查看: 1488|回复: 0
打印 上一主题 下一主题

串口数据接收小结

[复制链接]
跳转到指定楼层
沙发
发表于 2016-5-8 23:19:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
之前使用串口总碰到数据接收不完整的情况,发现有时候可能并不是要去修改串口,而是我们的串口接收结构需要改一下了,因为串口本身一次把我们需要的所有数据都读到。

对于串口的数据接收,串口本身无法保证数据的完整性。因为这里不是它需要做的,对于应用层的数据只有应用层知道什么样的数据是完整的。串口只是接收数据,不能要求它什么都知道。所以应用层的数据是否完整只能由应用层自己来判断。在接收时,添加必要的数据校验。大体思路如下:
如果判断数据不完整,就继续接收。如果完整,就退出接收。等待必要的时间后和次数后,如果数据依旧不完整就退出。


  接收数据-------------|
       |                   |未超过要求的时间或次数
判断数据完整---数据不完整
       |                  |
       |数据完整      |超过要求的时间或次数
       |------------------|
     退出

根据以上思路,完成了下列代码:
  • typedef int (*ProJudgeFun)(void * data1, void *data2, void *data3);
  • struct SerialRec{
  •     int            s32Port;
  •     unsigned char  *pData;
  •     struct timeval *pTv;
  •     ProJudgeFun    fJudge;
  •     unsigned short u16DataSize;
  •     unsigned short u16RecSize;
  • };
  • int ReadSerialPort(struct SerialRec *pSerialRec)
  • {
  • #define READ_DATA_SIZE   255
  •     unsigned char u8CycleTime = 3;
  •     short int     u16length   = 0;
  •     unsigned short u16PreReadNum;
  •     unsigned char  u8Data[256];
  •     unsigned char *pData = u8Data;
  •     unsigned char u8Start;
  •     unsigned char u8ReadSize;
  •     unsigned char u8Ret = FALSE;
  •     if(pSerialRec == NULL)
  •         return u8Ret;
  •     if(pSerialRec->u16DataSize > READ_DATA_SIZE)
  •     {
  •         u16PreReadNum = READ_DATA_SIZE;
  •     }
  •     else
  •     {
  •         u16PreReadNum = pSerialRec->u16DataSize;
  •     }
  •     do{
  •         if(FALSE == is_ready_read(pSerialRec->s32Port, pSerialRec->pTv))
  •             break;
  •         u8ReadSize = read(pSerialRec->s32Port, pData, u16PreReadNum);
  •         if(u8ReadSize != 0)
  •         {
  •             u16length += u8ReadSize;
  •             pData     += u8ReadSize;
  •             tcflush(fd3, TCIOFLUSH);  //clear the rest of the data  in the fd3
  •             if(TRUE == pSerialRec->fJudge(&u8Start, u8Data, u16length))
  •             {
  •                 u16length = u16length - u8Start;
  •                 /*===Copy the data after A===*/
  •                 memcpy(pSerialRec->pData, &u8Data[u8Start],u16length);
  •                 pSerialRec->u16RecSize = u16length;
  •                 u8Ret = TRUE;
  •                 break;
  •             }
  •             u8CycleTime--;
  •             pSerialRec->pTv->tv_sec  = 1;
  •             pSerialRec->pTv->tv_usec = 0;
  •             u16PreReadNum            -= u8ReadSize;
  •             //printf_str_int("####/***read continue*****/####");
  •         }
  •         else
  •         {
  •             u8CycleTime = 0;
  •         }
  •     }while(u8CycleTime);
  •     return u8Ret;
  • }

[color=rgb(51, 102, 153) !important]复制代码








回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表