⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comport.cpp

📁 一个封装好的串口通信类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ComPort.cpp : 实现文件
#include "stdafx.h"
#include "ComPort.h"

namespace LsComm{
	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;
		}
	}
	
	//当前串口是否打开
	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))
	{
		if(!this->HandleBreakEvent(dwMask))
			return false;
		goto SetBegin;
	}
	
    DWORD error=::GetLastError();
	if(error==ERROR_IO_PENDING)
	{ return true; }
	else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -