【发布时间】:2011-01-12 22:57:26
【问题描述】:
我的应用程序没有从 COM 端口正确接收数据。这曾经奏效。我不知道发生了什么。我知道正在通过线路发送/接收正确的数据,因为我可以在我的协议分析器上看到它。
PC 进入WAIT_OBJECT_0 + 1 状态,但缓冲区内容始终为零。我知道这很多,但如果有人能指出我做错了什么,我会非常感激。我可以根据要求添加/删除详细信息。谢谢。
编辑:附加信息
我已经能够验证 PC 拨打了ReadFileEx,并且它“成功”了。但是,PC 永远不会进入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 );
【问题讨论】:
-
你不应该像这样强制转换函数指针(除非你绝对确定它是一个好的强制转换)。您松散了函数签名检查。
-
我知道微软已经想出了各种混淆的方法来制作和强制转换指针,但最后一个指针是一个指针是一个指针,一个32位(或64位)表示内存位置地址的原子值。我确保在使用前将其放回原处;在这里(和其他地方)开始的线程可以正常工作。
-
@Jim Fell:每个函数(除了名称和参数)都有一个调用约定(如 _cdecl ,stdcall ,thiscall ),当您使用不同的调用约定转换为指针时,没有捕获该错误的方法。您很可能会遇到某种运行时错误,最终可能会花费数小时,有时甚至是一天才能找到错误。
-
只是为了简单的 rs232 通信?该代码正在乞求重写
-
您几乎从不检查您正在调用的函数的结果,还是因为您清理了代码以便更轻松地发布?
标签: c++ serial-port serial-communication overlapped-io