您的位置 首页 设计

嵌入式硬件通讯接口协议-UART(五)数据包规划与解析

上一节讲到起止式SST(Start-Stop-Type)帧结构协议,该协议利用帧头、长度、校验构建帧结构,基于帧结构能实现对数据包的可靠、准确传输。应用层数据包设计思路回到工程本身,帧结构

  上一节讲到起止式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音频设备时,相似的回调函数方法:

  

  调试截图

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

  

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

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/sheji/129074.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部