RS232 接收数据,该如何处理
RS232 接收数据
我的软件使用rs232通信, 但是总是偶尔出现 读取了部分数据,不是全部。概率是10%。
下面是我的重叠读取rs232的代码,做了很多确保读取操作完成的处理,可是为什么还是会出现失败呢?
1. 采用重叠方式打开com口
CreateFile( strCom, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
2. 创建 重叠结构体,并设置一个事件
Overlapped.hEvent = CreateEvent(NULL,TRUE,FALSE, _T(""));
3. 采用一发一收,所以每次发送读取命令之前,清空buffer,以及终止未完成的重叠操作。
PurgeComm(m_hComm, PURGE_RXABORT | PURGE_RXCLEAR);
PurgeComm(m_hComm, PURGE_TXABORT | PURGE_TXCLEAR);
4. 设置 timeout
根据设备的通信要求,必须要达到这个程度。
commTimeOuts.ReadIntervalTimeout = 200 ;
commTimeOuts.ReadTotalTimeoutMultiplier =1;
commTimeOuts.ReadTotalTimeoutConstant = 1000;
commTimeOuts.WriteTotalTimeoutMultiplier = 1;
commTimeOuts.WriteTotalTimeoutConstant = 1;
5. 接收数据 代码
ClearCommError();//清除硬件错误
m_wrOverlapped.Offset = 0;
m_wrOverlapped.OffsetHigh = 0;
if(!ReadFile(m_hComm, m_arrMsg, nCount, &dwByteRead, &m_wrOverlapped))
{
dwError = GetLastError();
if(ERROR_IO_PENDING == dwError)
{
DWORD dwRes = WaitForSingleObject(m_wrOverlapped.hEvent, dWaitTime);//dWaitTime是通信的容忍的最大时间
if(WAIT_OBJECT_0 == dwRes) // 察看hEvent是否有信号
{
if(!GetOverlappedResult(m_hComm, &m_wrOverlapped, &dwByteRead, FALSE)) //判断接收操作是否真正完成
{
// read time fail
return;
}
else
{
// 到这了,代表数据都接收到了,可实际上只读取了部分数据呢?
}
}
}
}
------解决方案--------------------
有没有制定一个协议,知道每次发送多少呢?
------解决方案--------------------
%10的概率是怎么得出的,你用串口助手模拟的么?
粗看一遍,想的很周到。
你设的缓冲区大小够么?要多设一些,不要正好。暂时还想不到别的问题。
------解决方案--------------------
超时给短了,数据大的话会照成分包
------解决方案--------------------
是说设备端数据格式代码不可更改?
那上位机端还有两个地方注意:
1、数据读间隔,适当增大一些,可能下位机在发送数据与\0字符的过程中有些操作略,在200ms左右。某些时候会超时令上位机读操作返回。
commTimeOuts的所有参数的设置也是下位机设计通讯的估算值,不要迷信,那只是给你的参考值。
完全可以在你pc机这端调整更改,以获取数据的准确性为目标。
2、确定接收的数据格式是否是unsigned char(BYTE)格式?
3、缓冲区大小要根据数据量设置,每次接收的数据不要小于缓冲区,一般要设多一倍。
------解决方案--------------------
自发自收 设断点慢慢调!
我的软件使用rs232通信, 但是总是偶尔出现 读取了部分数据,不是全部。概率是10%。
下面是我的重叠读取rs232的代码,做了很多确保读取操作完成的处理,可是为什么还是会出现失败呢?
1. 采用重叠方式打开com口
CreateFile( strCom, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
2. 创建 重叠结构体,并设置一个事件
Overlapped.hEvent = CreateEvent(NULL,TRUE,FALSE, _T(""));
3. 采用一发一收,所以每次发送读取命令之前,清空buffer,以及终止未完成的重叠操作。
PurgeComm(m_hComm, PURGE_RXABORT | PURGE_RXCLEAR);
PurgeComm(m_hComm, PURGE_TXABORT | PURGE_TXCLEAR);
4. 设置 timeout
根据设备的通信要求,必须要达到这个程度。
commTimeOuts.ReadIntervalTimeout = 200 ;
commTimeOuts.ReadTotalTimeoutMultiplier =1;
commTimeOuts.ReadTotalTimeoutConstant = 1000;
commTimeOuts.WriteTotalTimeoutMultiplier = 1;
commTimeOuts.WriteTotalTimeoutConstant = 1;
5. 接收数据 代码
ClearCommError();//清除硬件错误
m_wrOverlapped.Offset = 0;
m_wrOverlapped.OffsetHigh = 0;
if(!ReadFile(m_hComm, m_arrMsg, nCount, &dwByteRead, &m_wrOverlapped))
{
dwError = GetLastError();
if(ERROR_IO_PENDING == dwError)
{
DWORD dwRes = WaitForSingleObject(m_wrOverlapped.hEvent, dWaitTime);//dWaitTime是通信的容忍的最大时间
if(WAIT_OBJECT_0 == dwRes) // 察看hEvent是否有信号
{
if(!GetOverlappedResult(m_hComm, &m_wrOverlapped, &dwByteRead, FALSE)) //判断接收操作是否真正完成
{
// read time fail
return;
}
else
{
// 到这了,代表数据都接收到了,可实际上只读取了部分数据呢?
}
}
}
}
------解决方案--------------------
有没有制定一个协议,知道每次发送多少呢?
------解决方案--------------------
%10的概率是怎么得出的,你用串口助手模拟的么?
粗看一遍,想的很周到。
你设的缓冲区大小够么?要多设一些,不要正好。暂时还想不到别的问题。
------解决方案--------------------
超时给短了,数据大的话会照成分包
------解决方案--------------------
是说设备端数据格式代码不可更改?
那上位机端还有两个地方注意:
1、数据读间隔,适当增大一些,可能下位机在发送数据与\0字符的过程中有些操作略,在200ms左右。某些时候会超时令上位机读操作返回。
commTimeOuts的所有参数的设置也是下位机设计通讯的估算值,不要迷信,那只是给你的参考值。
完全可以在你pc机这端调整更改,以获取数据的准确性为目标。
2、确定接收的数据格式是否是unsigned char(BYTE)格式?
3、缓冲区大小要根据数据量设置,每次接收的数据不要小于缓冲区,一般要设多一倍。
------解决方案--------------------
自发自收 设断点慢慢调!