串口通信,比如接收6个字节,会触发两次,第一次接收6个字节,第二次接收0个字节
使用API编程,异步通信方式。
计算机仅仅从串口读数据,不用向串口写数据,因此比较简单。
思路:使用一个辅助线程来读串口。
发现问题:当设备向计算机发送数据时候,比如发送6个字节,计算机会接收两次,第一次接收6个字节,第二次接收0个字节。
这里,我给出主要代码:
一、打开串口1,以及串口主要设置信息:
g_hCom1 = CreateFile("COM1",
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL
);
波特率9600,校验,缓冲区大小,超时等等,都设置好。
//超时
tmOuts.ReadIntervalTimeout = 500;
tmOuts.ReadTotalTimeoutMultiplier = 0;
tmOuts.ReadTotalTimeoutConstant = 1000;
//设置触发事件为
SetCommMask(hCom, EV_RXCHAR);
二、监控串口1的线程,主要代码:
UINT WatchComm1Thread(LPVOID pParam)
{
DWORD dwMask, dwTransfered;
OVERLAPPED ol;
memset(&ol, 0, sizeof(OVERLAPPED));
ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
while(1)
{
if(!WaitCommEvent(g_hCom1 , &dwMask, &ol))//语句1
{
if(GetLastError() == ERROR_IO_PENDING)
GetOverlappedResult(g_hCom1, &ol, &dwTransfered, TRUE);//语句2
}
if((dwMask & EV_RXCHAR) == EV_RXCHAR)
{
int iReadLen = ReadComm1();//语句3
}
}
}
三、读串口函数ReadComm1()主要代码:
int ReadComm1()
{
DWORD dwError, dwRecvedLen = 0, dwTansfered;
COMSTAT comStat;
OVERLAPPED olRead1;
memset(&olRead1, 0, sizeof(OVERLAPPED));
olRead1.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ClearCommError(g_hCom1, &dwError, &comStat);
if(comStat.cbInQue > 0)
{
if(!ReadFile(g_hCom1, g_RecvBuf1, comStat.cbInQue, &dwRecvedLen, &olRead1))
{
if(GetLastError() == ERROR_IO_PENDING)
GetOverlappedResult(g_hCom1, &olRead1, &dwTansfered, TRUE);
}
}
CloseHandle(olRead1.hEvent);
return (int)dwRecvedLen;
}
/////////////////////////////////////////
我开始调试了:
我在“语句1”设置断点。
程序运行起来,很快执行到“语句1”处,单步运行,使其执行到“语句2”,再单步运行,因为设备一直不向计算机发送数据,“语句2”一直不会返回,这些都表明程序是好的。
设备向计算机发送6个字节,“语句2”立即返回,通过单步,可以发现“语句3”读取了6个字节,一切正常。然后继续单步,使其运行到“语句1”处,单步运行,使其执行到“语句2”,再单步运行,却发现“语句2”立即返回,(可是现在并串口中没有数据可读啊,“语句2”为什么会立即返回呢),再单步,程序符合“if((dwMask & EV_RXCHAR) == EV_RXCHAR)”的条件,运行到“语句3”,解下来就可以发现“语句3”读到了0个字节,怎么回事?
////////////////////////////
如果设备仅仅向计算机发送一个字节的话,就不会出现触发两次的情况,而是仅仅触发一次,然后正确接收到数据。
问题点数:60、回复次数:3Top
1 楼zhaoxinghan(我还真不是一般的菜........)回复于 2006-03-08 21:29:57 得分 20
我以前用的是MOXA提供的串口dll,基本构架应该是
1 先初始化函数,收到字节就触发一个回调函数。
2 在回调函数里查看收到的字节数,如果为0就返回,不为0就全部Read出来,然后放到一个全局的缓冲里,然后发出一个收到字符的消息;
3 主程序接到消息触发自己定义的一个查看函数,查看函数的作用是将收到的字节从缓冲里拿出来,然后和以前的数据组成到一起,然后判断是否到达数据的帧尾部。如果到达帧尾部,则取出完整的一帧数据,否则返回。
PS:串口的事件触发不是全收到才触发的,它是一字节一字节的接收的,所以每次触发的字节数不固定。要在触发事件里将收到的字节读出来放到一个全局的缓冲里。然后在外边判断是否收满一帧。Top
2 楼newcore(to be or not to be, it's a question.)回复于 2006-03-08 21:53:32 得分 20
关注,我没有遇到这样的情况,大概流程和你的代码差不多~~,收到数据,去读都能回读到数据。不过如楼上所说,可以加入在读数据时判断字节数是否是0
Top
3 楼oyljerry(【勇敢的心】→ ㊣提拉米苏√㊣)回复于 2006-03-09 14:39:40 得分 20
判断一下内容,全部接收下来再处理Top




