当前位置: 代码迷 >> WinCE >> Win CE下串口接收数据不完整?解决方案
  详细解决方案

Win CE下串口接收数据不完整?解决方案

热度:190   发布时间:2016-04-28 13:49:07.0
Win CE下串口接收数据不完整???
大家好,我在WinCE下采样已封装类进行串口数据收发,串口接收数据是新建一个监视线程,主要参数设置为:串口间隔超时为MAXDWORD,读系数与读常量为0;数据收发缓冲区分配32KB大小,先用SetCommMask指定接收事件。
  监视线程主要部分代码如下:
  while (TRUE)

//如果收到读线程退出信号,则退出线程
if (WaitForSingleObject(ceSeries->m_hReadCloseEvent,500) == WAIT_OBJECT_0)
break;

if (WaitCommEvent(ceSeries->m_hComm,&evtMask,NULL))
{
SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );
//表示串口收到字符
if (evtMask & EV_RXCHAR) 
{
ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState);
willReadLen = cmState.cbInQue ;//要读取的字节数
if (willReadLen <= 0)
{
continue;
}
//分配内存
readBuf = new BYTE[willReadLen];
ZeroMemory(readBuf,willReadLen); //接收得数据初始化为0

//读取串口数据
ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);

//如果读取的数据大于0,
if (actualReadLen>0)
{
//触发读取回调函数
if (ceSeries->m_OnSeriesRead)
{
ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen);
}
}
//释放内存
delete[] readBuf;
readBuf = NULL;
}
}
  ceSeries为封装类对象,m_OnSeriesRead为回调函数。现在的问题是,我发送一个18字节的数据段,结果在ReadFile设置断点,一般willReadLen为8,有时候也为18,因为我后面要严重数据包的格式,所以如果不是一次性读入18个字节则无法通过验证。
  我想请问,为什么它不能一次性接收18个数据段呢???请大家帮忙看一下,谢谢!!!

------解决方案--------------------
提高波特率可以显著减少数据截断的情况。或者在read之前给一个人为的延时也可以

当然最好是自己做数据拼接

给一段我拼接数据的代码参考

作用:
执行GetAnswer后最长5秒(10*500)延时,如果没收到数据则返回;
一旦收到数据,则200ms后再次ReadCom,如果收到则做数据拼接,继续延时200ms再ReadCom,如果未收到,退出。

C/C++ code
int GetAnswer(unsigned char * pData, UINT16 MaxLen){    int result = 0;    int datalen = 0;    unsigned char * pDataSource = pData;    for (int i=0;i<10;i++)    {        result = ReadCom(pData,MaxLen-datalen);        if (result<0) return result;        else if (result==0)        {            if (datalen) break;            Sleep(500);        }        else        {            datalen += result;            pData += result;            i--;            Sleep(200);        }                }        if (DebugFunc)        DebugFunc(pDataSource,datalen,1);    return datalen;}int ReadCom(unsigned char * pData, UINT16 MaxLen)//从端口读取数据//pData:数据存放首地址//MaxLen:最大读取长度//返回:正常返回读取到的数据长度 否则返回错误列表//非导出函数{    if (!CheckCom())          return ER_COMINVALID;    DWORD dwEvent = 0;    DWORD ReceiveLength = 0;    static  COMSTAT  comstat;      static  BOOL  bSendData = FALSE;    ZeroMemory(&comstat, sizeof(COMSTAT));    ClearCommError(hCom, &dwEvent, &comstat);    if (!ReadFile(hCom,                   pData,                   MaxLen,                   &ReceiveLength,                   NULL))    {        if (GetLastError() != ERROR_IO_PENDING)         {            return ER_COMREADFAIL;        }    }    else      {         return ReceiveLength;    }       PurgeComm(hCom,PURGE_RXCLEAR);    return (ReceiveLength);}
------解决方案--------------------
我代码里面移动readBuf是因为readBuf是个局部变量,函数内部移动不会影响外部

你要是直接把我的代码插入你的某个函数,而你又用到了readBuf,自然就不能移动了啊。

方法也简单,要么你在移动之前记录readBuf的初值,拼接完后再恢复。要么你重新弄个指针,把readBuf赋给它,你再移那个指针不就可以了
  相关解决方案