📄 serialcomm.cpp
字号:
if( pPort == NULL )
return FALSE;
BOOL successed = pPort->GetOverlappedResult( m_BreakOverlapped, dwReadBytes, FALSE );
if( successed )
{
m_pPortComm->OnComBreak(dwMask); // 调用处理过程
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------------------------
// 根据读写模式,执行线程
//---------------------------------------------------------------------------------------
void CSerialReadThread::Execute()
{
switch( m_pPortComm->GetReceiveMode() )
{
case ManualReceiveByQuery:
ExecuteByManualQueryRecvMode();
break;
case ManualReceiveByConst:
ExecuteByManualConstRecvMode();
break;
case AutoReceiveBySignal:
ExecuteByAutoSignalRecvMode();
break;
default:
// 中断模式
ExecuteByAutoBreakRecvMode();
}
}
//---------------------------------------------------------------------------------------
// 常用方式1:串口收到数据后自动通知主线程
//---------------------------------------------------------------------------------------
void CSerialReadThread::ExecuteByAutoSignalRecvMode()
{
DWORD dwMask = 0;
HANDLE WaitHandles[3]; // 监听事件数组
DWORD dwSignaledHandle;
// 第一个信号量为线程结束运行的通知
// 第二个信号量读取重叠操作,串口收到数据后的通知
// 第三个信号量中断重叠操作
WaitHandles[0] = m_pPortComm->GetCloseHandle();
WaitHandles[1] = m_ReadOverlapped.hEvent;
WaitHandles[2] = m_BreakOverlapped.hEvent;
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
goto EndThread;
pPort->SetMask( EV_ERR | EV_RLSD | EV_RING );
if( !SetBreakEvent(dwMask) )
goto EndThread;
// 设置读事件
if( !SetReadEvent(m_ReadOverlapped) )
goto EndThread;
// 设置ComEvent
for(;;)
{
dwSignaledHandle = ::WaitForMultipleObjects( 3, WaitHandles, FALSE, INFINITE );
switch(dwSignaledHandle)
{
case WAIT_OBJECT_0:
goto EndThread;
break;
case WAIT_OBJECT_0+1:
if( !HandleReadEvent(m_ReadOverlapped) )
goto EndThread;
if( !SetReadEvent(m_ReadOverlapped) )
goto EndThread;
break;
case WAIT_OBJECT_0+2:
if( !HandleBreakEvent(dwMask) )
goto EndThread;
if( !SetBreakEvent(dwMask) )
goto EndThread;
break;
default:
// goto EndThread;
break;
}
}
EndThread:
pPort->Purge( PURGE_RXABORT | PURGE_RXCLEAR );
::CloseHandle( m_ReadOverlapped.hEvent );
::CloseHandle( m_BreakOverlapped.hEvent );
}
//---------------------------------------------------------------------------------------
// 常用方式2:主线程在需要数据时主动查询串口是否已收到数据
//---------------------------------------------------------------------------------------
void CSerialReadThread::ExecuteByManualQueryRecvMode()
{
DWORD dwMask = 0;
HANDLE WaitHandles[2]; // 监听事件数组
DWORD dwSignaledHandle;
// 第一个信号量为线程结束运行的通知
// 第二个信号量无
// 第三个信号量无
WaitHandles[0] = m_pPortComm->GetCloseHandle();
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
goto EndThread;
pPort->SetMask( EV_ERR | EV_RLSD | EV_RING );
pPort->SetBreak();
for(;;)
{
dwSignaledHandle = ::WaitForMultipleObjects(1, WaitHandles, FALSE, INFINITE);
switch( dwSignaledHandle )
{
case WAIT_OBJECT_0:
goto EndThread;
break;
default:
// goto EndThread;
break;
}
pPort->GetMask(dwMask);
if( dwMask > 0 )
m_pPortComm->OnComBreak(dwMask);
}
EndThread:
pPort->Purge(PURGE_RXABORT | PURGE_RXCLEAR);
}
void CSerialReadThread::ExecuteByManualConstRecvMode()
{
DWORD dwMask = 0;
HANDLE WaitHandles[2]; // 监听事件数组
DWORD dwSignaledHandle;
// 第一个信号量为线程结束运行的通知
// 第二个信号量中断重叠操作
// 第三个信号量无
WaitHandles[0] = m_pPortComm->GetCloseHandle();
WaitHandles[1] = m_BreakOverlapped.hEvent;
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
goto EndThread;
pPort->SetMask( EV_ERR | EV_RLSD | EV_RING );
if( !SetBreakEvent(dwMask) )
goto EndThread;
// 设置 ComEvent
for(;;)
{
dwSignaledHandle = ::WaitForMultipleObjects( 2, WaitHandles, FALSE, INFINITE );
switch( dwSignaledHandle )
{
case WAIT_OBJECT_0:
goto EndThread;
break;
case WAIT_OBJECT_0+1:
if( !HandleBreakEvent(dwMask) )
goto EndThread;
if( !SetBreakEvent(dwMask) )
goto EndThread;
break;
default:
// goto EndThread;
break;
}
}
EndThread:
pPort->Purge( PURGE_RXABORT | PURGE_RXCLEAR );
::CloseHandle( m_ReadOverlapped.hEvent );
::CloseHandle( m_BreakOverlapped.hEvent );
}
void CSerialReadThread::ExecuteByAutoBreakRecvMode()
{
DWORD dwMask = 0;
HANDLE WaitHandles[2]; // 监听事件数组
DWORD dwSignaledHandle;
// 第一个信号量为线程结束运行的通知
// 第二个信号量中断重叠操作
// 第三个信号量无
WaitHandles[0] = m_pPortComm->GetCloseHandle();
WaitHandles[1] = m_BreakOverlapped.hEvent;
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
goto EndThread;
pPort->SetMask(EV_ERR | EV_RLSD | EV_RING | EV_RXCHAR);
if( !SetBreakEvent(dwMask) )
goto EndThread;
// 设置读事件
if( !SetReadEvent(m_BreakOverlapped) )
goto EndThread;
// 设置 ComEvent
for(;;)
{
dwSignaledHandle = ::WaitForMultipleObjects( 2, WaitHandles, FALSE, INFINITE );
switch( dwSignaledHandle )
{
case WAIT_OBJECT_0:
goto EndThread;
break;
case WAIT_OBJECT_0+1:
if( (dwMask & EV_RXCHAR) == EV_RXCHAR )
{
if( !HandleReadEvent(m_BreakOverlapped) )
goto EndThread;
if( !SetReadEvent(m_BreakOverlapped) )
goto EndThread;
}
else
{
if( !HandleBreakEvent(dwMask) )
goto EndThread;
if( !SetBreakEvent(dwMask) )
goto EndThread;
}
break;
default:
// goto EndThread;
break;
}
}
EndThread:
pPort->Purge(PURGE_RXABORT | PURGE_RXCLEAR);
::CloseHandle( m_ReadOverlapped.hEvent );
::CloseHandle( m_BreakOverlapped.hEvent );
}
static DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
CSerialReadThread* pThread = (CSerialReadThread*)lpParam;
ASSERT(pThread);
pThread->m_IsTerminated = FALSE;
pThread->Execute();
pThread->m_IsTerminated = TRUE;
return 0;
}
void CSerialReadThread::Create()
{
m_hThread = CreateThread( NULL, // no security attributes
0, // use default stack size
ThreadFunc, // thread function
this, // argument to thread function
CREATE_SUSPENDED, // use default creation flags
&dwThreadId ); // returns the thread identifier
// ::SetThreadPriority( m_hThread, THREAD_PRIORITY_HIGHEST );
::SetThreadPriority( m_hThread, THREAD_PRIORITY_NORMAL );
}
void CSerialReadThread::Terminate()
{
if (m_hThread == NULL)
{
TRACE( _T("CreateThread failed.") );
}
else
{
if( !IsTerminated() )
{
if( WaitForSingleObject(m_hThread, 1000) != WAIT_OBJECT_0 )
{ // 先等 1 秒,仍没有结束,强制结束
::TerminateThread( m_hThread, 0 );
}
}
CloseHandle( m_hThread );
}
}
void CSerialReadThread::Resume()
{
ResumeThread( m_hThread );
}
void CSerialReadThread::BandSerialPort(CSerialComm* pPort)
{
ASSERT(pPort);
m_pPortComm = pPort;
// 创建异步读取事件
if( m_pPortComm->IsOverlapped() )
{
m_ReadOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT( m_ReadOverlapped.hEvent );
m_BreakOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE,NULL);
ASSERT( m_BreakOverlapped.hEvent );
}
}
DWORD CSerialReadThread::ReadInput(void* pBuf, DWORD Count, DWORD dwMilliseconds)
{
DWORD dwRead = 0;
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
return 0;
// 正在等待
if( !pPort->Read(pBuf, Count, m_ReadOverlapped, &dwRead) )
{
// 等待,直到有数据或超时
if( WaitForSingleObject(m_ReadOverlapped.hEvent, dwMilliseconds) == WAIT_OBJECT_0 )
pPort->GetOverlappedResult( m_ReadOverlapped, dwRead, FALSE );
}
return dwRead;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -