关于可变帧长度数据的解析

关于可变帧长度数据的解析
在项目中需要解析另一主机的数据,而该主机数据是由积木式拼搭而成的可变的数据帧格式,每个积木所包含的数据长度不定,但是都小于10;
这里说明一下我在实际应用中的解决方法:
首先是和另一主机定义好数据帧格式协议,定义格式如下表:

帧头命令字帧长度参数校验和
0x5AInstructionLengthParameter1, 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

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DLT860中的CMS报文数据格式是由多个数据域组成的,主要包括头、附加头、数据域等部分。 头包含起始符、数据长度、地址、控制、校验等信息,用于标识报文的起始和结束,并确定报文的方向和类型。 附加头包含附加信息和功能码,用来说明数据域的具体信息和处理方法,包括报文的发送和接收时间、报文的优先级和传输方式,以及数据格式、加密方式等信息。 数据域是报文的核心部分,包含了从报文的源端口向目的端口传输的数据,可以分为命令域、应答域、数据域和保留域等不同类型,根据报文类型和应用场景的不同,具体格式也会有所不同。 通过这种CMS报文格式,DLT860可以实现高效、安全、可靠的数据传输和通信服务,满足工业自动化、物联网、智能电力等应用场景的需求。 ### 回答2: dlt860中的CMS报文数据格式主要由报文头和报文体组成。报文头部分包含报文类型、数据源地址、目的地址、报文序列号、时间戳等元素,用于标识和定位报文的重要属性信息。报文体部分则是实际携带数据的部分,具体格式如下: 1. 报文头部分 报文类型:1个字节,用于表示该报文的类型,通常有控制数据、测试等。不同类型的报文头中可能还会包含其他特定的元素。 数据源地址:4个字节,用于标识发送该报文的节点地址。 目的地址:4个字节,用于标识该报文最终的接收节点地址。 报文序列号:2个字节,用于标识该报文在通信过程中的序列号。 时间戳:4个字节,用于标识该报文的发送时间。 2. 报文体部分 报文体部分的具体格式和内容,在不同的数据类型中会有所不同。通常会包含数据域、校验码等元素,用于确保报文的正确性和完整性。 例如,在数据中,报文体部分的格式一般为: 起始符:1个字节,用于标识报文体部分的开始。 数据长度:2个字节,用于标识数据域的长度数据域:包含实际所传输的数据长度可变。 校验码:2个字节,用于校验整个数据的正确性。 结束符:1个字节,用于标识报文体部分的结束。 综合而言,dlt860中的CMS报文数据格式中,报文头和报文体分别负责标识和携带报文的重要信息和数据,从而保证了通信过程中数据的正确传输和解析。 ### 回答3: DLT860是一种物联网模组,其中涉及到的CMS报文数据格式是用于通信传输中的数据格式。其数据格式如下: 1. 头:固定值“0x68”,表示开始一个新的数据。 2. 数据长度:表示本数据数据字段的长度,通常为11个字节。 3. 控制域:包含3个字节,分别表示功能码、附加标志和传送方向。 4. 地址域:表示目标设备的地址,包含1个字节。 5. 应用层数据单元:是指需要传输的数据信息,通常包含多个数据段。 6. 校验码:是对整个数据进行校验的码,通常使用CRC或者LRC校验方式。 7. 尾:固定值“0x16”,表示一个数据的结束。 通过以上数据格式,DLT860可以在通信传输中准确、高效地传输数据信息,提高物联网设备的可靠性和稳定性。此外,对于不同的通信协议,也可进行相应的数据格式调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值