使用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个字节,怎么回事?
计算机仅仅从串口读数据,不用向串口写数据,因此比较简单。
思路:使用一个辅助线程来读串口。
发现问题:当设备向计算机发送数据时候,比如发送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个字节,怎么回事?
may be which could help you anything
A character was received and placed in the input buffer
串口向计算机发送六个字节,系统会受到六次EV_RXCHAR消息,第一次你就收了六个字节,以后的五次就只能收0字节了
至于为什么只受到2次EV_RXCHAR,我觉得原因应该是
if(!ReadFile(g_hCom1, g_RecvBuf1, comStat.cbInQue, &dwRecvedLen, &olRead1))
{
if(GetLastError() == ERROR_IO_PENDING)
GetOverlappedResult(g_hCom1, &olRead1, &dwTansfered, TRUE);
}
这里做了GetOverlappedResult的缘故,只有第一次和最后一次被受到了另:其实SearialCOM真的很好用,而且和你的程序很相似,可以比较一下
也就是说,在读串口的时候,一次性就读完了comStat.cbInQue数量的字节,ReadFile语句返回了TRUE。呵呵。
可以一个一个读
完了之后再处理.否则在语句3处加个对comStat.cbInQue是否为空的判断
另:BBirdlyh(BBird)说的没错