📄 serialcomm.cpp
字号:
//=======================================================================================
// ComPort.cpp : 实现文件
//
//=======================================================================================
#include "stdafx.h"
#include "serialcomm.h"
//***************************************************************************************
// CSerialComm
//***************************************************************************************
CSerialComm::CSerialComm()
{
m_pfnOnReceiveData = NULL;
m_pfnOnComBreak =NULL;
m_pPort = NULL;
m_pReadThread = NULL;
::ZeroMemory( &m_WriteOverlapped, sizeof(m_WriteOverlapped) );
m_hWriteEvent = NULL;
}
CSerialComm::~CSerialComm()
{
if(m_pPort)
{
if(m_pPort->IsOpen())
Close();
}
delete m_pPort;
m_pPort = NULL;
}
//---------------------------------------------------------------------------------------
// 比 CSerialPort 多了一个 ReceiveMode 的参数,表示读取方式
//---------------------------------------------------------------------------------------
void CSerialComm::Open(int nPort, ReceiveMode mode, DWORD dwBaud, Parity parity, BYTE DataBits,
StopBits stopbits, FlowControl fc)
{
// 1.新建串口
m_pPort = new CSerialPort();
// 2.判断收发模式
if( mode == ManualReceiveByQuery )
m_IsOverlapped = FALSE;
else
m_IsOverlapped = TRUE;
m_RecvMode = mode;
// 3.打开串口
m_pPort->Open(nPort, dwBaud, parity, DataBits, stopbits, fc, m_IsOverlapped );
m_pPort->Setup(4096, 4096);
m_pPort->Purge(PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
// --- 重点
COMMTIMEOUTS timeouts;
m_pPort->GetTimeouts(timeouts);
timeouts.ReadIntervalTimeout = 100;
m_pPort->SetTimeouts(timeouts);
m_CurPortNum = nPort;
// 创建关闭事件
m_hCloseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ASSERT(m_hCloseEvent);
//-------------------------------------------------------------------------
// 4.创建线程类
//-------------------------------------------------------------------------
m_pReadThread = new CSerialReadThread();
m_pReadThread->BandSerialPort(this);
m_pReadThread->Create();
m_pReadThread->Resume();
if( IsOverlapped() )
{ // 对于支持重叠操作的方式创建重叠事件
m_hWriteEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
}
}
void CSerialComm::Close()
{
// 1.串口,没有创建或打开
if( m_pPort == NULL )
return;
if( !m_pPort->IsOpen() )
return;
// 2.事件
::SetEvent( m_hCloseEvent );// 通知关闭系统
// ???
// Sleep(1000);
// 3.结束读线程
TRY
{
m_pReadThread->Terminate();
delete m_pReadThread;
m_pReadThread = NULL;
}
CATCH(CSerialException, pEx)
{
TRACE(pEx->GetErrorMessage());
pEx->Delete();
}
END_CATCH
// 4.结束关闭线程
::CloseHandle(m_hCloseEvent);
m_pPort->Close();
// 5.结束写事件
if( m_hWriteEvent )
{
::CloseHandle( m_hWriteEvent );
m_hWriteEvent = NULL;
}
// 6.释放串口对象
delete m_pPort;
m_pPort = NULL;
}
void CSerialComm::OnReceiveData(void* pBuf, DWORD InBufferCount)
{
if( m_pfnOnReceiveData )
m_pfnOnReceiveData( m_pSender, pBuf, InBufferCount );
}
void CSerialComm::SetReceiveFunc(PFNOnReceiveData pfnOnReceiveData, LPVOID pSender)
{
m_pfnOnReceiveData = pfnOnReceiveData;
m_pSender = pSender;
}
void CSerialComm::OnComBreak(DWORD dwMask)
{
if( m_pfnOnComBreak )
{
COMSTAT stat;
m_pPort->GetStatus( stat );
m_pfnOnComBreak( m_pPort, dwMask, stat );
}
}
void CSerialComm::SetBreakHandleFunc(PFNOnComBreak pfnOnComBreak)
{
m_pfnOnComBreak = pfnOnComBreak;
}
//---------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------
ReceiveMode CSerialComm::GetReceiveMode()
{
return m_RecvMode;
}
DWORD CSerialComm::GetInBufferCount()
{
if(this->IsOverlapped())
{
TRACE( _T("this methord is only used for ManualQuery mode!") );
return 0;
}
COMSTAT stat;
ZeroMemory(&stat, sizeof(stat));
this->m_pPort->GetStatus(stat);
return stat.cbInQue;
}
DWORD CSerialComm::GetInput(void* pBuf,DWORD Count,DWORD dwMilliseconds)
{
// 不允许在自动模式下工作
if( GetReceiveMode() == AutoReceiveByBreak ||
GetReceiveMode() == AutoReceiveBySignal )
{
TRACE( _T("Can't use GetInput methord in AutoQuery mode!") );
return 0;
}
if( IsOverlapped() )
{
ASSERT(m_pReadThread);
DWORD dwBytes = m_pReadThread->ReadInput(pBuf,Count,dwMilliseconds);
m_pPort->TerminateOutstandingReads();
return dwBytes;
}
else
{
return m_pPort->Read(pBuf,Count);
}
}
DWORD CSerialComm::Output(void* pBuf,DWORD Count)
{
DWORD dwWriteBytes = 0;
if( IsOverlapped() )
{ // 异步模式
m_pPort->Write(pBuf, Count, m_WriteOverlapped);
if( WaitForSingleObject(m_WriteOverlapped.hEvent,INFINITE) == WAIT_OBJECT_0 )
{
m_pPort->GetOverlappedResult(m_WriteOverlapped, dwWriteBytes, FALSE);
}
}
else
{
dwWriteBytes = m_pPort->Write(pBuf,Count);
}
return dwWriteBytes;
}
CSerialPort* CSerialComm::GetSerialPort()
{
ASSERT(m_pPort);
return m_pPort;
}
HANDLE CSerialComm::GetCloseHandle()
{
ASSERT(this->m_hCloseEvent);
return this->m_hCloseEvent;
}
//***************************************************************************************
// CSerialReadThread
//***************************************************************************************
CSerialReadThread::CSerialReadThread()
{
m_hThread = NULL;
m_pPortComm = NULL;
m_IsClose = FALSE;
ZeroMemory(&m_BreakOverlapped, sizeof(m_BreakOverlapped));
ZeroMemory(&m_ReadOverlapped, sizeof(m_ReadOverlapped));
memset(m_InputBuffer, 0, 2048);
}
CSerialReadThread::~CSerialReadThread()
{
m_hThread = NULL;
}
BOOL CSerialReadThread::SetReadEvent(OVERLAPPED& overlapped)
{
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
return FALSE;
BeginSet:
if( pPort->Read(m_InputBuffer, 2048, overlapped, &m_InBufferCount) )
{ // 读取完成后调用 HandleData 处理
if( !HandleData() )
return FALSE;
::ResetEvent( m_ReadOverlapped.hEvent );
goto BeginSet;
}
DWORD error = GetLastError();
if( error == ERROR_IO_PENDING )
return TRUE;
else
return FALSE;
}
BOOL CSerialReadThread::HandleData() //处理读取数据
{
if( m_InBufferCount > 0 )
{
m_pBuffer = new BYTE[m_InBufferCount];
for( int i = 0; i< (int)m_InBufferCount; i ++ )
{ // 拷贝
m_pBuffer[i] = m_InputBuffer[i];
}
// 处理完后立即删掉
m_pPortComm->OnReceiveData( m_pBuffer, m_InBufferCount );
delete[] m_pBuffer;
}
return TRUE;
}
BOOL CSerialReadThread::HandleReadEvent(OVERLAPPED& overlapped)
{
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
return FALSE;
if( pPort->GetOverlappedResult(overlapped, m_InBufferCount, FALSE) )
{ // 转到了 CSerialReadThread::HandleData(),然后到了 CSerialComm::ReceiveData
return HandleData();
}
DWORD dwError = ::GetLastError();
if( dwError == ERROR_INVALID_HANDLE )
return FALSE;
else
return TRUE;
}
BOOL CSerialReadThread::SetBreakEvent(DWORD& dwMask )
{
CSerialPort* pPort = m_pPortComm->GetSerialPort();
if( pPort == NULL )
return FALSE;
SetBegin:
if( pPort->WaitEvent(dwMask, m_BreakOverlapped) )
{
if( !HandleBreakEvent(dwMask) )
return FALSE;
goto SetBegin;
}
DWORD error = GetLastError();
if( error == ERROR_IO_PENDING )
return TRUE;
else
return FALSE;
}
BOOL CSerialReadThread::HandleBreakEvent(DWORD dwMask)
{
DWORD dwReadBytes;
CSerialPort* pPort = m_pPortComm->GetSerialPort();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -