Страница 1 из 1

Ассинхронная работа COM порта под XP

Добавлено: 20 окт 2005, 15:01
vdg
Есть интересная проблема, которую не могу решить, нужна помощь. Дело в следующем. Есть проект (исходник) простейшей ассинхронной терминалки под MFC из книги "Visual C++ и MFC" Мешкова и Тихомирова 2 издание. Работает безукоризненно. Я решил подчистить код от MFC, перенести всё под WinAPI. Для надёжности всё отладил в том же проекте терминалки, а потом просто вынес код в новое чистое консольное приложение. Так вот этот код не пошёл. WaitCommEvent работает нормально, но ReadFile не считывает пришедшие байты. Я сократил алгоритм, поместил в одну функцию только инициализацию порта и приём байта. Поставил эту функцию в обработчик "тестовой" кнопки на диалоге. Посмотрел отладчиком, всё идеально работает. Поместил это код в консоль - не работает (ReadFile возвращает FALSE - см. код ниже). Создал чистое Win32 приложение - результат аналогичен. Сделал визардом MFC диалог (такой же как и работающая терминалка) - опять та жа ахинея. Проверил какие библиотеки подключены в "терминалке", вдруг чего у меня недостаёт - нет, всё тоже самое. Посмотрел отличия в настройках проекта, сделал всё идентичное - результата не дало. :(
В общем, я упёрся и не знаю что делать. Перерыл инет, такой проблемы у других не нашёл, зато нашёл ещё более ненормальные случаи. Так что последний вариант спросить здесь, может найдётся специалист. Буду рад работающему под XP исходнику на WinAPI. Мой код ниже.
Спасибо.

********************************
В нормальном состоянии m_Quit, разумеется находится вовне. Его код инициализации я внёс сюда, чтобы не "портить" код потока.
o.hEvent в MSDN-е требуют делать с ручным сбросом, я так и сделал. Но в терминалке оно почему-то с автоматическим, и это никак не влияет на его нормальную работу.
Функцию InData вызывал как функцию потока, так и простым вызовом. Результат один: в проекте терминалки всё пучком, в моих проектах - нет.
********************************
DWORD InData(LPVOID lParam)
{
BYTE szBuffer[4096];

DWORD dwEvtMask;
DWORD dwError;
DWORD dwBytes;
COMSTAT csStat;


//=======================================
HANDLE m_hComm;

m_hComm = CreateFile("COM2",
GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//FILE_FLAG_OVERLAPPED

if (m_hComm == INVALID_HANDLE_VALUE)
return FALSE;

DCB dcb;

GetCommState(m_hComm, &dcb);
BuildCommDCB("baud=38400 parity=N data=8 stop=1", &dcb);
SetCommState(m_hComm, &dcb);

SetCommMask(m_hComm, EV_BREAK | EV_RXCHAR);
//=======================================
HANDLE m_Quit;
m_Quit = CreateEvent(NULL, TRUE, FALSE, NULL);
//=======================================


HANDLE event = m_Quit;

OVERLAPPED o;
o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

HANDLE Handles[] = { o.hEvent, event };

for (; ;)
{
ResetEvent(o.hEvent);

if (!WaitCommEvent(m_hComm, &dwEvtMask, &o))
{
if (WaitForMultipleObjects(2, Handles, FALSE, INFINITE) == WAIT_OBJECT_0+1)
break;
}

if (dwEvtMask & EV_BREAK)
{
break;
}
else if (dwEvtMask & EV_RXCHAR)
{
ClearCommError(m_hComm, &dwError, &csStat);

ResetEvent(o.hEvent);

if (!ReadFile(m_hComm, szBuffer,
csStat.cbInQue, &dwBytes, &o))
{// в неработающем приложении ReadFile возвращает FALSE и WaitForMultipleObjects ждёт до посинения

if (WaitForMultipleObjects(2, Handles, FALSE, INFINITE) == WAIT_OBJECT_0+1)
break;
}
// в работающем приложении ReadFile возвращает TRUE

for (UINT i = 0; i < csStat.cbInQue; i++)
{
// этот участок кода сделан, чтобы отладчик мог за него зацепиться (поставить точку остановки)
BYTE temp = 0;
temp = szBuffer;
}
}
}


CloseHandle(m_Quit);
//=======================================
CloseHandle(o.hEvent);
//=======================================
EscapeCommFunction(m_hComm, SETBREAK);

CloseHandle(m_hComm);
m_hComm = INVALID_HANDLE_VALUE;
//=======================================

return 0;
}
********************************