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

📄 serialhandler.cpp

📁 自编的串口通信程序
💻 CPP
字号:
// SerialCom.cpp: implementation of the CSerialHandler class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SerialHandler.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

HANDLE G_m_hCom;
CSerialHandler *pGSerial;

UINT CommProc(LPVOID lParam);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSerialHandler::CSerialHandler(CWinThread * pThread)
{
	m_pParentThread=pThread;

	//com default value
	m_nBaud=8; //115200
	m_nDataBits=1;//8bits
	m_nFlowCtrl=
	m_nParity=1;//No Parity
	m_nRespond_TimeOut=1000;
	m_nStopBits=0;//1 stop bit
	::sprintf(m_cPort,"COM%d",1);

	// 为重叠读创建事件对象,手工重置,初始化为无信号的
	if((m_osRead.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
	{
		AfxMessageBox("为重叠读创建事件对象失败!");
	}

	// 为重叠写创建事件对象,手工重置,初始化为无信号的
	if((m_osWrite.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL))==NULL)
	{
		AfxMessageBox("为重叠写创建事件对象失败!");
	}
}

CSerialHandler::~CSerialHandler()
{
	CloseConnection();
}

DWORD CSerialHandler::WriteComm(unsigned char *buf,DWORD dwLength)
{
	BOOL fState;
	DWORD length=dwLength;
	
	fState=WriteFile(m_hCom,buf,length,&length,&m_osWrite);

	if(!fState)
	{
		if(GetLastError()==ERROR_IO_PENDING)
			GetOverlappedResult(m_hCom,&m_osWrite,&length,TRUE);// 等待
		else
			length=0;
	}
	return length;
}
BOOL CSerialHandler::ConfigConnection(HANDLE m_hCom)
{
	DCB dcb;

	if(!GetCommState(m_hCom, &dcb))
		return FALSE;

	dcb.fBinary=TRUE;
	switch(m_nBaud)
	{
		case 0: dcb.BaudRate = 1200; break;// 波特率 
			
		case 1: dcb.BaudRate = 2400; break;
			
		case 2: dcb.BaudRate = 4800; break;// 波特率 
			
		case 3:	dcb.BaudRate = 9600; break;
		
		case 4:	dcb.BaudRate = 14400; break;// 波特率 
		
		case 5:	dcb.BaudRate = 19200; break;
		
		case 6:	dcb.BaudRate = 38400; break;// 波特率 

		case 7:	dcb.BaudRate = 57600; break;

		case 8:	dcb.BaudRate = 115200; break;// 波特率 
		
		default: dcb.BaudRate = 9600;   break;
	}
	switch(m_nDataBits)
	{
		case 0: dcb.ByteSize = 7; break;
		case 1:	dcb.ByteSize = 8; break;
		default: dcb.ByteSize = 8; break;
	}


	dcb.fParity=TRUE;
	switch(m_nParity) // 校验设置
	{
		case 0: dcb.Parity=NOPARITY; break;
		case 1: dcb.Parity=ODDPARITY; break;
		case 2: dcb.Parity=EVENPARITY; break;
		default:dcb.Parity=NOPARITY; break;
	}

	switch(m_nStopBits) // 停止位
	{
		case 0:  dcb.StopBits=ONESTOPBIT;   break;
		case 1:  dcb.StopBits=ONE5STOPBITS;	break;
		case 2:  dcb.StopBits=TWOSTOPBITS;	break;
		default: dcb.StopBits=ONESTOPBIT;   break;
	}

	// 硬件流控制设置
	//dcb.fOutxCtsFlow=m_nFlowCtrl==1;
	//dcb.fRtsControl=m_nFlowCtrl==1?
	//RTS_CONTROL_HANDSHAKE:RTS_CONTROL_ENABLE;
	// XON/XOFF流控制设置
	//dcb.fInX=dcb.fOutX=m_nFlowCtrl==2;
	//dcb.XonChar=XON;
	//dcb.XoffChar=XOFF;
	//dcb.XonLim=50;
	//dcb.XoffLim=50;
	return SetCommState(m_hCom, &dcb);
}
BOOL CSerialHandler::OpenConnection()
{
	COMMTIMEOUTS TimeOuts;

	if(m_bConnected)
		return FALSE;

	m_hCom=CreateFile(m_cPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,
			OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL); // 重叠方式

	if(m_hCom==INVALID_HANDLE_VALUE)
	{
		m_bConnected = FALSE;
		return FALSE;
	}
	SetupComm(m_hCom,MAXBLOCK,MAXBLOCK);
	SetCommMask(m_hCom, EV_RXCHAR);

	TimeOuts.ReadIntervalTimeout=
	TimeOuts.ReadTotalTimeoutMultiplier=
	TimeOuts.ReadTotalTimeoutConstant=
	TimeOuts.WriteTotalTimeoutMultiplier=
	TimeOuts.WriteTotalTimeoutConstant=m_nRespond_TimeOut;
	SetCommTimeouts(m_hCom, &TimeOuts);
    

	if(ConfigConnection(m_hCom))
	{
		this->m_bConnected = TRUE;
		m_pWatchThread= AfxBeginThread(CommProc,this,THREAD_PRIORITY_NORMAL,
			                                 0,CREATE_SUSPENDED,NULL);
		if(m_pWatchThread == NULL)
		{   
			CloseHandle(m_hCom);
			return FALSE;
		}
		else
		{
			m_pWatchThread->ResumeThread();
		}
	//	m_pThread=AfxBeginThread(CommProc, this, THREAD_PRIORITY_NORMAL, 
	//			                0, CREATE_SUSPENDED, NULL); // 创建并挂起线程
	//	if(m_pThread==NULL)
	//	{
	//		CloseHandle(m_hCom);
	//		return FALSE;
	//	}
	//	else
	//	{
	//		m_pThread->ResumeThread(); // 恢复线程运行
	//	}
	}
	else
	{
		m_bConnected = FALSE;
		CloseHandle(m_hCom);
		return FALSE;
	}
	pGSerial = this;
	G_m_hCom = m_hCom;
	return TRUE;
}

BOOL CSerialHandler::CloseConnection()
{
	if(!m_bConnected) return TRUE;
	m_bConnected=FALSE;
   
	//等待辅助线程终止
	WaitForSingleObject(m_pWatchThread->m_hThread, INFINITE);

	if(CloseHandle(m_hCom))
	{
		return TRUE;
	}
	else
		return FALSE;
}
UINT CommProc(LPVOID lParam) //监视串口字符事件线程
{
	COMSTAT ComStat;
	DWORD dwErrorFlags=0;

//	CSerialHandler *pSerial = (CSerialHandler*)pParam;
	CSerialHandler * pHandler=(CSerialHandler *)lParam;

	while(pHandler->m_bConnected)
	{
		ClearCommError(pHandler->m_hCom,&dwErrorFlags,&ComStat);
		if(ComStat.cbInQue>=4)//only if more than 4 bytes in port pending, we start reading
			(pHandler->m_pParentThread)->PostThreadMessage(WM_SERIAL_RX_CHAR,0,0);
		else
			::Sleep(100);
	}
	return 0;

}

void CSerialHandler::CalculateLRC(unsigned char *pByte, int nNumberOfBytes, unsigned short *pChecksum)
{
	//ASCII模式LRC校验
	unsigned char c,temph,templ;
	unsigned int i;
	c=0;
	for(i=0;i<nNumberOfBytes-1;i+=2)
	{
		temph=(pByte[i]<'A') ? pByte[i]-48 : ((pByte[i]<'a') ? pByte[i]-55 : pByte[i]-87);
		templ=(pByte[i+1]<'A') ? pByte[i+1]-48 : ((pByte[i+1]<'a') ? pByte[i+1]-55 : pByte[i+1]-87);
		c=temph*16+templ+c;
	}
	if(nNumberOfBytes%2!=0)
	{
		temph=(pByte[i]<'A') ? pByte[i]-48 : ((pByte[i]<'a') ? pByte[i]-55 : pByte[i]-87);
		c=temph*16+c;
	}
	*pChecksum=~c+1;
}
BOOL CSerialHandler::CalculateChecksum(unsigned char * pByte, int nNumberOfBytes,
 							   				   unsigned short *pChecksum, int nChecksumMode /* = BCC_CHECKSUM */)
{
	BOOL bReturn = TRUE;

	if (BCC_CHECKSUM == nChecksumMode)
		CalculateBCC(pByte, nNumberOfBytes, pChecksum);
	else if (LRC_CHECKSUM == nChecksumMode)
		CalculateLRC(pByte, nNumberOfBytes, pChecksum);
	else if (CRC_CHECKSUM == nChecksumMode)
		CalculateCRC(pByte, nNumberOfBytes, pChecksum);
	else
	{
		// this should never happen
		TRACE("Invalid Checksum Mode(%ld), File %s, Line %d\n", nChecksumMode, __FILE__, __LINE__);
		bReturn = FALSE;
	}

	return bReturn;
}
void CSerialHandler::CalculateBCC(unsigned char * pByte, int nNumberOfBytes, unsigned short *pChecksum)
{
	for (int nByte = 0; nByte < nNumberOfBytes; nByte++)
	{
		*pChecksum = (unsigned char)((unsigned char)*pChecksum + *pByte);
		pByte++;
	}

}
void CSerialHandler::CalculateCRC(unsigned char *pByte, int nNumberOfBytes, unsigned short *pChecksum)
{
	//RTU模式CRC校验
	int nBit;
	unsigned short nShiftedBit;
	*pChecksum=0xffff;
	
	for (int nByte = 0; nByte < nNumberOfBytes; nByte++)
	{
       	*pChecksum ^= *(pByte+nByte);
       	for (nBit=0; nBit<8; nBit++)
		{
       		nShiftedBit=*pChecksum;
       		*pChecksum>>=1;
    		if (nShiftedBit & 0x0001)  *pChecksum^=0xA001;
		}
			
	}
}

BOOL CSerialHandler::ReadComm(unsigned char *pBuf, UINT *pLen,UINT maxLen)
{
	COMSTAT ComStat;
	DWORD dwErrorFlags=0;
	BOOL fReadStat;
	DWORD dwBytesRead;

//	CSerialHandler *pSerial = (CSerialHandler*)pParam;
	ClearCommError(m_hCom,&dwErrorFlags,&ComStat);	
	fReadStat= ReadFile(m_hCom,pBuf,
						min(maxLen,ComStat.cbInQue),
						&dwBytesRead,&m_osRead); //读数据
	if(!fReadStat){// we have to wait for overlapped reading
		if(GetLastError()==ERROR_IO_PENDING){		
			while(!GetOverlappedResult(m_hCom,&m_osRead,
									   &dwBytesRead,TRUE)){
				dwErrorFlags = GetLastError();
				if(dwErrorFlags == ERROR_IO_INCOMPLETE) 
					 continue;
					else{dwErrorFlags=-1;break;}
			}
		}else{//abnormal error
		dwErrorFlags=-1;
		}
	}
	*pLen=dwBytesRead;

	if(dwErrorFlags!=-1)
		return TRUE;
	else
		return FALSE;
		
}

⌨️ 快捷键说明

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