Мое приложение неправильно получает данные от COM-порта. Это раньше работало. Я не знаю, что случилось. Я знаю, что правильные данные отправляются / принимаются по линии, потому что я вижу их на своем анализаторе протоколов.
ПК переходит в состояние WAIT_OBJECT_0 + 1
, но содержимое буфера всегда равно нулю. Я знаю, что это много, но если кто-то может указать, что я делаю неправильно, я был бы очень признателен. Я могу добавить / удалить детали в соответствии с просьбой. Спасибо.
РЕДАКТИРОВАТЬ: Дополнительная информация
Мне удалось проверить, что ПК выполняет вызов ReadFileEx
, и он "успешно". Тем не менее, компьютер никогда не попадает в FileIOCompletionRoutine
. Есть идеи? (Я удалил обработку ошибок из кода, чтобы упростить жизнь.) Кроме того, из того, что я прочитал на сайте MSDN, похоже, что FileIOCompletionRoutine
будет вызываться асинхронно в своем собственном потоке. Это верно? Спасибо.
РЕДАКТИРОВАТЬ: окончательное решение
Это то, что я придумал. Очевидно, что код инициализации и обработки ошибок не здесь. Мы не можем сделать вещи слишком легкими. :)
// Load event handles.
pHandles[0] = s_hSerialPortRxThreadExitEvent;
// OVERLAPPED structure event handle is loaded in loop.
while ( blContinue )
{
// Wait for a communications event.
if ( !::WaitCommEvent( s_hSerialPort, &dwEventMask, &s_ov ) )
{
if ( ::GetLastError() != ERROR_IO_PENDING )
{
blContinue = FALSE;
continue;
}
else if ( ::WaitForSingleObject( pHandles[0], 0 ) == WAIT_OBJECT_0 )
{
// The thread-exit event has been signaled. Get out of here.
blContinue = FALSE;
continue;
}
}
else
{
// Load OVERLAPPED structure event handle.
pHandles[1] = s_ov.hEvent;
}
if ( dwEventMask & EV_RXCHAR )
{
if ( !::ReadFile( s_hSerialPort, pBuf, RX_BUF_SIZE, NULL, &s_ov ) )
{
if ( ::GetLastError() == ERROR_IO_PENDING )
{
// Wait for events.
dwObjectWaitState = ::WaitForMultipleObjects( 2, pHandles, FALSE, INFINITE );
// Switch on event.
switch ( dwObjectWaitState )
{
case WAIT_OBJECT_0: // thread exit event signaled
blContinue = FALSE;
continue;
case WAIT_OBJECT_0 + 1: // OVERLAPPED structure event signalled
// Reset event first to mitigate underrun condition.
if ( !::ResetEvent( pHandles[1] ) )
{
blContinue = FALSE;
continue;
}
// Get the OVERLAPPED result.
if ( !::GetOverlappedResult( s_hSerialPort, &s_ov, &dwBytesRead, FALSE ) )
{
blContinue = FALSE;
continue;
}
break;
default: // Error
blContinue = FALSE;
continue;
}
}
}
else if ( !::GetOverlappedResult( s_hSerialPort, &s_ov, &dwBytesRead, FALSE ) )
{
blContinue = FALSE;
continue;
}
// If bytes were read...
if ( dwBytesRead > 0 )
{
// Copy received data from local buffer to thread-safe serial port buffer.
::EnterCriticalSection( &s_csRxRingBuffer );
blSuccess = s_pobjRxRingBuffer->Add( pBuf, dwBytesRead, TRUE );
::LeaveCriticalSection( &s_csRxRingBuffer );
if ( !blSuccess )
{
blContinue = FALSE;
continue;
}
// Set the received data event.
if ( !::SetEvent( s_phEventIds[RECEIVE_EVENT] ) )
{
blContinue = FALSE;
continue;
}
}
}
if ( dwEventMask & EV_TXEMPTY )
{
// Set the transmit complete event.
if ( !::SetEvent( s_phEventIds[TRANSMIT_EVENT] ) )
{
blContinue = FALSE;
continue;
}
}
} // end while ( blContinue );