解析不定长hex格式指令-自定义协议

参考工程

主动解析样例工程2

注意

每个页面仅建议在一个定时器中读取串口缓冲区的数据,在多个定时器中读取串口缓冲区的数据容易照成逻辑混乱。

假设串口屏获取4个led灯的开关状态,串口屏需要解析的参数为灯的状态(开或关)

并且还要解析一个值为-32768到32767范围的温度值

帧头为0x55 ,帧尾为3个0xff

u[1]为AA时代表每次传输灯的状态,每帧9字节

u[2]为AB时代表传输当前温度值,每帧7字节

//含义:当前传输的是灯的数据,4个灯状态分别为:开、开、开、开
55 AA 01 01 01 01 ff ff ff

//含义:当前传输的是灯的数据,4个灯状态分别为:关、关、关、关
55 AA 00 00 00 00 ff ff ff

//含义:当前传输的是灯的数据,4个灯状态分别为:关、开、关、开
55 AA 00 01 00 01 ff ff ff

//含义:当前传输的是灯的数据,4个灯状态分别为:开、关、开、关
55 AA 01 00 01 00 ff ff ff

//含义:当前传输的是温度的数据(小端模式),温度值是03E8,转换为10进制是1000
55 AB E8 03 FF FF FF

//含义:当前传输的是温度的数据(小端模式),温度值是FFB0,转换为10进制是-80
55 AB B0 FF FF FF FF

program.s中的配置如图所示

 1//以下代码只在上电时运行一次,一般用于全局变量定义和上电初始化数据
 2//全局变量定义目前仅支持4字节有符号整形(int),不支持其他类型的全局变量声明,如需使用字符串类型可以在页面中使用变量控件来实现
 3int sys0=0,sys1=0,sys2=0
 4
 5//最短一帧的数据
 6int shortestLength=7
 7
 8int frameLength,getFrameFlag
 9bauds=115200 //波特率256000
10recmod=1    //打开主动解析
11page 0                       //上电刷新第0页

解析定时器(tim为50)中的代码如下图所示

 1while(usize>=shortestLength&&getFrameFlag==0)
 2{
 3  if(usize>=9&&u[0]==0x55&&u[1]==0xAA&&u[6]==0xFF&&u[7]==0xFF&&u[8]==0xFF)
 4  {
 5    //找到帧头,退出循环
 6    getFrameFlag=1
 7    frameLength=9
 8  }else if(usize>=7&&u[0]==0x55&&u[1]==0xAB&&u[4]==0xFF&&u[5]==0xFF&&u[6]==0xFF)
 9  {
10    //找到帧头,退出循环
11    getFrameFlag=2
12    frameLength=7
13  }else
14  {
15    //如果帧头不对,就一直删除1个字节,直到不满足条件退出循环
16    udelete 1
17  }
18}
19if(getFrameFlag!=0)
20{
21  if(getFrameFlag==1)
22  {
23    n1.val=u[2]
24    n2.val=u[3]
25    n3.val=u[4]
26    n4.val=u[5]
27  }else if(getFrameFlag==2)
28  {
29    sys0=0  //必须清零,否则否则高字节有数据时将会错误
30    ucopy sys0,2,2,0
31    //判断温度值的正负,大于32767为负数,通过负数补码获取原码
32    if(sys0>32767)
33    {
34      sys0-=65536
35    }
36    x0.val=sys0 //x0是一个虚拟浮点数控件
37  }
38  udelete frameLength //删除已经解析过的数据
39  getFrameFlag=0 //清空标记变量
40}

帧头为0xFF ,帧尾为0d 0a

u[1]为AA时代表每次传输灯的状态,每帧9字节

u[1]为AB时代表传输当前温度值,每帧7字节

u[2]代表这帧的长度

//含义:当前传输的是灯的数据,9字节长度,4个灯状态分别为:开、开、开、开
FF AA 09 01 01 01 01 0D 0A

//含义:当前传输的是灯的数据,9字节长度,4个灯状态分别为:关、关、关、关
FF AA 09 00 00 00 00 0D 0A

//含义:当前传输的是灯的数据,9字节长度,4个灯状态分别为:关、开、关、开
FF AA 09 00 01 00 01 0D 0A

