Программирование COM порта в Win XP ?
Есть проблемы по работе в Win XP с COM портом в асинхронном режиме, и еще проблема со вторым потоком. Где размещать функцию записи и функцию чтения, в каком потоке размещать код инициализации порта? Дайте пожалуйста ссылку где можно почитать про программирование порта средствами Win32 API в асинхронном режиме.
Есть проблемы по работе в Win XP с COM портом в асинхронном режиме, и еще проблема со вторым потоком. Где размещать функцию записи и функцию чтения, в каком потоке размещать код инициализации порта? Дайте пожалуйста ссылку где можно почитать про программирование порта средствами Win32 API в асинхронном режиме.
Разделять потоки при работе с портом имеет смысл только в том случае если работаем с устройством которое само по своей инициативе передает данные. Это может быть в программе подчиненного устройства или в осциллографах , кардиографах и т п. Отдельно еще стоит класс задач отображения принятой информации от приборов в SCADA системах.
Инициализацию лучше всего делать в основном потоке.
Запись и чтение могут быть как в одном потоке (основном или вспомогательном), так и в разных. В этом случает запись надо сделать по какому либо событию (кнопка или таймер), а прием вести в другом потоке по флагу что что-то передали.
В том случае если решитесь разносить прием и передачу по потокам надо аккуратно перед передачей очистит буферы приема и передачи, потом передать то что хотим и ждать ответ.
В том случае, если у вас работа идет по принципу : запрос ответ, и время ожидания ответа небольшое, не имеет смысла связываться с асинхронным приемом и разными потоками, все можно сделать в одном потоке синхронно двумя функциями Write и ReadFile и при этом приключений будет меньше.
Помогите пожалуйста разобраться почему у меня функция WaitCommEvent всегда возвращает ноль ?
Инициализация порта:
{
DCB dcb;
COMMTIMEOUTS MyTimeouts;
ZeroMemory(&dcb, sizeof(DCB));
ZeroMemory(&MyTimeouts, sizeof(COMMTIMEOUTS));
//-------------------------------------------------------
//-------------------------------------------------------
hCom_1 = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if(hCom_1 == INVALID_HANDLE_VALUE) // если порт не удалось открыть
{
return 0;
}
//-------------------------------------------------------
if(!GetCommState(hCom_1, &dcb))
{
CloseHandle(hCom_1);
return 0;
}
if(!GetCommTimeouts(hCom_1,&MyTimeouts))
{
CloseHandle(hCom_1);
return 0;
}
//-------------------------------------------------------
dcb.BaudRate = CBR_1200; // скорость передачи
//dcb.fBinary = TRUE; // бинарный режим работы
dcb.fParity = FALSE; // контроль четности запрещен
dcb.ByteSize = 8; // размер байта данных
dcb.StopBits = ONESTOPBIT; // один стоповый бит
//dcb.Parity = NOPARITY; // контроля четности нет
dcb.fNull = FALSE; // принимать нулевые байты
//-------------------------------------------------------
//dcb.fDtrControl = DTR_CONTROL_ENABLE;
//dcb.fRtsControl = RTS_CONTROL_TOGGLE;
//dcb.fDsrSensitivity = 0;
//dcb.fOutxCtsFlow = 0;
//dcb.fOutxDsrFlow = 0;
//-------------------------------------------------------
MyTimeouts.ReadIntervalTimeout=15;
MyTimeouts.ReadTotalTimeoutMultiplier=1;
MyTimeouts.ReadTotalTimeoutConstant=250;
MyTimeouts.WriteTotalTimeoutMultiplier=1;
MyTimeouts.WriteTotalTimeoutConstant=250;
//-------------------------------------------------------
if(!SetCommState(hCom_1, &dcb))
{
CloseHandle(hCom_1);
return 0;
}
if(!SetCommTimeouts(hCom_1,&MyTimeouts))
{
CloseHandle(hCom_1);
return 0;
}
return 1;
}
Функция чтения:
bool __fastcall ThreadCom::ReadPort(char *lpBuf, DWORD dwReadBytes)
{
//-------------------------------------------------------------------------
memset(&RD_OL, 0, sizeof(RD_OL));
memset(&EV_OL, 0, sizeof(EV_OL));
SetCommMask(hCom_1, EV_RXCHAR);
RD_OL.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
EV_OL.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
//-------------------------------------------------------------------------
if((RD_OL.hEvent == NULL)||(EV_OL.hEvent == NULL))
{
CloseHandle(hCom_1);
return false;
}
//-------------------------------------------------------------------------
if(WaitCommEvent(hCom_1, &dwCommEv, &EV_OL) == 0)// ждем события порта
{
CloseHandle(hCom_1);
return false;
}
WFSO = WaitForSingleObject(EV_OL.hEvent, INFINITE);
if(WFSO == WAIT_OBJECT_0)
{
if(!ReadFile(hCom_1, lpBuf, dwReadBytes, &dwRead, &RD_OL))
{
Form1->ListBox1->Items->Append("Ошибка чтения из порта");
CloseHandle(hCom_1);
return false;
}
WFSO1 = WaitForSingleObject(RD_OL.hEvent, INFINITE);
if(WFSO1 == WAIT_OBJECT_0)// обьект перешол в сигнальное состояние
{
if(!GetOverlappedResult(hCom_1, &RD_OL, 0, FALSE))
{
Form1->ListBox1->Items->Append("Результат чтения не получен!");
CloseHandle(hCom_1);
return false;
}
}
}
ReturnReadBytes(dwRead);
CloseHandle(RD_OL.hEvent);
CloseHandle(EV_OL.hEvent);
return true;
}
//---------------------------------------------------------------------------
MyTimeouts.ReadTotalTimeoutConstant=250;
у вас внешнее устройство успевает ответить за 250 миллисекунд с момента передачи хоть что-нибудь? Если неясно , то поставьте здесь скажем 10000 и попробуйте в течении 10 секунд что-то ответить.