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 版权协议,转载请附上原文出处链接和本声明。