📄 ceserialcomm.cpp
字号:
/*************************************************************************
CeSerialComm.cpp: implementation of the CCeSerialComm class.
作 者: Raymond
创建时间: 2006.04.19
作 用: 封装串口API
*************************************************************************/
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RddDbg.h"
#include "CeSerialComm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCeSerialComm::CCeSerialComm()
{
m_hComm = NULL;
m_strPort = _T("COM1");
m_strError = _T("");
m_uRate = 9600;
}
CCeSerialComm::~CCeSerialComm()
{
}
BOOL CCeSerialComm::InitComm(LPCTSTR lpszPort, UINT uRate, UINT uTimeOut)
{
if(IsCommOpened()) return TRUE;
if(!OpenComm(lpszPort)) return FALSE;
DCB commParam;
// 得到打开串口的当前属性参数,修改后再重新设置串口。
// 设置串口的超时特性为立即返回。
if (!GetCommState(m_hComm,&commParam))
{
return FALSE;
}
commParam.fOutxCtsFlow = FALSE;
commParam.fOutxDsrFlow = FALSE;
commParam.fRtsControl = DTR_CONTROL_DISABLE;
commParam.fDtrControl = DTR_CONTROL_DISABLE;
commParam.BaudRate = uRate; // set the baud rate
commParam.ByteSize = 8; // data size, xmit, and rcv
commParam.Parity = NOPARITY; // no parity bit
commParam.StopBits = ONESTOPBIT; // one stop bit
if (!SetCommState(m_hComm, &commParam))
{
AfxMessageBox(_T("设置串口属性参数失败!"));
return FALSE;
}
//设置串口读写时间
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts (m_hComm, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 10;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
if(!SetCommTimeouts( m_hComm, &CommTimeOuts ))
{
TRACE( _T("SetCommTimeouts 返回错误") );
return FALSE;
}
//指定端口监测的事件集
SetCommMask (m_hComm, EV_RXCHAR|EV_TXEMPTY);
//分配设备缓冲区
SetupComm(m_hComm, 2048, 2048);
//初始化缓冲区中的信息
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
return TRUE;
}
BOOL CCeSerialComm::OpenComm(LPCTSTR lpszPort)
{
TCHAR szPort[15];
//设置串口名
wsprintf(szPort, L"%s:", lpszPort);
m_hComm = CreateFile(szPort, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if(m_hComm == INVALID_HANDLE_VALUE)
{
m_strError = GetLastErrorDisc();
AfxMessageBox(m_strError);
return FALSE;
}
return TRUE;
}
BOOL CCeSerialComm::CloseComm()
{
if(m_hComm != NULL && m_hComm != INVALID_HANDLE_VALUE) return FALSE;
return CloseHandle(m_hComm);
}
BOOL CCeSerialComm::ClearCommBreaks()
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return ClearCommBreak(m_hComm);
}
BOOL CCeSerialComm::ClearCommErrors(LPDWORD lpErrors, LPCOMSTAT lpStat)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return ClearCommError(m_hComm, lpErrors, lpStat);
}
BOOL CCeSerialComm::GetCommMasks(LPDWORD lpEvtMask)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return GetCommMask(m_hComm, lpEvtMask);
}
BOOL CCeSerialComm::GetCommStates(LPDCB lpDCB)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return GetCommState(m_hComm, lpDCB);
}
BOOL CCeSerialComm::GetCommTimeOut(LPCOMMTIMEOUTS lpCommTimeouts)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return GetCommTimeouts(m_hComm, lpCommTimeouts);
}
BOOL CCeSerialComm::SetCommTimeOut(LPCOMMTIMEOUTS lpCommTimeouts)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return SetCommTimeouts(m_hComm, lpCommTimeouts);
}
BOOL CCeSerialComm::PurgeCeComm(DWORD dwFlags)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return PurgeComm(m_hComm, dwFlags);
}
BOOL CCeSerialComm::SetCommMasks(DWORD dwEvtMsk)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return SetCommMask(m_hComm, dwEvtMsk);
}
BOOL CCeSerialComm::SetCommStates(LPDCB lpDCB)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return SetCommState(m_hComm, lpDCB);
}
BOOL CCeSerialComm::IsCommOpened()
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return TRUE;
}
BOOL CCeSerialComm::ReadNoEvent(BYTE *pByMsg, DWORD dwLen, LPDWORD lpdwReadLen, DWORD dwTimeOut/* =0 */)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
if(dwTimeOut != 0)
{
COMMTIMEOUTS CommTimeouts;
if(!GetCommTimeOut(&CommTimeouts)) return FALSE;
CommTimeouts.ReadTotalTimeoutMultiplier = 10;
CommTimeouts.ReadTotalTimeoutConstant = dwTimeOut;
if(!SetCommTimeOut(&CommTimeouts)) return FALSE;
}
if(!ReadFile(m_hComm, pByMsg, dwLen, lpdwReadLen, NULL))
{
CloseComm();
return FALSE;
}
if(*lpdwReadLen != dwLen) return FALSE;
return TRUE;
}
BOOL CCeSerialComm::ReadComm(BYTE *pByMsg, DWORD dwNumberOfBytesToRead, LPDWORD lpNumOfByRead, DWORD dwTimeOut)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
if(dwTimeOut != 0)
{
COMMTIMEOUTS CommTimeouts;
if(!GetCommTimeOut(&CommTimeouts)) return FALSE;
CommTimeouts.ReadTotalTimeoutMultiplier = 10;
CommTimeouts.ReadTotalTimeoutConstant = dwTimeOut;
if(!SetCommTimeOut(&CommTimeouts)) return FALSE;
}
if(!ReadFile(m_hComm, pByMsg, dwNumberOfBytesToRead, lpNumOfByRead, NULL))
{
CloseComm();
return FALSE;
}
return TRUE;
}
BOOL CCeSerialComm::WriteComm(BYTE *pByMsg, DWORD dwNumOfByToWrite, LPDWORD lpNumOfByWritten, DWORD dwTimeOut)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
if(dwTimeOut != 0)
{
COMMTIMEOUTS CommTimeouts;
if(!GetCommTimeOut(&CommTimeouts)) return FALSE;
CommTimeouts.WriteTotalTimeoutMultiplier = 10;
CommTimeouts.WriteTotalTimeoutConstant = dwTimeOut;
if(!SetCommTimeOut(&CommTimeouts)) return FALSE;
}
if(!WriteFile(m_hComm, pByMsg, dwNumOfByToWrite, lpNumOfByWritten, NULL))
{
CloseComm();
return FALSE;
}
return TRUE;
}
BOOL CCeSerialComm::WaitCommEvents(LPDWORD lpEvtMask)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return WaitCommEvent(m_hComm, lpEvtMask, NULL);
}
int CCeSerialComm::ReadAframe(BYTE *pByMsg, LPDWORD lpdwReadLen, DWORD dwTimeOut /* = 0 */)
{
*lpdwReadLen = 0;
DWORD dwIndex = 0;
DWORD dwReadLen;
if(!Read(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut)) return 0; //读出错
if(pByMsg[0] != 0xeb && pByMsg[0] != 0xd7) return -1; //报文头第一个字节出错
dwIndex += 1; //读出一个字节
*lpdwReadLen = dwIndex;
if(!Read(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut)) return 0; //读出错
if(!(pByMsg[0]==0xeb && pByMsg[1]==0x90) && !(pByMsg[0]==0xd7 && pByMsg[1]==0x09)) return -1; //报文头出错
dwIndex += 1; //读出一个字节
*lpdwReadLen = dwIndex;
if(!Read(pByMsg+dwIndex, 2, &dwReadLen, dwTimeOut)) return 0; //读出错
int iMsgLen = pByMsg[2] + pByMsg[3]*0x100;
if(iMsgLen > MAX_MSG_LEN) return -1; //长度出错
dwIndex += 2; //读出2个字节
*lpdwReadLen = dwIndex;
if(!Read(pByMsg+dwIndex, iMsgLen-4, &dwReadLen, dwTimeOut)) return 0; //读出错
dwIndex += iMsgLen-4; //读出iMsgLen-4个字节
*lpdwReadLen = dwIndex;
return 1; //读完
}
BOOL CCeSerialComm::Recv(BYTE *pByMsg, DWORD &dwLen, DWORD dwTimeOut)
{
dwLen = 0;
DWORD dwCommStatus;
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
//清空串口
if(!PurgeCeComm(PURGE_RXCLEAR | PURGE_TXCLEAR )) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(!WaitCommEvents(&dwCommStatus)) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(dwCommStatus & EV_RXCHAR)
{
DWORD dwReadLen;
DWORD dwIndex = 0;
do
{
if(!ReadComm(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut))
{
m_strError = GetLastErrorDisc();
return FALSE;
}
if(dwReadLen == 1)
{
dwIndex++;
dwLen ++;
}
else
{
return FALSE;
}
} while(dwReadLen == 1);
return TRUE;
}
return FALSE;
}
/*****************************************************************************************
设计意图:从串口中读取指定长度的数据。如果串口中原来有数据,则直接读出来,读到够长度就
返回,如果不够,则等待直到读到所需为止。如果串口中没有数据,则等待
*****************************************************************************************/
BOOL CCeSerialComm::Read(BYTE *pByMsg, DWORD dwLen, LPDWORD lpdwReadLen, DWORD dwTimeOut)
{
*lpdwReadLen = 0;
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
COMSTAT comStat;
DWORD dwErrors;
DWORD dwCommStatus;
BOOL bIsHasData = TRUE; //原本就有数据
if(!ClearCommErrors(&dwErrors, &comStat)) return FALSE;
DWORD dwInLen = comStat.cbInQue;
if(dwInLen < 1) //没有数据
{
//清空串口
if(!PurgeCeComm(PURGE_RXCLEAR | PURGE_TXCLEAR )) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(!WaitCommEvents(&dwCommStatus)) return FALSE;
bIsHasData = FALSE;
}
DWORD dwIndex = 0;
DWORD dwReadLen;
//有数据来,或者原本就有数据
if((dwCommStatus & EV_RXCHAR) || bIsHasData)
{
do
{
if(!ReadComm(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut))
{
*lpdwReadLen = dwReadLen;
m_strError = GetLastErrorDisc();
return FALSE;
}
if(dwReadLen == 1)
{
dwIndex++;
}
if(dwIndex == dwLen) //已经读完所需
{
*lpdwReadLen = dwLen;
return TRUE;
}
} while(dwIndex < dwInLen);
}
//清空串口
if(!PurgeCeComm(PURGE_RXCLEAR | PURGE_TXCLEAR )) return FALSE;
//长度不够
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
//读到所需为止
while(dwIndex < dwLen)
{
if(!WaitCommEvents(&dwCommStatus)) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(dwCommStatus & EV_RXCHAR)
{
do
{
if(!ReadComm(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut))
{
m_strError = GetLastErrorDisc();
*lpdwReadLen = dwReadLen;
return FALSE;
}
if(dwReadLen == 1) dwIndex++;
if(dwIndex == dwLen) //已经够所需了
{
*lpdwReadLen = dwLen;
return TRUE;
}
} while(dwReadLen == 1);
}
}
return FALSE;
}
BOOL CCeSerialComm::Write(BYTE *pByMsg, DWORD dwLen, LPDWORD lpdwWriteLen, DWORD dwTimeOut)
{
UINT uIndex = 0;
*lpdwWriteLen = 0;
while(uIndex < dwLen)
{
DWORD dwWrittenLen;
if(!WriteComm(pByMsg+uIndex, 1, &dwWrittenLen))
{
m_strError = GetLastErrorDisc();
return FALSE;
}
if(dwWrittenLen == 1)
{
uIndex++;
(*lpdwWriteLen)++;
}
else
{
return FALSE;
}
}
return TRUE;
}
CString CCeSerialComm::GetLastErrorDisc()
{
int iErCode = GetLastError();
HLOCAL hLocal = NULL;
BOOL fOk = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, iErCode, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
(PTSTR) &hLocal, 0, NULL);
//如果没有则从网络模块查找.
if(!fOk)
{
HMODULE hDLL = LoadLibraryEx(TEXT("netmsg.dll"), NULL,
DONT_RESOLVE_DLL_REFERENCES);
if(hDLL != NULL)
{
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM,
hDLL, iErCode, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
(PTSTR)&hLocal, 0, NULL);
FreeLibrary(hDLL);
}
}
if(hLocal != NULL)
{
CString strMsg;
strMsg.Format(_T("%s"), (PTSTR)LocalLock(hLocal));
m_strError = strMsg;
LocalFree(hLocal);
return strMsg;
}
return _T("Unknow Error");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -