Re: Comm-port reader
От: lyudmil_selin Болгария  
Дата: 03.09.03 09:58
Оценка:
Здравствуйте, Mag, Вы писали:

Mag>Помогите с чтением из com-порта. Вот тривиальная задача.

Mag>Создаётся отдельный поток. Он выполняет следующие действия.
Mag>1. Открыть com-порт (CreateFile... — здесь всё просто).
Mag>2. Настроили порт, как надо (тут тоже не проблема).

Mag>Цикл:

Mag>3. Организуем ожидание события принятия байта из com-порта. Вот тут ключевая проблема. Должно быть что-то с WaitForSingleObject, WaitCommEvent или что-то ещё.
Mag>4. По принятию байта помещаем его в массив.

Mag>5. Закрываем com-порт.


Mag>Хитрость задачи состоит в том, что количество принимаемых байт не определено. Т.е. процесс приёма непрерывен: есть что-то — принимаем. Может есть у кого реально работающий кусок кода, реализующий поставленную задачу. Буду премного благодарен.


Я из Болгарии; с русской киррилице у меня не совсем в порядке, некоторие букви нету, но надеюсь и так поймете:
1; тред приема — должна бит глобальная в приложении и поставь в коде перед ее визовом
//------------------------------------------------------------------------
static HANDLE hRxThread;
FILE *hf;

DWORD WINAPI RxThread(LPVOID dl)
{
CEsaDlg *cpdlg=(CEsaDlg *)dl;
HANDLE hComm = cpdlg->hComm;

DWORD dResult=1;
DWORD dBytes;
DWORD dNumberOfBytes;
unsigned char Buffer[100];
BOOL bSuccess;

while (cpdlg->nThr_cmd)
{
Sleep (1);

dNumberOfBytes=21;
bSuccess=ReadFile (hComm, Buffer, dNumberOfBytes, &dBytes, NULL);
if (!bSuccess) continue;

if (dBytes)
{
cpdlg->ReceiveData (Buffer, (int)dBytes);
}
}
return dResult;
}
//----------------------------------------------------------------------
dNumberOfBytes — количество байтов, которие принимаешь, лучше принимай по одному если пакети произвольной длини
*cpdlg — указатель, необходим для доступа к функциям и переменним класса /он у меня називается CEsaDlg/
ReceiveData (Buffer, (int)dBytes) — член-функция класса, где обрабативаесх принйатие байти

ниже инициализация порта

//------------------------------------------------------------------------
int CEsaDlg::InitComPort(int nPort)
{
char port[10]="COM";
char Digit[2];
COMMTIMEOUTS to;
DCB dcb;
DWORD dThreadID;

itoa (nPort,Digit,10);
strcat (port,Digit);

hComm = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

if (hComm == INVALID_HANDLE_VALUE)
{
return 1;
}

to.ReadIntervalTimeout = 1;
to.ReadTotalTimeoutMultiplier = 1;
to.ReadTotalTimeoutConstant = 1;

to.WriteTotalTimeoutMultiplier = 1;
to.WriteTotalTimeoutConstant = 1;
SetCommTimeouts(hComm, &to);

GetCommState(hComm, &dcb);

dcb.fParity = FALSE;
dcb.BaudRate = 57600;
//dcb.BaudRate = 115200;
//dcb.BaudRate = 256000;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fBinary = TRUE;

SetCommState(hComm, &dcb);

nThr_cmd = 1; // enable trhead

hRxThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)RxThread,(LPVOID)this,0,&dThreadID);
return 0;
}
//----------------------------------------------------------------------

ниже функция обработки принятих байтов
//------------------------------------------------------------------------
void CEsaDlg::ReceiveData(unsigned char *Buffer, int Bytes)
{
// код напиши сам
}

ниже функция закрития порта, необходимо когда надо открить другой порт не закривая приложение
//------------------------------------------------------------------------
void CEsaDlg::CloseComPort()
{
if (hComm != INVALID_HANDLE_VALUE)
{
nThr_cmd = 0; // disable thread
PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
WaitForSingleObject(RxThread, INFINITE);
CloseHandle(hComm);
CloseHandle(RxThread);
}
}
//------------------------------------------------------------------------

у меня ето работает отлично;
если проблеми — пиши — lyudmil_selin@yahoo.com
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.