对于串口的数据接收,串口本身无法保证数据的完整性。因为这里不是它需要做的,对于应用层的数据只有应用层知道什么样的数据是完整的。串口只是接收数据,不能要求它什么都知道。所以应用层的数据是否完整只能由应用层自己来判断。在接收时,添加必要的数据校验。大体思路如下:
如果判断数据不完整,就继续接收。如果完整,就退出接收。等待必要的时间后和次数后,如果数据依旧不完整就退出。
接收数据-------------|
| |未超过要求的时间或次数
判断数据完整---数据不完整
| |
|数据完整 |超过要求的时间或次数
|------------------|
退出
根据这个想法,写了下边一段代码:
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;
unsigned short 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;
}