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

📄 hwclasscom.cpp

📁 网络家电
💻 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 + -