FreeModbus 从站设计( 10 ) -Modbus 功能码的回调函数如何编写 关键词: FreeModbus CubeMX HAL 库 串口 功能码 此系列的前面几篇文章,主要是阐述了用 HAL 库生成 keil 工程、如何将 FreeModbus 的代码加入 keil 工程、协议栈的初始化、串口和定时器接口函数的修改等内容,并整理了 FreeModbus 协议栈调与 HAL 库函数的调用关系,通过以上这些工作, Modbus 的通路(串口和定时器)已经通了,下面就是数据的处理部分了。数据处理部分主要是对各个功能码的回调函数的编写。 以常用的读写保持寄存器的功能码( 03 、 06 、 16 )为例,阐述回调函数的编写方法。 1. 回调函数的位置 第一个是回调函数被调用的地方,也就是回调函数在 FreeModbus 协议栈的哪些地方被使用。 保持寄存器的回调函数为: eMBRegHoldingCB() 。被调用的位置如图 1- 图 4 所示。从几张图片可以看出,调用的位置都在 mbfuncholding.c 文件中,首先说明,在移植 FreeModbus 协议栈的时候, mbfuncholding.c 文件中的代码是不需要修改的,孔丙火(微信公众号:孔丙火)这里只是为了更清晰地展示函数的调用关系,做一个简单的阐述。调用 eMBRegHoldingCB() 的地方主要是写单个保持寄存器(对应的功能码 06 )、写多个保持寄存器(对应的功能码 16 )、读保持寄存器(对应的功能码 03 )、读写多个保持寄存器(对应的功能码 23 ),读写多个保持寄存器的地方调用了两次(读和写),在图 4 中只截取了一个的图片,因此,共有 5 处调用了 eMBRegHoldingCB() 。 图1 图2 图3 图4 这里顺便说一句, FreeModbus 协议栈是严格按照 Modbus 协议标准来做的,在 Modbus 协议规范中,对于保持寄存器的定义见图 5 ,跟读、写寄存器相关的几个功能码,在 FreeModbus 协议栈里面都有定义,这也是使用标准协议栈的好处,相对于自己编写的协议栈,功能全面,不会缺少某些功能。 图5 第二个是回调函数定义的地方。从图 6 可以看出, eMBRegHoldingCB() 函数是字啊 mb.h 中声明的。至于在何处定义(编写)这个函数?只要是在包含了 mb.h 的任何一个 .c 文件中都可以。 图6 2. 回调函数编写方法 在孔丙火(微信公众号:孔丙火)的这个例子中,新建了一个 modbus_app.c 文件, eMBRegHoldingCB() 的代码就编写在 modbus_app.c 中。如图 7 所示,是 eMBRegHoldingCB() 函数的总体结构,首先判断需要读或写的寄存器地址是否在定义的范围内,不在范围内的话,返回 MB_ENOREG ,这样协议栈就会回复相应的错误代码。 图7 如图 8 所示,在读或写的数据在范围内时,对数据进行操作。在程序内部,保持寄存器的数据时存储在数组 usRegHoldingBuf[] 中的,大小根据实际情况自行定义。 图8 图 8 所展示的是一个最基本的读写操作。在实际应用中,也许需要根据保持寄存器中的值做一些操作,后续的操作代码也可以写在这个函数中,这样可以保证第一时间执行。如图 9 所示,就是一个在收到相应的指令后,进入上电停止状态和修改通信参数的例子,后续会有专门一个章节,对此进行阐述。 图9 按照本文的思路,就可以编写自己的功能码回调函数了。 文章在公众号( 孔丙火 )同步推出,欢迎查看更多系列文章。 单片机、 ARM 、现场总线、 PLC 、嵌入式软硬件的设计经验分享,秉承“点点滴滴皆智慧”的理念,以实际项目为单元阐述知识点,一起分享,共同交流。