//含义:当前传输的是灯的数据,9字节长度,4个灯状态分别为:开、关、开、关
FF AA 09 01 00 01 00 0D 0A

//含义:当前传输的是温度的数据(小端模式),7字节长度,温度值是03E8,转换为10进制是1000
FF AB 07 E8 03 0D 0A

//含义:当前传输的是温度的数据(小端模式),7字节长度,温度值是FFB0,转换为10进制是-80
FF AB 07 B0 FF 0D 0A

program.s中的配置如图所示

 1//以下代码只在上电时运行一次,一般用于全局变量定义和上电初始化数据
 2//全局变量定义目前仅支持4字节有符号整形(int),不支持其他类型的全局变量声明,如需使用字符串类型可以在页面中使用变量控件来实现
 3int sys0=0,sys1=0,sys2=0
 4
 5//最短一帧的数据
 6int shortestLength=7
 7
 8int frameLength,getFrameFlag
 9bauds=115200 //波特率256000
10recmod=1    //打开主动解析
11page 0                       //上电刷新第0页

解析定时器(tim为50)中的代码如下图所示

 1while(usize>=shortestLength&&getFrameFlag==0)
 2{
 3  frameLength=u[2]
 4  if(usize>=frameLength&&u[0]==0xff&&u[frameLength-2]==0x0d&&u[frameLength-1]==0x0a)
 5  {
 6    //找到帧头,退出循环
 7    getFrameFlag=1
 8    printh ae
 9  }else
10  {
11    //如果帧头不对,就一直删除1个字节,直到不满足条件退出循环
12    udelete 1
13    printh af
14  }
15}
16if(getFrameFlag!=0)
17{
18  if(u[1]==0xAA)
19  {
20    n1.val=u[3]
21    n2.val=u[4]
22    n3.val=u[5]
23    n4.val=u[6]
24  }else if(u[1]==0xAB)
25  {
26    sys0=0  //必须清零,否则否则高字节有数据时将会错误
27    ucopy sys0,3,2,0
28    //判断温度值的正负,大于32767为负数,通过负数补码获取原码
29    if(sys0>32767)
30    {
31      sys0-=65536
32    }
33    x0.val=sys0
34  }
35  udelete frameLength //删除已经解析过的数据
36  getFrameFlag=0 //清空标记变量
37}

传输不定长的字符串

帧头为0xFF

u[1]为00时代表传输给t0,u[1]为01时代表传输给t1

u[2]代表字符串的长度

//含义:给t0文本赋值为“淘晶驰电子”,文本长度10,1汉字占2字节
FF 00 0A CC D4 BE A7 B3 DB B5 E7 D7 D3

//含义:给t1文本赋值为“TJC”,文本长度3
FF 01 03 54 4A 43

program.s中的配置如图所示

 1//以下代码只在上电时运行一次,一般用于全局变量定义和上电初始化数据
 2//全局变量定义目前仅支持4字节有符号整形(int),不支持其他类型的全局变量声明,如需使用字符串类型可以在页面中使用变量控件来实现
 3int sys0=0,sys1=0,sys2=0
 4
 5//frameLength:每帧数据长度
 6//getFrameFlag:是否找到帧头或帧尾标记
 7int frameLength,getFrameFlag,strLength
 8
 9//当字符串长度为0时,最短的帧长度为3
10int shortestLength=3
11
12bauds=115200 //波特率115200
13recmod=1    //打开主动解析
14page 0                       //上电刷新第0页

解析定时器(tim为50)中的代码如下图所示

 1while(usize>=shortestLength&&getFrameFlag==0)
 2{
 3  strLength=u[2]
 4  frameLength=strLength+3
 5  if(u[0]==0xFF&&usize>=frameLength)
 6  {
 7    //找到帧头,退出循环
 8    getFrameFlag=1
 9  }else
10  {
11    //如果帧头不对,就一直删除1个字节,直到不满足条件退出循环
12    udelete 1
13  }
14}
15if(getFrameFlag==1)
16{
17  if(u[1]==0x00)
18  {
19    ucopy t0.txt,3,strLength,0
20  }else if(u[1]==0x01)
21  {
22    ucopy t1.txt,3,strLength,0
23  }
24  udelete frameLength //删除已经解析过的数据
25  getFrameFlag=0 //清空标记变量
26}