表驱动法在串行通讯协议解析中的应用 2024-06-22 04:21:15 在《单片机高级裸编程思想》和《代码大全2》中,均提到了数据驱动程序的编程思想,认为数据是宇宙的语言。虽然我们可以通过代码逻辑实现任务需求,但容易出现代码分支众多,程序难以理解和维护的困境,但如果我们选择了正确的数据结构并进行有条理的整理,并秉持数据是易变的而逻辑是稳定的认识,将数据和实现分离,算法则不言自明。数据比程序更易驾驭。尽可能把设计的复杂度从代码转移至数据是个好的实践方式。所谓表驱动法,也称C语言映射表(有点函数中X和Y的取值映射的味道),简而言之就是通过查表的方式得到数据对应的实现。此处“表”通常的表现形式是数组,也认为是数据库的一种实现方式。查表的理念在NTC热敏电阻的测温和CRC校验算法中可见一斑。NTC热敏电阻通常原厂会给出一张温度-阻值对应表,程序的一般实现方式:ADC测量电压àNTC电阻à查表获取温度值。CRC校验算法通常不会每次采用对数据采用逐位异或,反复迭代计算CRC,而是采用查表计算得到CRC的方式求解CRC值(当然这里涉及到的空间换时间的理念就不展开了)。举个简单的例子,如下。考试根据考分计算成绩等级。低于60,计等级E;60~70,计等级D;70~80,计等级C;80~90,计等级B;90~100,计等级A。一般思路关键代码可实现如下。很显然,按照上述的编程思路,如果分数段划分得足够细,增加更多的分数等级,每增加一个等级,就要增加一个流程分支。但查表的思路,则代码逻辑简洁,关键代码如下。很显然,上述代码整体观感上简洁很多。同样的问题,如果细分更多等级,仅仅只需要修改score_map这个数组本身和数组长度。相比较而言,第二种查表方法,只需要修改数据,不需要对算法的逻辑进行增删操作,当然上述伪代码的数组长度是需要宏定义的。显然上述的思路优势很明显:1.可读性更强,消息流程处理一目了然;2.易于维护,如果要增加新的等级,只需要修改数据,不需要修改流程;3.良好的重用性,将相同的逻辑提取出来,而把容易发生改变的部分提取到外部。查表的方式分为直接查找、索引查找和二分查找等。直接查找即通过数组下标直接获取数据,可以看出这种方式就是哈希表的直接访问法。很显然,表驱动法是适用于无需有序遍历数据,且数据量大小可提前预知的情况。索引查找的基本思想是:首先查找索引表,可用二分查找或顺序查找,然后在确定的块中进行顺序查找。二分查找则是通过确定数据所处的范围确定分类,但是需要注意边界,将每一分段范围的上限值都考虑在内。表驱动在CAN通讯协议中的应用背景:CAN总线上挂载若干设备,其中一个设备人为指定为主控,其余设备人为指定为从控。制定如下通讯协议:在其扩展帧ID中约定了一些位,定义了地址、功能码、指令码等功能。那么如何解析主机可能收到的数据帧呢?常规思路可能有如下伪代码。从上述代码中可以看到,对于这种需求,随着总线上挂载设备的增多,核心解码函数需要不断增加case分支。以上代码缺点很多:1.可读性不高,解析一条CAN指令的处理部分代码需要跳转3层代码,随着分支的增加也给阅读带来一定的障碍;2.过多的swicth分支,其实这也是一种重复代码,都有共同特性,可以进一步提炼;3.程序缺少核心主干,主干被淹没在大量的代码逻辑之中。针对以上问题,用表驱动法来实现如下。根据上述功能要求,定义3个枚举类型:设备地址、功能类型和指令类型等,定义如下函数跳转列表(伪代码)。这种方法好处很明显:1.提高了程序的可读性,消息如何处理,查阅驱动表即可,非常明显;2.减少了重复代码,将switch分支进行了抽象,将公共的要素进行抽象形成了一个函数外加一个可扩展的驱动表;3.可扩展性,驱动表中的函数指针就是一个接口,当需要更改功能时,只需要对驱动表进行增删处理,隔离了变化;4.程序拥有了明显的主干;5.降低了程序复杂度,将程序逻辑的复杂度转移到了数据中来,达到控制复杂度的目的。表驱动在ASCII串口通讯协议中的应用背景:在某一些通信协议中,可能存在使用纯ASCII作为通信协议的情形。比如MODBUS ASCII以':’开始,以OD和OA作为结束符;常用语DTU或者NB-IOT模块中的AT指令集以“AT+xxx”作为指令等都是较为常见的ASCII指令。这里以若干条指令作为例子,简述如下。解析如下指令:信号强度指令CSQ:17,0; IP地址读取指令STAIP:192.168.0.1;开机指令SON,以上指令均以0D和0A作为结束符。按照常规的思路代码如下。以上指令借用常规的MODBUS ASCII协议,为了简便取消以':’开头,很显然实际项目中消息还会不断增加。此处只列举了3条指令作为示意,单屏已无法查看全部代码,阅读起来十分不便。再者,如果不断增加消息类型,几乎很难阅读这段“意大利面条代码”了。那么按照数据驱动编程的思路(表驱动法),可以改造成如下代码。显然这样的表现形式是比较容易阅读和维护的。上述2个例子利用表驱法在一般的思路上进行优化,使程序逻辑更清晰。总结一下,数据驱动编程背后的实现思想包括: 1. 控制复杂度,通过把程序逻辑的复杂度转移到数据中,达到了控制复杂度的目的。 2. 隔离变化,把容易变化的消息和不容易变化的逻辑进行隔离。 3. 机制和策略的分离,机制就是消息的处理逻辑,策略就是不同的消息处理。这一点可以参考《Unix编程艺术》的第一章,对此做了探讨。 当然,表驱法的应用还可在GUI菜单逻辑交互、传感器驱动流程、设备参数设置和修改(多国语言实现)等等得到应用。最后,由于本人太懒(当然水平也有限),可能伪代码逻辑不够严谨,代码主用于表述表驱法的实现思想。下一期内容:浅述DES和AES加密。 赞 (0) 相关推荐 深入理解嵌入式中重要的编程模型 大家好,我是写代码的篮球球痴. 今天我们看一看业界一些著名的编程模型. 背景 模型是对事物共性的抽象,编程模型就是对编程的共性的抽象. 什么是编程的共性呢? 最重要的共性就是:程序设计时,代码的抽象方 ... 单片机开发:什么是单片机的串行通讯? 单片机(MCU)具有串行通信功能,其中的数据按直线排列并按顺序传输,而并行通信则通过多个终端一次传输8位数据.与字符串"ABC"通信时,在并行通信中,每个字符同时传输,而在串行通信 ... 【学术论文】三维电磁仿真在25 Gbps串行收发通道设计中的应用方法 摘要: 高速串行收发信道设计问题在5G通信以及数据中心的设计中越来越受到重视.通过25 Gbps串行多通道收发器PCB设计工程实例,从而分析工程实现过程中遇到的过孔设计.阻抗匹配以及通道串扰等信号完整 ... GDB串行协议概述 GDB串行协议概述 1.概述 2.GDB Server的作用 3.一个标准的gdb的调试过程 4.GDB 远程串行协议解析 5.小结 1.概述 做嵌入式开发时,很多时候都会使用到GDB,从底层去理解G ... RS485是硬件接口,那么他是怎么实现数据通讯的呢?Modbus-RTU协议解析 ▲ 1 MODBUS-RTU的通讯格式 RS485接口在工业自动化中应用非常广泛,该接口为双总线通信方式,只有RSA和RSB两根线,可以走MODBUS TCP/IP协议,也可以走MODBUS-RTU协 ... 《诗经》课堂:《大雅·行苇》/ 解析:闻天语 / 薛红诵读(第1421期) 天语说: <礼记.射仪>:是故古者天子之制,诸候岁献贡于天子,天子试之于射宫.其容体比于礼,其节比于乐.而中多者,得与于祭.其容体不比于礼,其乐不比于乐,而中少者,不得与于祭.射礼主要是周 ... 分享一款具有扩展温度的2Mbit串行FRAM存储器FM25V20A-DGQTR CYPRESS在包括汽车.工业.家庭自动化和家电.医疗产品和消费电子业务领域.主要向客户提供市场领先的MCU.无线 SoC.存储器.模拟IC和USB控制器的解决方案.在快速发展的物联网领域获得了优势和 ... 赛普拉斯代理4Mbit串行SPI铁电存储器CY15B104Q-LHXI 赛普拉斯型号CY15B104Q-LHXI主要采用先进铁电工艺的4Mbit非易失性存储器.铁电随机存取存储器或FRAM是非易失性的,并且执行类似于RAM的读取和写入操作.它提供了151年的可靠数据保留, ... 西门子PLC最常用的几种通讯接口RS232、RS485和通讯协议PPI、MPI、Modbus、Pro... 一.接口的物理结构 1.RS232接口: 计算机通讯接口之一,通常 RS-232 接口以9个引脚 (DB-9) 或是25个引脚 (DB-25) 的型态出现,一般个人计算机上会有两组 RS-232 接口 ... Modbus通讯协议学习 了解了它,会使你对串口通信有一个清晰的认识! 通用消息帧 ASCII消息帧 (在消息中的每个8Bit 字节都作为两个ASCII字符发送) 十六进制,ASCII字符0...9,A...F 消息中的每个A ...