主要根据帧头和数据长度判断一包数据的,前2个字节是数据头部,第3到第4个字节是数据长度。
测试结果看截图,1ms发送一次数据,发送9万8千多个字节,没有丢数据。
代码如下所示
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t uart1_stack[1024];
struct rt_thread uart1_thread;
static UP_DIVICE_INFO g_SendInfo;
static UP_DIVICE_INFO g_RecvInfo;
static rt_uint8_t g_ComBuf[COM_CMD_SIZE*3];
static rt_uint16_t g_ComRecvLen;
/*串口数据解析进度*/
static rt_uint8_t g_Process = 0x00;
/* 判断数据协议中字节长度 */
static rt_uint8_t g_DataLen_L,g_DataLen_H;
static rt_uint16_t g_DataLen;
/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
rt_sem_release(&rx_sem);
return RT_EOK;
}
/* 解析数据头部 和数据长度*/
static void anylyse_data_head_length(char ch)
{
switch(g_Process)
{
/*解析数据头部*/
case 0x00:
if(ch == 0x4c)
{
g_Process = 0x01;
}
break;
case 0x01:
if(ch == 0x44)
{
g_Process = 0x02;
}
else
{
g_Process = 0x00;
}
break;
/*解析书籍长度*/
case 0x02:
g_DataLen_H = ch;
g_Process = 0x03;
break;
case 0x03:
g_DataLen_L = ch;
g_DataLen = ((rt_uint16_t)g_DataLen_H<<8) + g_DataLen_L;
if(g_DataLen >= COM_CMD_SIZE)
{
;
}
g_ComRecvLen = 0x04;
g_Process = 0x04;
break;
default:
break;
}
}
/* 数据处理 */
void data_parse()
{
rt_uint8_t bcc,i;
rt_uint8_t dataBuf[COM_CMD_SIZE];
memcpy(dataBuf,&g_RecvInfo,sizeof(UP_DIVICE_INFO));
//bcc 校验
bcc = 0x00;
for(i=0;i<dataBuf[2]*256 + dataBuf[3] - 1;i++)
bcc = bcc ^ dataBuf[i];
if(bcc != g_RecvInfo.Bcc)
{
g_Process = 0x00;
g_ComRecvLen = 0x00;
g_DataLen = 0x00;
return;
}
/* ·发送数据 */
rt_device_write(serial, 0, &g_RecvInfo, (sizeof(UP_DIVICE_INFO)));
}
/*启动线程*/
static void serial_thread_entry(void *parameter)
{
char ch;
while (1)
{
while (rt_device_read(serial, -1, &ch, 1) != 1)
{
rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
}
//判断缓存区是否已满
if(g_ComRecvLen >= COM_CMD_SIZE)
{
g_ComRecvLen = 0;
}
g_ComBuf[g_ComRecvLen] = ch;
g_ComRecvLen++;
/* 解析数据头部和长度 */
anylyse_data_head_length(ch);
/* 解析完数据头部和长度 */
if(g_Process == 0x04)
{
if(g_ComRecvLen >= g_DataLen)
{
memcpy(&g_RecvInfo,g_ComBuf,g_DataLen);
/* 数据处理 */
data_parse();
/* 复位,准备下一包数据接收 */
g_Process = 0x00;
g_ComRecvLen = 0x00;
g_DataLen = 0x00;
}
}
/* 接收的数据超过需要接收的数据时*/
if(g_Process >= 0x01)
{
if(g_ComRecvLen >= sizeof(UP_DIVICE_INFO)+1)
{
/* 复位*/
g_Process = 0x00;
g_ComRecvLen = 0x00;
g_DataLen = 0x00;
}
}
}
}