Контроль COM порта (serial) в WINAPI
Не могу найти механизм или функцию мониторинга состояния COM порта в windows, используя WINAPI.
Приходится разбираться в нативных функциях, не используя boost и им подобные библиотеки.
Проблема следующая: написал функцию открытия serial, на другом конце arduino(с ней проблемы нет).
В целом всё работает нормально при многократных запусках, но если выскакивает ошибка, то arduino продолжает слать данные в порт. для того чтобы вернуть arduino в режим ожидания, надо послать в порт 0xF0.
С этим куском всё в порядке. Теперь о проблеме:
Если воспользоваться сторонним терминалом и отправлять туда данные, то закрыв соединение и вернувшись к своей программе , я не могу прочитать что либо из порта, хотя все функции инициализации проходят успешно. Если подождать неопределённое время, то всё начинает работать как было.
Соответственно структуры в примере statusSerial, statusError, dcbSerialParams, ctSerialParams - не вызывают нареканий и отображают верные данные. Сама функция из примера полностью отрабатывает без ошибок, а вот дальше прочесть из порта ничего не удаётся. Что я упустил из виду?
#include <stdio.h> // printf
#include <Windows.h>
// обработчик com порта
HANDLE hSerial;
//структура состояния порта
COMSTAT statusSerial;
DWORD statusError;
int mpc_init(LPCTSTR sPortName)
{
hSerial = CreateFile(sPortName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0
);
if (hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf("serial port does not exist.\n");
}
else printf("some other error occurred.\n");
exit(-1);
}
// структура содержащая настройки com порта
DCB dcbSerialParams = { 0 };
COMMTIMEOUTS ctSerialParams = { 0 };
// задаём размер структуры
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
// читаем текущие настройки и заполняем структуру
if (!GetCommState(hSerial, &dcbSerialParams))
{
printf("getting state error\n");
}
if (!GetCommTimeouts(hSerial, &ctSerialParams))
{
printf("getting state error\n");
}
if (!BuildCommDCBAndTimeouts(L"baud=500000 parity=N data=8 stop=1 TO=OFF", &dcbSerialParams, &ctSerialParams))
{
printf("error setting serial port\n");
}
// применяем настройки к порту
if (!SetCommState(hSerial, &dcbSerialParams))
{
printf("error setting serial port state\n");
}
if (!SetCommTimeouts(hSerial, &ctSerialParams))
{
printf("error setting serial port state\n");
}
if (!SetupComm(hSerial, 1024, 1024))
{
printf("error buff serial port state\n");
}
if (!PurgeComm(hSerial, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT))
{
printf("error purge serial port state\n");
}
// жду для гарантированного применения настроек
Sleep(50);
// отправляем команду перехода в командный режим
bdm_port.TxBuffer[0] = 0xF0;
bdm_port.TxIter = 1;
portw();
// ждём пока adduino раздуплится
Sleep(50);
if (!ClearCommError(hSerial, &statusError, &statusSerial))
{
printf("error Status Port");
}
if (!PurgeComm(hSerial, PURGE_TXCLEAR | PURGE_RXCLEAR))
{
printf("error purge serial port state\n");
}
Sleep(50);
printf("Port open\n");
return 0;
}