1. 背景

      用VS2010 MFC,读取照度计的值,时间仓促没有做CRC校验。照度计是RS485通讯。

2. 代码

HANDLE xxxDlg::OpenCOM(LPCTSTR COM)
{
	//打开串口
	HANDLE hCom;
	hCom = CreateFile(COM,
		GENERIC_READ|GENERIC_WRITE,
		0,//独占方式
		NULL,
		OPEN_EXISTING,//打开而不是创建
		0,//同步方式打开
		NULL);

	if ((HANDLE)-1 == hCom)
	{
		//AfxMessageBox("打开COM失败");
		return NULL;
	}
	else
	{
		//AfxMessageBox("打开COM成功");
		return hCom;
	}
}
/*配置照度计串口*/
void xxxDlg::ComCfg(HANDLE hCom)
{
	SetupComm(hCom,1024,1024);  //设置输入输出缓冲区的大小都为1024
	COMMTIMEOUTS TimeOuts;    
	TimeOuts.ReadIntervalTimeout = 1000;
	/*设定读超时*/
	TimeOuts.ReadTotalTimeoutMultiplier = 500;//时间系数
	TimeOuts.ReadTotalTimeoutConstant = 5000; //时间常量
	/*设定写超时*/
	TimeOuts.WriteTotalTimeoutMultiplier = 500;
	TimeOuts.WriteTotalTimeoutConstant = 2000;
	SetCommTimeouts(hCom, &TimeOuts);

	DCB dcb;
	GetCommState(hCom, &dcb);   //获得COM口的设备控制块,从而获得相关参数
	dcb.BaudRate = 9600;        //设置比特率
	dcb.ByteSize = 8;           //设置通信字节位数
	dcb.Parity = NOPARITY;      //指定奇偶校验方法(NOPARITY:无校验; EVENPARITY:偶校验; MARKPARITY:标记校验; ODDPARITY:奇校验)
	dcb.StopBits = ONESTOPBIT;  //设置停止位(TWOSTOPBITS:2位停止位;ONESTOPBIT:1位停止位;ON5STOPBITS:1.5位停止位)
	SetCommState(hCom, &dcb);
	PurgeComm(hCom, PURGE_TXCLEAR|PURGE_RXCLEAR); //清空缓冲区,在读写串口之前调用
	//AfxMessageBox("COM配置成功");
}

/*写串口数据*/
BOOL xxxDlg::ComWrite_cmm(HANDLE hCom)
{
	unsigned char OutBuffer[8] = {0x01,0x03,0x00,0x07,0x00,0x02,0x75,0xCA};//查询照度的问询指令
	DWORD dwByteWrite;
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	BOOL bWriteStat;
	ClearCommError(hCom, &dwErrorFlags,&ComStat);
	bWriteStat = WriteFile(hCom, OutBuffer,sizeof(OutBuffer),&dwByteWrite,NULL);
	if(!bWriteStat)
	{
		//AfxMessageBox("写串口失败");
		return FALSE;
	}
	PurgeComm ( hCom , PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
	return TRUE;
}

/*读串口数据*/
BOOL xxxDlg::ComRead_cmm(HANDLE hCom)
{
	unsigned char str[9];
	DWORD wCount = 9;//读取的字节数
	BOOL bReadStat;
	bReadStat=ReadFile(hCom,str,sizeof(str),&wCount,NULL);

	int lux = str[3]*256*256*256+str[4]*256*256+str[5]*256+str[6];
	if(!bReadStat)
	{
		//AfxMessageBox("读串口失败!"); 
		return FALSE; 
	} 
	//AfxMessageBox("读串口成功!");
	return TRUE; //同步写串口
}
/* 获取当前照度值 */
读串口获得照度计数据 lux 全局变量*/
void xxxDlg::GetLux()
{
	//AfxMessageBox("打开COM");
	HANDLE hCom;
	hCom = OpenCOM("COM1");//如果端口号大于等于10那么,要写成"\\.\COM10"
	ComCfg(hCom);
	ComWrite_cmm(hCom);
	ComRead_cmm(hCom);
}

3. tips

(1)在MFC多线程中,使用UpdataData(FALSE)是会报错(Debug Assertion Failed!)

那就不用debug了 用release

(2)端口号COM两位以及以上时,需要用 \\.\COM10,这样的命名,负责会打开串口失败!

(3)char类型的16进制数,可以直接转化成int类型的十进制数,挺好。(lux为照度值)

4. 说明

别忘了在头文件中定义这些函数,如果有一些参数没有定义,那有可能是定义为类的成员变量,或者全局变量。


版权声明:本文为qiangbaa原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qiangbaa/article/details/109093210