📄 serialhandler.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 + -