之前使用串口总碰到数据接收不完整的情况,发现有时候可能并不是要去修改串口,而是我们的串口接收结构需要改一下了,因为串口本身一次把我们需要的所有数据都读到。
对于串口的数据接收,串口本身无法保证数据的完整性。因为这里不是它需要做的,对于应用层的数据只有应用层知道什么样的数据是完整的。串口只是接收数据,不能要求它什么都知道。所以应用层的数据是否完整只能由应用层自己来判断。在接收时,添加必要的数据校验。大体思路如下:
如果判断数据不完整,就继续接收。如果完整,就退出接收。等待必要的时间后和次数后,如果数据依旧不完整就退出。
接收数据-------------|
| |未超过要求的时间或次数
判断数据完整---数据不完整
| |
|数据完整 |超过要求的时间或次数
|------------------|
退出
根据以上思路,完成了下列代码:- 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]复制代码
|
|
|
|