关于可变帧长度数据的解析
在项目中需要解析另一主机的数据,而该主机数据是由积木式拼搭而成的可变的数据帧格式,每个积木所包含的数据长度不定,但是都小于10;
这里说明一下我在实际应用中的解决方法:
首先是和另一主机定义好数据帧格式协议,定义格式如下表:
帧头 | 命令字 | 帧长度 | 参数 | 校验和 |
---|---|---|---|---|
0x5A | Instruction | Length | Parameter1, Parameter2,Parameter3……. | Check Sum |
帧头: 收到0x5A表示有数据到达;
命令字:每个命令字代表本帧数据的含义;
帧长度:表示本条帧数据的长度,Length = 参数长度;
参数: 除了命令字外,补充其他更详细的信息,这里包括可变的积木数据;
校验和:Check Sum = Instruction + Length + Parameter1 + Parameter2 + 。。。+ ParameterN
下表是命令字的相关说明:
参数说明:由于每个模块参数都有所不同,所以数据帧中不同ID,相同位置代表的含义也不同,在这里做个总结
此表格不完全…
具体的C代码解析
串口中将数据转存,同时置一个标志位:
CTRL_FLAG.BLOCK_FIRST_ROW_RECEIVE_OK_FLAG = TRUE ;///数据接收并校验完成标志位
CTRL_COUNT.BLOCK_CNT = UART_RX3_BUF[UART_RX3_BUF[2] + 2] ;///BB的个数
for(i=0;i<UART_RX3_CNT;i++)
{
UART_RX3_FIRST_ROW_DATA_BUF[i]=UART_RX3_BUF[i];///将接收的数据转存
}
然后在程序中判断数据接收标志位是否进行解析,解析函数如下:
if (CTRL_FLAG.BLOCK_FIRST_ROW_RECEIVE_OK_FLAG == TRUE)///数据接收并校验完成标志位
{
block_data_receive_finish_ack(0x03);///数据接收完成 后告知开始模块 0822 ;
for(i=0;i<CTRL_COUNT.BLOCK_CNT ;i++)///直到所有的数据都处理完成才退出
{
single_block_data_handle(i,UART_RX3_FIRST_ROW_DATA_BUF,block_sequence,1);///第1个BB,数据数组,数组起点(当前BB ID)
BLOCK_SEQUENCE[i] = UART_RX3_FIRST_ROW_DATA_BUF[block_sequence]; ///第1个BB的ID
block_length_data = UART_RX3_FIRST_ROW_DATA_BUF[block_sequence-1]; ///第1个BB 的数据长度
block_sequence = block_sequence + block_length_data + 1; ///计算下一个BB的ID数组位置(将这个BB长度+5) 供下一次传参使用
}
}
根据积木参数的数据进行解析,一个函数搞定:
/*
u8 sequence 当前是第几个积木的数据
u8 *UART_RX3_FIRST_ROW_DATA_BUF 接收到的数据区,待处理
u8 number 当前处理的这个积木在数据区的开始
u8 row 是哪一行的数据
*/
void single_block_data_handle(u8 sequence ,u8 *DATA_BUF , u8 number,u8 row)///处理当前单积木模块的数据
{
u8 i = 0 ;
// PARAMETER *PARAMETER_DATA ;
switch( DATA_BUF[number])///判断当前是那个模块
{
// case 1:///不存在1模块
// break;
case 2: ///模块2 ---3参数
case 5: ///模块5 ---3参数
for(i = 0 ; i< 3 ; i ++)
{
if(row ==1)
BLOCK_DATA[sequence][i] = DATA_BUF[number+i+1];//
else if(row ==2)
BLOCK_SECOND_DATA[sequence][i] = DATA_BUF[number+i+1];///
else if(row ==3)
BLOCK_THIRD_DATA[sequence][i] = DATA_BUF[number+i+1];///
}
break;
case 3: ///模块3 ---2参数
case 4: ///模块4 ---2参数
case 7: ///模块7 ---2参数
for(i = 0 ; i< 2 ; i ++)
{
if(row ==1)
BLOCK_DATA[sequence][i] = DATA_BUF[number+i+1];///
else if(row ==2)
BLOCK_SECOND_DATA[sequence][i] = DATA_BUF[number+i+1];///
else if(row ==3)
BLOCK_THIRD_DATA[sequence][i] = DATA_BUF[number+i+1];///
}
break;
case 6: ///模块6 ---1参数
case 8: ///模块8 左 ---1参数
if(row ==1)
BLOCK_DATA[sequence][0] = DATA_BUF[number+1];///
else if(row ==2)
BLOCK_SECOND_DATA[sequence][0] = DATA_BUF[number+1];///
else if(row ==3)
BLOCK_THIRD_DATA[sequence][0] = DATA_BUF[number+1];///
break;
case 9: ///模块9 右
break;
case 0x0B: ///舵机 抛球
if(row ==1)
BLOCK_DATA[sequence][0] = DATA_BUF[number+1];///
else if(row ==2)
BLOCK_SECOND_DATA[sequence][0] = DATA_BUF[number+1];///
else if(row ==3)
BLOCK_THIRD_DATA[sequence][0] = DATA_BUF[number+1];///
break;
default:
break;
}
}
致此,积木的数据解析已经完成,
积木的数据存储在二位数组:BLOCK_DATA[][],
积木顺序存储在BLOCK_SEQUENCE[];
执行函数
/*
block_sequence 是第几个模块顺序
返回值:当前模块是否执行完成
*/
u8 block_data_deal(u8 block_sequence)///
{
if((block_sequence!=last_block_sequence)&&(BLOCK_STATUS == 1))///数据回传,只回传一次 仅在是开始的时候执行
{
block_data_receive_finish_ack(0x02);
last_block_sequence = block_sequence;
}
if (BLOCK_STATUS == 3) ///暂停
{
Pause_Stop();
}
else if(BLOCK_STATUS == 1)///开始
{
switch (BLOCK_SEQUENCE[block_sequence])///判断是哪个积木模块ID
{
case 2:
return (1);
case 3:
return (1);
case 4:
return (1);
case 5:///模块
return (1);
case 6:///模块
return (1);
case 7:
return (1);
case 8:
return (1);
case 9:
return (1);
case 10:
return (1);
case 11:
return (1);
default:
break;
}
}
}
block_data_deal 负责执行数据中的命令,完成返回1,未完成返回0,用以顺序执行。
第一次写稿,只是想表述一种思想,不知道表述清楚与否,欢迎交流扣:50944-2881