上一节讲到起止式SST(Start-Stop-Type)帧结构协议,该协议运用帧头、长度、校验构建帧结构,依据帧结构能完结对数据包的牢靠、精确传输。
运用层数据包规划思路
回到工程自身,帧结构中的数据包才是运用程序终究需求解析运用的,且与详细的事务需求有关。
这篇文章将简略介绍,在数据包里怎么规划运用层的交互指令,然后完结详细的事务需求。共享个思路,就当抛砖引玉了。
相似于帧结构,在规划数据包时,依据交互逻辑的详细需求,相同选用逐字节组成字段,字段组成数据包,然后完结指令交互。
详细到项目中,一般地有方针地址、源地址、指令类型、传输方向、级联序号、参数ID、参数值等等。
字段的界说因项目需求而定,以上提及的字段或许存在且不限于此。
以下介绍在详细项目中,对数据包规划与解析思路。工程实践中办法许多,信任许多阅历熟练的老工程师必定都有各自奇妙的编程思路,欢迎在本页留言沟通。
项目事例
依据nRF51822的BLE终端设备,与上位机运用UART通讯,物理线路运用USB转UART。
数据包界说

类型界说

参数名&参数值界说

依据以上界说,可认为运用程序规划指令解析的结构体,结构体中所界说的类型type和参数名para,运用枚举类型界说:

惯例解析进程
解析函数,一般地会把输入参数的 *indata,运用一个新的结构体指针指向该输入参数,之后的解析运用结构体指针来对数据处理,增强代码可读性!

上述截图中的界说方法呈现了正告,这儿需求做个如下的强制转化:

惯例的判别处理,多选用switch(){case :}联合if(…){;}else(…){;}判别逻辑,这个方法的判别处理架构如下:

以上的做法,顺次去判别类型type、参数名para,然后直接处理。当这两个字段的枚举成员数量少,倒还能够这么判别;可是假设工程需求扩展、事务有了新的需求,那么if(…){;}else(…){;}的逐个判别将会使得解析函数里的代码量巨大!
总结有这几个缺陷:
1.事务需求有多少个类型或许其他分支,就需求多少个这样的判别逻辑,关于编写代码变成个体力活;
2.在代码检查、保护时,面临的仍是罗列了一大堆的switch(){case :}和if(…){;}else(…){;}句子;
3.增删功用时,需求找到代码中详细的判别方位,然后小心谨慎给注释或许修正掉。
这儿现已没有任何的技术含量,基本上便是复制粘贴判别句子、修正判别目标,说到底也便是个查表的进程!
构建查表方法解析
已然要查表,当然是有个while()循环,然后递加某一变量来查表的进程。在这儿,数据包结构体中界说的类型type、参数名para,都能够作为查表的目标,该怎么挑选?
假定:
1.以类型作为查表目标,假设查表后类型等于查询参数,那么参数名仍然是个多个分支的状况,要么持续查表要么持续选用switch(){case
:}或许if(…){;}else(…){;}来判别许多不同的参数名;
2.以参数名作为查表目标,假设查表后参数名等于设备运转状况,那么类型需求做最多三种判别:查询、设置、其他。
比照以上两种,必定是第2个更能进步编程功率、缕清逻辑结构。
要查表就要建表,建表的结构体,以参数名para作为被查目标,而且以回调函数的方法履行查表成果。建表如下:

说是建表,其实便是界说一个结构体数组,数组的每个元素都是结构体类型,这儿的结构体,主要由数据包协议的参数名和回调函数组成,界说如下:

在履行数据包解析的时分,查表的思路是:
1.先创立一个表结构的指针*ptable指向表的开端方位,也便是指向数组内第一个元素{ECHO, dcapp_dev_echo}
2.再创立一个数据包结构的指针*pbuf指向输入数据首地址
3.经过递加ptable指针,对ptable与pbuf的参数名成员进行比对
4.最终履行ptable指针对应回调函数

以上的思路,放到代码中,只是数行就能够完结对输入数据包参数名的解析!高效、明晰!
别的,建表时,把无效参数名对应的值和对应的回调函数放在最终,这样做的优点是查完整个表,无需区别是否找到对应的参数名,而直接履行指针对应的回调函数即可。
这样即使是未找到参数名,也会履行表中最终一个元素,便是过错解析的回调函数dcapp_parser_err()。
有了这样一个查表的处理方法,增删指令功用就变得简略太多了!增加功用,只需求在表中增加参数名和对应的回调函数,删去某功用,也是回到表中找到对应的参数名和回调函数即可!
总结一下,尽管查表方法十分明晰,可是对应的回调函数内部,需求独自处理和完结,而且每个参数名都需求独自处理。比较于选用switch(){case
:}联合if(…){;}else(…){;}判别逻辑,的确明晰许多。
以上的查表思路,来源于阅历的项目,一起还参阅了
《STM32CubeExpansion_MEMSMIC1_V1.1》
这个ST官方的数字麦克风开源项目示例,作为USB音频设备时,相似的回调函数方法:

调试截图
正确解析了数据包的参数名之后,对应的函数履行成果是打印输出调试信息,如下截图:

以上是开始的解析作用,能够经过回调函数,正确地跳转到对应的函数履行。详细的处理仍需求针对项目的事务需求而规划,在此不做更多的延伸。