📄 comport.cpp
字号:
// ComPort.cpp : 实现文件
//
#include "stdafx.h"
#include "ComPort.h"
namespace LsComm{
// CComPort
CComPort::CComPort()
: m_bIsOpen(false)
{
this->m_pfnOnReceiveData = NULL;
this->m_pfnOnComBreak =NULL;
this->m_pPort = NULL;
this->m_pReadThread = NULL;
::ZeroMemory(&this->m_WriteOverlapped,sizeof(this->m_WriteOverlapped));
this->m_hWriteEvent = NULL;
this->m_bIsOpen = false;
}
CComPort::~CComPort()
{
if(this->m_pPort)
{
if(this->m_pPort->IsOpen())
{
this->Close();
}
}
if(this->m_pPort)
{
delete this->m_pPort;
this->m_pPort = NULL;
}
}
// CComPort 成员函数
// //当前串口是否打开
bool CComPort::IsOpen(void)
{
return this->m_bIsOpen;
}
bool CComPort::Open(int nPort,ReceiveMode mode, DWORD dwBaud, Parity parity, BYTE DataBits,
StopBits stopbits,FlowControl fc)
{
//1.新建串口
if(this->m_pPort)
delete this->m_pPort;
this->m_pPort = new CSerialPort();
this->m_bIsOpen = false;
//2.判断收发模式
if(mode==ReceiveMode::ManualReceiveByQuery)
{
this->m_IsOverlapped = false;
}
else
{
this->m_IsOverlapped = true;
}
this->m_RecvMode = mode;
//3.转换参数,打开串口
int index;
index=parity-CComPort::EvenParity;
CSerialPort::Parity spParity=(CSerialPort::Parity)(CSerialPort::EvenParity+index);
index=stopbits-CComPort::OneStopBit;
CSerialPort::StopBits spStopbits=(CSerialPort::StopBits)(CSerialPort::OneStopBit+index);
index=fc-CComPort::NoFlowControl;
CSerialPort::FlowControl spFC=(CSerialPort::FlowControl)(CSerialPort::NoFlowControl+index) ;
try
{
this->m_pPort->Open(nPort,dwBaud,spParity,DataBits,spStopbits,spFC,m_IsOverlapped);
}
catch(CSerialException* pE)
{
//AfxMessageBox(pE->GetErrorMessage());
pE->Delete();
return false;
}
//it is important!!
COMMTIMEOUTS timeouts;
this->m_pPort->GetTimeouts(timeouts);
timeouts.ReadIntervalTimeout=100;
//timeouts.WriteTotalTimeoutConstant = 1000;
this->m_pPort->SetTimeouts(timeouts);
this->m_pPort->Purge(PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
this->m_pPort->Setup(4096,4096);
this->m_CurPortNum = nPort;
//创建关闭事件
this->m_hCloseEvent = CreateEvent(NULL,true,false,NULL);
if(this->m_hCloseEvent==NULL)
{
return false;
}
//4.创建线程类
this->m_pReadThread = new CReadComThread();
this->m_pReadThread->BandSerialPort(this);
this->m_pReadThread->Create();
this->m_pReadThread->Resume();
if(this->IsOverlapped())
{
this->m_hWriteEvent = ::CreateEvent(NULL,true,false,NULL);
if(this->m_hCloseEvent==NULL)
return false;
this->m_WriteOverlapped.hEvent = this->m_hWriteEvent;
}
this->m_bIsOpen = true;
return true;
}
void CComPort::Close()
{
//1.串口
if(this->m_pPort==NULL)
return;
if(!this->m_pPort->IsOpen())
return;
//2.事件
::SetEvent(this->m_hCloseEvent);//通知关闭系统
Sleep(1000);
//3.结束读线程
try
{
this->m_pReadThread->Terminate();
delete this->m_pReadThread;
this->m_pReadThread = NULL;
}
catch(char e[150])
{
::AfxMessageBox(e);
}
//4.结束关闭线程
::CloseHandle(this->m_hCloseEvent);
this->m_pPort->Close();
//5.结束写事件
if(this->m_hWriteEvent)
{
::CloseHandle(this->m_hWriteEvent);
this->m_hWriteEvent = NULL;
}
//6.释放串口对象
if(this->m_pPort)
{
delete this->m_pPort;
this->m_pPort = NULL;
}
}
void CComPort::ReceiveData(void* pBuf,DWORD InBufferCount)
{
if(this->m_pfnOnReceiveData)
this->m_pfnOnReceiveData(this->m_pSender,pBuf,InBufferCount);
}
void CComPort::SetReceiveFunc(FOnReceiveData pfnOnReceiveData,LPVOID pSender)
{
this->m_pfnOnReceiveData = pfnOnReceiveData;
this->m_pSender = pSender;
}
void CComPort::ComBreak(DWORD dwMask)
{
if(this->m_pfnOnComBreak)
{
COMSTAT stat;
this->m_pPort->GetStatus(stat);
this->m_pfnOnComBreak(this->m_pPort,dwMask,stat);
}
}
void CComPort::SetBreakHandleFunc(FOnComBreak pfnOnComBreak)
{
this->m_pfnOnComBreak = pfnOnComBreak;
}
CComPort::ReceiveMode CComPort::GetReceiveMode()
{
return this->m_RecvMode;
}
DWORD CComPort::GetInBufferCount()
{
if(this->IsOverlapped())
{
::AfxMessageBox("this methord is only used for ManualQueryMode!");
return 0;
}
COMSTAT stat;
::ZeroMemory(&stat,sizeof(stat));
this->m_pPort->GetStatus(stat);
return stat.cbInQue;
}
DWORD CComPort::GetInput(void* pBuf,DWORD Count,DWORD dwMilliseconds)
{
//不能在自动模式下getinput
if(this->GetReceiveMode()==CComPort::AutoReceiveByBreak||
this->GetReceiveMode()==CComPort::AutoReceiveBySignal)
{
::AfxMessageBox("Can't use GetInput methord in this mode!");
return 0;
}
if(this->IsOverlapped())
{
ASSERT(this->m_pReadThread);
DWORD dwBytes = this->m_pReadThread->ReadInput(pBuf,Count,dwMilliseconds);
this->m_pPort->TerminateOutstandingReads();
return dwBytes;
}
else
return this->m_pPort->Read(pBuf,Count);
}
DWORD CComPort::Output(void* pBuf,DWORD Count)
{
DWORD dwWriteBytes=0;
if(this->IsOverlapped())//异步模式
{
this->m_pPort->Write(pBuf,Count,this->m_WriteOverlapped);
if(WaitForSingleObject(this->m_WriteOverlapped.hEvent,INFINITE)==WAIT_OBJECT_0)
{
this->m_pPort->GetOverlappedResult(this->m_WriteOverlapped,dwWriteBytes,false);
}
}
else
{
/*for(DWORD i=0;i<Count;i++)
{
dwWriteBytes+= this->m_pPort->Write(pBuf,1);
} //for use in win98
*/
dwWriteBytes = this->m_pPort->Write(pBuf,Count);
}
return dwWriteBytes;
}
CSerialPort* CComPort::GetSerialPort()
{
ASSERT(m_pPort);
return m_pPort;
}
HANDLE CComPort::GetCloseHandle()
{
ASSERT(this->m_hCloseEvent);
return this->m_hCloseEvent;
}
//CReadComThread
CReadComThread::CReadComThread()
{
this->m_hThread = NULL;
this->m_pPort = NULL;
this->IsClose =false;
::ZeroMemory(&this->m_BreakOverlapped,sizeof(this->m_BreakOverlapped));
::ZeroMemory(&this->m_ReadOverlapped,sizeof(this->m_ReadOverlapped));
memset(this->m_InputBuffer,0,2048);
}
CReadComThread::~CReadComThread()
{
this->m_hThread = NULL;
}
// CReadComThread 成员函数
bool CReadComThread::SetReadEvent(OVERLAPPED& overlapped)
{
BeginSet:
memset(this->m_InputBuffer,0,2048);
if(this->m_pPort->GetSerialPort()->Read(this->m_InputBuffer,2048,overlapped,&this->m_InBufferCount))
{
if(!this->HandleData())
return false;
::ResetEvent(this->m_ReadOverlapped.hEvent);
goto BeginSet;
}
DWORD error=::GetLastError();
if(error==ERROR_IO_PENDING)
{ return true; }
else
{ return false; }
}
bool CReadComThread::HandleData() //处理读取数据
{
if(this->m_InBufferCount>0)
{
this->m_pBuffer = new byte[this->m_InBufferCount];
for(int i=0;i<(int)this->m_InBufferCount;i++)
{
this->m_pBuffer[i] = this->m_InputBuffer[i];
}
//this->m_pSerialPort->
this->m_pPort->ReceiveData(this->m_pBuffer,this->m_InBufferCount);
delete[] this->m_pBuffer;
}
return true;
}
bool CReadComThread::HandleReadEvent(OVERLAPPED& overlapped)
{
if(this->m_pPort->GetSerialPort()->GetOverlappedResult(overlapped,this->m_InBufferCount,false))
{
return this->HandleData();
}
DWORD dwError = ::GetLastError();
if(dwError==ERROR_INVALID_HANDLE)
return false;
else
return true;
}
bool CReadComThread::SetBreakEvent(DWORD& dwMask )
{
SetBegin:
if(this->m_pPort->GetSerialPort()->WaitEvent(dwMask,this->m_BreakOverlapped))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -