在用PDA接收我们的设备中的数据是总是有数据丢失
于是我做了一个相关的实验:
串口波特率设为19200,PC机上用串口调试助手用45ms发1000个字节左右,可是测到PDA的串口缓冲区总是少几个字节!
这能说明是PDA不能处理在这么样的的时间里发来这么多的数据吗???
应该不会把,pda的处理能力没那么差。你有硬件流控或者软件流控吗,如果没有也许会发生溢出,这就需要处理程序要足够快地读走数据,不过如果使用中断式处理问题应该不大。
问题的主要原因并不在PDA,而在于你的处理代码,
因为:
1.串口驱动一般默认buffer超过1000字节,而且你的波特率那么低,一般不会发生buffer溢出的问题。
2.流控是需要注意的问题,在你配置打开串口时必须填写该类参数,但是这只影响到数据的正确性,并不直接造成数据减少。
3.最主要的问题在于,串口驱动的原理是一个字节一个直接传输的,也就是每次只能传8位,这就造成,你误以为每帧数据会按照你设想的传来一个完整的,而实际却总是缺了后面一段(注意下面ReadIntervalTimeout的数值,建议如果115200可填1,会有改善),所以你这里必须做一个完整的流程,保证数据不会丢失。一般做法是接受到RXCHAR之后,做一个循环去不停读取buffer,一直读到空再跳出,然后等待下一次RXCHAR。这里必须这么做,因为操作系统并不是等待你设想的每帧结束才产生这个event,而是根据系统中断响应时间相对随机产生的。
这里给出一个实际的配置,是有流控的,并且注意timeout那一段需要根据你的机器性能来调整
hHandle = CreateFile(szComName, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if(hHandle != INVALID_HANDLE_VALUE)
{
// Get serial port state
memset(&dcb, 0, sizeof(DCB));
GetCommState(hHandle, &dcb);
// Set com port parameters
dcb.fBinary = TRUE;
dcb.fParity = TRUE;
dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fTXContinueOnXoff = TRUE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fAbortOnError = FALSE;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.BaudRate = dwBaudRate ;
SetCommState(hHandle, &dcb);
// Set serial port event mask
SetCommMask(hHandle, EV_BREAK | EV_ERR | EV_RXCHAR) ;
// Set serial port access time out
GetCommTimeouts(hHandle, &cto);
cto.WriteTotalTimeoutConstant = 100;
cto.WriteTotalTimeoutMultiplier = 1;
cto.ReadTotalTimeoutConstant = 100;
cto.ReadTotalTimeoutMultiplier = 1;
cto.ReadIntervalTimeout = 2;
SetCommTimeouts(hHandle,&cto);
}
nbcool======== 大侠
我还是不太懂你所说的
SetupComm()可将串口区设为大于1000个字节,那就不用来了一个字节(EV_RXCHAR)我就读出串口中的数据了吧.我也就用串口助手sscom3.2发了1000个字节左右每一次发20个字节,1ms定时发送一次.当波特率为19200时,我用ClearCommError查看串口区的数据总是少几个数据.我将定时发送改为5ms,就能全部收到.如果将波特率改为9600时,1ms定时发送数据,也能全部收到数据.
我认为要分两步来看:1.设备将数据传过来了没有;2.PDA将数据接收完了没有。
sczx888==
1.设备肯定将数据传过来了,我们的设备已经用了几年,用VC软件接收的,现在改用PDA.
2.PDA等的时间够长.
你确实必须先看懂我上面说的内容才行。另外我告诉你一个测试结果,在115200的速率下,通过PC发送1M的数据给PDA,无任何流控的情况下,只丢失了144字节,丢失率0.013%。SetupComm 这个API并不一定能设置串口驱动的buffer,你必须看到驱动源码才能确定,在WM2005上,驱动的buffer是通过注册表配置的,并不是使用这个API。
另外有一个问题,就是你的PDA等待时间足够长这是不对的,必须等待时间足够短才行。我建议你写个测试程序,就是采用循环读取EV_RXCHAR的方式,保存到内存中,然后一次性存储到文件里来确认数据丢失问题。千万不要边读边写。还有,你在PDA上EV_RXCHAR的buffer最好在3k左右。
估计是你的串口软件有问题,我发现“串口调试助手”这个软件在波特率低的时候有问题。
估计他的程序是这样处理的:
while(1)
{
sleep( X ms);
SendCommData( pBuff, len);
}
以上是简单的示例,表达的意识是:当发送的 len 长度的数据所需要的时间超过 X ms 的时候,要丢数据。