我的应用程序没有正确地从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 );
答案 0 :(得分:1)
另外,根据我在MSDN上阅读的内容 网站,它看起来像 FileIOCompletionRoutine将获得 在它自己的异步调用 线。这是对的吗?
不,这不正确。完成例程在调用ReadFileEx的线程的上下文中调用。当它准备好运行时,它会排队,直到线程处于“可警告的等待状态”。当您调用Wait *函数之一时,通常会发生这种情况。此外,从ReadFileEx的MSDN,它声明:
ReadFileEx函数忽略了 OVERLAPPED结构的hEvent成员。 应用程序可以免费使用 成员为了自己的目的 ReadFileEx调用的上下文。 ReadFileEx标志着它的完成 通过呼叫或排队来读取操作 调用完成例程 由lpCompletionRoutine指向,所以 它不需要事件句柄。
因此,您创建的事件无效。此外,在调用ReadFileEx之前不会处理读取,因此您必须在等待时撤消订单。你在阅读循环中应该做的是这样的(在伪代码中):
while(continue)
{
ReadFileEx();
WaitForSingleObject(s_hSerialPortRxThreadExitEvent);
. . . etc . . .
}
答案 1 :(得分:1)
我不知道我是否看到你的代码错了,但我看到你正在设置事件,等待事件而不告诉O / S你还在等什么,你应该先做ReadFileEx()当缓冲区中的数据要读取时,告诉O / S你正在等待事件,然后你做了WFSO()/ WFMO(),这就是我在我的串口库(在接收器线程上)做的事情:
do
{
byteRead = 0;
readBuffer = 0;
if(!::ReadFile(this->commHandle,&readBuffer,
1,NULL,&this->readOverlapIO))
{
if(GetLastError() == ERROR_IO_PENDING)
{
if(::WaitForSingleObject(this->readOverlapIO.hEvent,INFINITE) == WAIT_OBJECT_0)
{
if(!::GetOverlappedResult(this->commHandle,&this->readOverlapIO,&byteRead,FALSE))
{
byteRead = 0;
}
}
}
}
else
{
if(!::GetOverlappedResult(this->commHandle,&this->readOverlapIO,&byteRead,FALSE))
{
byteRead = 0;
}
}
if(byteRead > 0)
{
totalByteRead += this->ringBuffer.push(readBuffer,1);
}
}while(byteRead);
我在这里使用事件信号使用完成事件,如果你愿意,可以将它改为完成功能。
答案 2 :(得分:0)
如果您确定已收到某些内容(应该),则可能是& dwWritten的双重用法。尝试使用两个单独的变量(一个用于ReadFile,另一个用于GetOverlappedResult)。 当然要检查它们。
另外,您是否已将完整重叠结构初始化为0(beffore将事件分配给它)?