Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как сделать чтение из COM  (Прочитано 9244 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
volkov75
Гость
« : 04-05-2007 09:26 » 

Помогите, пожалуйста, у меня задача сделать класс чтение и записи в COM порт?

Я сегодня открыл COM порт, как сказано в книге и послал в порт значение, у меня вопрос как объединить ожидание чтения информации и записи, а то у меня в программе два потока и я зависаю на ожидании символа из порта. Исходники я могу выложить на forum
« Последнее редактирование: 04-05-2007 16:24 от volkov75 » Записан
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #1 : 04-05-2007 14:15 » 

Почему не сразу так? Ага

Так я не понял - у тебя проблема с синхронизацией тредов или чтения-записи СОМ?
Зачем ты вобще треды сделал? Ты ведь всё-равно не сможешь одновременно читать и писать из/в порт.
Обычно делается цикл на опрашивание порта - для этого можно например установить необходимый TimeOut с помощью SetCommState. Тк когда ты хочешь отправить данные ты знаешь, и в этот момент никакого приёма всё-равно не будет.

Мне видится простенький цикл типа

Код:
повторять до упора
{

ReadFile(... &dwRead... )
if(dwRead>0)
{
   // обрабатываем полученные данные
}
else
{
      if( HasDataToSendToPort )
     {
           WriteFile(...)
     }
}
}

Ну а этот цикл уже запустить в треде, чтобы удобней было управлять из основной проги.

Если тебе известен протокол обмена данными, то тогда можно чтение для проверки не делать, а опрашивать только управляющие сигналы.

Ну и для лучшего разбора полётов - исходники в студию.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 04-05-2007 14:44 » 

Ты ведь всё-равно не сможешь одновременно читать и писать из/в порт.
тихо так в сторону, это почему же?
Порт асинхронный? RXD и TXD разнесены
это не 485..  это RS232
« Последнее редактирование: 04-05-2007 14:50 от Sla » Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 04-05-2007 14:56 » 

Sla, а почему тихо и в сторону? Ага  Cогласен. Но это уже будет зависеть от протокола. А если пользоваться Read-/WriteFile тогда как? Хотя сначала надо посмотреть какие он параметры в CreateFile передаёт.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
volkov75
Гость
« Ответ #4 : 04-05-2007 16:30 » 

Параметры
Код:
hCom = CreateFile(NameCOM,GENERIC_READ | GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

Я понимаю,
Зачем ты вобще треды сделал? Ты ведь всё-равно не сможешь одновременно читать и писать из/в порт.
Что бы один поток читал другой записывал. Так было организовано в Delphi работа с COM портом.

Пример класса работы с COM
Код:
#include "stdafx.h"
#include "SerPort.h"
#include <shlwapi.h>


HANDLE hCom;
OVERLAPPED ovl;
UINT ThreadProc(LPVOID param);
bool bThreadstop;

ComPortWin::ComPortWin()
{
hCom = NULL;
NameCOM = "COM1";
ovl.Internal = 0;
ovl.InternalHigh = 0;
ovl.Offset = 0;
ovl.OffsetHigh = 0;
ovl.Pointer = 0;
}
ComPortWin::~ComPortWin()
{

}
void ComPortWin::GetSerPorts(CArray<CString>* arCOM)
{
HKEY hKey;
long Err;
int i = 0;
WCHAR  szData[80];
CString strTemp;
DWORD ErrV,dwType,cbData;
 
  Err = RegOpenKey(HKEY_LOCAL_MACHINE,_T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),&hKey);
  if (Err == ERROR_SUCCESS)
  { 
  arCOM->RemoveAll();
  while(1)
  {
  strTemp.Format(_T("\\Device\\Serial%d"),i);
  ErrV = ::SHGetValue(hKey,_T(""),strTemp,&dwType,&szData,&cbData);
  if (ErrV == ERROR_SUCCESS)
  {
  strTemp = szData;
  arCOM->Add(strTemp);
  }
  else
  {
  if (i > 100) break;
  }
  i++;
  }
  }
RegCloseKey(hKey);
}
bool ComPortWin::Open(CString _NameCOM)
{
NameCOM = _NameCOM;
try
{
hCom = CreateFile(NameCOM,
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hCom == INVALID_HANDLE_VALUE)
{
throw 0;
}
}
catch(...)
{
return false;
}
  return true;
}
bool ComPortWin::Open(int nCom)
{
  NameCOM.Format(_T("COM%d"),nCom);
return Open(NameCOM);
}
bool ComPortWin::SetParamWND(HWND hWnd)
{
    try
    {
        if(!GetCommState(hCom,&dcb)) throw 0;
COMMCONFIG CC;
        memcpy(&(CC.dcb),&dcb,sizeof(dcb));
        if(!CommConfigDialog(NameCOM,hWnd,&CC)) throw 1;
        memcpy(&dcb,&(CC.dcb),sizeof(dcb));
        if(!SetCommState(hCom,&dcb))  throw 2;
   }
    catch(...)
    {
        return false;
    }
    return true;
}
bool ComPortWin::GetStatus(LPDCB lpDCB)
{
    try
    {
        if(!GetCommState(hCom,&dcb)) throw 0;
}
    catch(...)
    {
        return false;
    }
    return true;
}
bool ComPortWin::SetStatus(DCB dcb)
{
    try
    {
        if(!SetCommState(hCom,&dcb)) throw 0;
}
    catch(...)
    {
        return false;
    }
    return true;
}
bool ComPortWin::SetStatus(CString s_BuildCommDCB)
{
FillMemory(&dcb,sizeof(dcb),0);
dcb.DCBlength = sizeof(dcb);
if (!BuildCommDCB(s_BuildCommDCB,&dcb))
{
return FALSE;
}
return TRUE;
}
void  ComPortWin::Close()
{
try
{
if(hCom != NULL) { CloseHandle(hCom); hCom = NULL; }
}
catch(...) {}
}
bool ComPortWin::Write(LPCVOID pBuffer,unsigned int nBytes)
{
    try
    {
        unsigned long dwNumBytesWritten;
WriteFile(hCom,pBuffer,nBytes,&dwNumBytesWritten,NULL);
// WriteFile(hCom,pBuffer,nBytes,&dwNumBytesWritten,&ovl);
}
    catch(...)
    {
        return false;
    }
    return true;
}
BOOL ComPortWin::Purge()
{
BOOL Tx,Rx;
Tx = PurgeComm(hCom,PURGE_TXCLEAR);
Rx = PurgeComm(hCom,PURGE_RXCLEAR);
return (Tx && Rx);
}
BOOL ComPortWin::Flush()
{
return FlushFileBuffers(hCom);
}

bool ComPortWin::Read(LPVOID pBuffer,unsigned int nBytes)
{
    try
    {
        DWORD dwBytesTransferred;
ReadFile (hCom,pBuffer,nBytes,&dwBytesTransferred,NULL);
// ReadFile (hCom,pc,1,&dwBytesTransferred,&ovl);
    }
    catch(...)
    {
        return false;
    }
    return true;
}
bool ComPortWin::Nastr()
{
  try
  {
GetStatus(&dcb);
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.Parity = ODDPARITY;
dcb.StopBits = TWOSTOPBITS;
SetStatus(dcb);

GetCommTimeouts(hCom,&CommTimeouts);
CommTimeouts.ReadIntervalTimeout = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.WriteTotalTimeoutConstant = 0;
CommTimeouts.WriteTotalTimeoutMultiplier = 0;
SetCommTimeouts(hCom,&CommTimeouts);

// SetCommMask(hCom,EV_RXCHAR);
// ovl.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
  }
  catch(...)
  {
    return false;
  }
  return true;
}
//Создание потоковой функции
UINT ThreadProc(LPVOID param)
{
BYTE Buffer[1];
DWORD dwBytesTransferred;

while(!bThreadstop)
{
ReadFile (hCom,Buffer,sizeof(Buffer),&dwBytesTransferred,NULL);
if (dwBytesTransferred) MessageBox(NULL,_T(""),_T(""),MB_OK);
MessageBeep(10);
Sleep(50);
}
/*
bool bRead;
DWORD dwEvtMask;
unsigned char pc;
HANDLE Handle;
OVERLAPPED o;

Handle = m_ComPort.GetHandle();
o = m_ComPort.GetOverlapped();
while(!bThreadstop)
{
if (WaitCommEvent(Handle,&dwEvtMask,&o))
{
if (dwEvtMask & EV_RXCHAR)
{
m_ComPort.GetChar(&pc);
if (pc == '0') {MessageBox(NULL,strTemp,_T(""),MB_OK); strTemp=""; }
else strTemp += pc;

}
Sleep(50);
}
}
*/
MessageBox(NULL,_T("Поток закрыт"),_T(""),MB_OK);
return 0;
}

Пример работы
Код:
void CProbaDlg::OnBnClickedButton1()
{
m_ComPort.Open(1);
m_ComPort.Nastr();
m_ComPort.SetParamWND(this->m_hWnd);

//Запуск потока
bThreadstop = false;
Thread1 = AfxBeginThread(ThreadProc,NULL);
}

void CProbaDlg::OnBnClickedButton2()
{
bThreadstop = true;
m_ComPort.Close();
}
« Последнее редактирование: 04-05-2007 16:33 от volkov75 » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines