📄 hwclasscom.cpp
字号:
// COM.cpp: implementation of the CHwClassCOM class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <afxmt.h>
#include "HwClassCOM.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CCriticalSection f_csForAllCom;
/********************************************************************************
* Function Type : Global
* Parameter : data - 被检验的有效数据
len - 被校验的有效数据的程度
crc1 - 得到的第一个crc校验码
crc2 - 得到的第二个crc校验码
* Return Value : None
* Description : Calculate the CRC check sum of the data block.
*********************************************************************************/
void CalculateCRC(PUCHAR data, int len, PUCHAR crc1, PUCHAR crc2)
{
const char CRC_DIVIDER1 = 0x10;
const char CRC_DIVIDER2 = 0x21;
UCHAR b1, b2, b3;
UCHAR c1, c2, c3;
int i, k;
if (len <= 0) return;
/* 取两字节数据 */
b1 = data[0];
b2 = ((len>=2) ? data[1] : 0);
i = 2;
do {
/* 取后一字节数据 */
b3 = ((i<len) ? data[i] : 0);
/* 处理一字节的数据 */
for (k=0; k<8; k++)
{
/* 取高位 */
c1 = b1 & 0x80;
c2 = b2 & 0x80;
c3 = b3 & 0x80;
/* 左移一位 */
b1 <<= 1;
b2 <<= 1;
b3 <<= 1;
if (c2) b1 |= 1;
if (c3) b2 |= 1;
if (c1)
{
/* 16位的模2除法 */
b1 ^= CRC_DIVIDER1;
b2 ^= CRC_DIVIDER2;
}
}
i ++;
} while (i < (len+2));
(*crc1) = b1;
(*crc2) = b2;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHwClassCOM::CHwClassCOM()
{
m_iComNO = INVALID_COM_NO;
ZeroMemory(&m_CommProp,sizeof(COMMPROP));
m_handleCOM = NULL;
}
CHwClassCOM::~CHwClassCOM()
{
Close();
}
/********************************************************************************
* Function Type : Public
* Parameter : buf - 读数据缓冲
* dwSize - 要读的字节数
* Return Value : >=0 - 读到的字节数
* -1 - error occured
* Description : 从串口中读数据
*********************************************************************************/
int CHwClassCOM::Read(LPVOID buf, DWORD dwSize)
{
DWORD nBytesComm;
ZeroMemory(buf,dwSize);
f_csForAllCom.Lock();
if(!ReadFile(m_handleCOM,buf,dwSize,&nBytesComm,NULL))
{
m_csError.Format("读%d字节数据时出错",dwSize);
f_csForAllCom.Unlock();
return -1L;
}
f_csForAllCom.Unlock();
return nBytesComm;
}
/********************************************************************************
* Function Type : Public
* Parameter : buf - 写数据缓冲
* dwSize - 要写的字节数
* Return Value : >=0 - 写出去的字节数
* -1 - error occured
* Description : 从串口中读数据
*********************************************************************************/
int CHwClassCOM::Write(LPVOID buf, DWORD dwSize)
{
DWORD nBytesComm;
f_csForAllCom.Lock();
if(!WriteFile(m_handleCOM,buf,dwSize,&nBytesComm,NULL))
{
m_csError.Format("写%d字节数据时出错",dwSize);
f_csForAllCom.Unlock();
return -1L;
}
f_csForAllCom.Unlock();
return nBytesComm;
}
/********************************************************************************
* Function Type : Private
* Parameter : iBytes - [in] 等待数据字节数
* timeout - [in] 等待数据的最大时间(秒)
* Return Value : TRUE - 等到数据
* FALSE - 没等到
* Description : 等到指定字节数据可读
*********************************************************************************/
BOOL CHwClassCOM::WaitForDataToRead(int iBytes,int timeout/* = 5*/)
{
time_t start_time = time(NULL);
//ClearComm();
while(difftime(time(NULL),start_time) < timeout)
{
if( GetCommInputBuffLen() < (DWORD)iBytes) //没有接收到iBytes个数据
Sleep(100);
else
{
return TRUE;
}
}
return FALSE;
}
/********************************************************************************
* Function Type : Private
* Parameter : bClearRead - TRUE : 终止读操作并清除读缓冲
* FALSE : 终止写操作并清除写缓冲
* Return Value : None
* Description : 清空串口所有缓冲和字符
*********************************************************************************/
void CHwClassCOM::ClearComm(BOOL bClearRead)
{
f_csForAllCom.Lock();
if(bClearRead)
PurgeComm(m_handleCOM, PURGE_RXABORT | PURGE_RXCLEAR);
else
PurgeComm(m_handleCOM, PURGE_TXABORT | PURGE_TXCLEAR);
f_csForAllCom.Unlock();
}
/********************************************************************************
* Function Type : Public
* Parameter : None
* Return Value : 长度
* Description : 获得串口输入缓冲区的长度
*********************************************************************************/
DWORD CHwClassCOM::GetCommInputBuffLen()
{
DWORD Errors;
COMSTAT Stat;
f_csForAllCom.Lock();
ClearCommError(m_handleCOM,&Errors,&Stat);
f_csForAllCom.Unlock();
return Stat.cbInQue;
}
/********************************************************************************
* Function Type : Public
* Parameter : None
* Return Value : 长度
* Description : 获得串口输出缓冲区中还有多少字节数据未发送
*********************************************************************************/
DWORD CHwClassCOM::GetCommOutBufRemainBytes()
{
DWORD Errors;
COMSTAT Stat;
f_csForAllCom.Lock();
ClearCommError(m_handleCOM,&Errors,&Stat);
f_csForAllCom.Unlock();
return Stat.cbOutQue;
}
/********************************************************************************
* Function Type : Public
* Parameter : iComNO - 串口号(如:2,表示COM2)
* nBaudRate - 波特率
* Return Value : None
* Description : 初始化串口
*********************************************************************************/
BOOL CHwClassCOM::InitializeClass(int iComNO, int nBaudRate/*=56000*/)
{
if(iComNO > 0 ) m_iComNO = iComNO;
COMMTIMEOUTS CommTimeouts;
UCHAR ucFileName[20];
//打开串口
sprintf((char*)ucFileName,"\\\\.\\COM%d",m_iComNO);
m_handleCOM = CreateFile((LPCTSTR)ucFileName,
GENERIC_READ | GENERIC_WRITE, //打开类型为可读写
0, //以独占模式打开串口
NULL, //不设置安全属性
OPEN_EXISTING, //设备不存在时打开失败
FILE_ATTRIBUTE_NORMAL, //
NULL);
if(!m_handleCOM || m_handleCOM == INVALID_HANDLE_VALUE)
{
m_csError.Format("初始化 COM%d 失败!",m_iComNO);
return FALSE;
}
DCB MyDcb;
if(GetCommState(m_handleCOM,&MyDcb))
{
MyDcb.BaudRate = nBaudRate;
MyDcb.ByteSize = 8;
MyDcb.Parity = NOPARITY;
MyDcb.StopBits = ONESTOPBIT;
MyDcb.fBinary=1;
SetCommState(m_handleCOM,&MyDcb);
}
SetupComm(m_handleCOM,MAX_COM_BUFSIZE,MAX_COM_BUFSIZE);
//进行超时设置
CommTimeouts.ReadIntervalTimeout = 0;
CommTimeouts.ReadTotalTimeoutMultiplier = 2;
CommTimeouts.ReadTotalTimeoutConstant = 15000;
CommTimeouts.WriteTotalTimeoutMultiplier = 2;
CommTimeouts.WriteTotalTimeoutConstant = 15000;
SetCommTimeouts(m_handleCOM,&CommTimeouts);
if (!SetCommTimeouts(m_handleCOM, &CommTimeouts))
{
m_csError.Format("超时设置出错");
return FALSE;
}
EscapeCommFunction(m_handleCOM,SETDTR);
GetCommProperties(m_handleCOM,&m_CommProp);
if(!(m_CommProp.dwProvCapabilities&PCF_INTTIMEOUTS))
{
m_csError.Format("设置串口参数出错");
return FALSE;
}
ClearCommBufByRead();
return TRUE;
}
CString CHwClassCOM::GetLastErrorString()
{
return m_csError;
}
void CHwClassCOM::Close()
{
if(m_handleCOM)
{
CloseHandle(m_handleCOM);
m_handleCOM = NULL;
}
}
/********************************************************************************
* Function Type : Private
* Parameter : None
* Return Value : None
* Description : 通过读操作来清空串口所有缓冲和字符
*********************************************************************************/
void CHwClassCOM::ClearCommBufByRead()
{
ClearComm ( TRUE ); ClearComm ( FALSE );
char buf[1024] = {0};
int nReadyBytes = 0;
while ( ( nReadyBytes = (int)GetCommInputBuffLen() ) > 0 )
{
Read ( buf, nReadyBytes );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -