|
Agile Modbus 1.1.2
Lightweight modbus protocol stack.
|
Agile Modbus 即:轻量型 modbus 协议栈,满足用户任何场景下的使用需求。

examples 文件夹提供 PC 上的示例| 名称 | 说明 |
|---|---|
| doc | 文档 |
| examples | 例子 |
| figures | 素材 |
| inc | 头文件 |
| src | 源代码 |
| util | 提供简单实用的组件 |
Agile Modbus 遵循 Apache-2.0 许可,详见 LICENSE 文件。
帮助文档请查看 doc/doxygen/Agile_Modbus.chm
用户需要实现硬件接口的 发送数据 、 等待数据接收结束 、 清空接收缓存 函数
对于 等待数据接收结束,提供如下几点思路:
通用方法
每隔 20 / 50 ms (该时间可根据波特率和硬件设置,这里只是给了参考值) 从硬件接口读取数据存放到缓冲区中并更新偏移,直到读取不到或缓冲区满,退出读取。
这对于裸机或操作系统都适用,操作系统可通过 select 或 信号量 方式完成阻塞。
串口 DMA + IDLE 中断方式
配置 DMA + IDLE 中断,在中断中使能标志,应用程序中判断该标志是否置位即可。
但该方案容易出问题,数据字节间稍微错开一点时间就不是一帧了。推荐第一种方案。
agile_modbus_rtu_init / agile_modbus_tcp_init 初始化 RTU/TCP 环境agile_modbus_set_slave 设置从机地址清空接收缓存agile_modbus_serialize_xxx 打包请求数据发送数据等待数据接收结束agile_modbus_deserialize_xxx 解析响应数据agile_modbus_slave_callback_t 类型回调函数agile_modbus_rtu_init / agile_modbus_tcp_init 初始化 RTU/TCP 环境agile_modbus_set_slave 设置从机地址等待数据接收结束agile_modbus_slave_handle 处理请求数据清空接收缓存 (可选)发送数据特殊功能码
需要调用 agile_modbus_set_compute_meta_length_after_function_cb 和 agile_modbus_set_compute_data_length_after_meta_cb API 设置特殊功能码在主从模式下处理的回调。
agile_modbus_set_compute_meta_length_after_function_cb
msg_type == AGILE_MODBUS_MSG_INDICATION: 返回主机请求报文的数据元长度(uint8_t 类型),不是特殊功能码必须返回 0。
msg_type == MSG_CONFIRMATION: 返回从机响应报文的数据元长度(uint8_t 类型),不是特殊功能码必须返回 1。
agile_modbus_set_compute_data_length_after_meta_cb
msg_type == AGILE_MODBUS_MSG_INDICATION: 返回主机请求报文数据元之后的数据长度,不是特殊功能码必须返回 0。
msg_type == MSG_CONFIRMATION: 返回从机响应报文数据元之后的数据长度,不是特殊功能码必须返回 0。
agile_modbus_rtu_init / agile_modbus_tcp_init
初始化 RTU/TCP 环境时需要用户传入 发送缓冲区 和 接收缓冲区,建议这两个缓冲区大小都为 AGILE_MODBUS_MAX_ADU_LENGTH (260) 字节。特殊功能码 情况用户根据协议自行决定。
但对于小内存 MCU,这两个缓冲区也可以设置小,所有 API 都会对缓冲区大小进行判断:
发送缓冲区设置:如果 预期请求的数据长度 或 预期响应的数据长度 大于 设置的发送缓冲区大小,返回异常。
接收缓冲区设置:如果 主机请求的报文长度 大于 设置的接收缓冲区大小,返回异常。这个是合理的,小内存 MCU 做从机肯定是需要对某些功能码做限制的。
见 2.1、移植。
agile_modbus_slave_handle 介绍
msg_length: 等待数据接收结束 后接收到的数据长度。
slave_strict: 从机地址严格性检查 (0: 不判断地址是否一致,由用户回调处理; 1: 地址必须一致,否则不会调用回调,也不打包响应数据)。
slave_cb: agile_modbus_slave_callback_t 类型回调函数,用户实现并传入。如果为 NULL,所有功能码都能响应且为成功,但寄存器数据依然为 0。
slave_data: 从机回调函数私有数据。
frame_length: 获取解析出的 modbus 数据帧长度。这个参数的意义在于:
一帧完整的 modbus 数据 + 部分 modbus 数据帧 组成,用户获得真实 modbus 帧长后,可以移除处理完的 modbus 数据帧,再次读取硬件接口数据与当前 部分 modbus 数据帧 组成新的一帧清空接收缓存agile_modbus_slave_callback_t 介绍
sft: 包含从机地址和功能码属性,回调中可利用
rsp_length: 响应数据长度指针,回调中处理 特殊功能码 时需要更新其值,否则 不准更改
address: 寄存器地址 (不是所有功能码都用到)
nb: 数目 (不是所有功能码都用到)
buf: 不同功能码需要使用的数据域 (不是所有功能码都用到)
send_index: 发送缓冲区当前索引 (不是所有功能码都用到)
agile_modbus_slave_info 不同功能码使用AGILE_MODBUS_FC_READ_COILS、AGILE_MODBUS_FC_READ_DISCRETE_INPUTS
需要使用到 address、nb、send_index 属性,需要调用 agile_modbus_slave_io_set API 将 IO 数据存放到 ctx->send_buf + send_index 开始的数据区域。
AGILE_MODBUS_FC_READ_HOLDING_REGISTERS、AGILE_MODBUS_FC_READ_INPUT_REGISTERS
需要使用到 address、nb、send_index 属性,需要调用 agile_modbus_slave_register_set API 将寄存器数据存放到 ctx->send_buf + send_index 开始的数据区域。
AGILE_MODBUS_FC_WRITE_SINGLE_COIL、AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER
需要使用到 address、buf 属性,将 buf 强转为 int * 类型,获取值存放到寄存器中。
AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS
需要使用到 address、nb、buf 属性,需要调用 agile_modbus_slave_io_get API 获取要写入的 IO 数据。
AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS
需要使用到 address、nb、buf 属性,需要调用 agile_modbus_slave_register_get API 获取要写入的寄存器数据。
AGILE_MODBUS_FC_MASK_WRITE_REGISTER
需要使用到 address、buf 属性,通过 (buf[0] << 8) + buf[1] 获取 and 值,通过 (buf[2] << 8) + buf[3] 获取 or 值。获取寄存器值 data,进行 data = (data & and) | (or & (~and)) 操作更新 data 值,写入寄存器。
AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS
需要使用到 address、buf、send_index 属性,通过 (buf[0] << 8) + buf[1] 获取要读取的寄存器数目,通过 (buf[2] << 8) + buf[3] 获取要写入的寄存器地址,通过 (buf[4] << 8) + buf[5] 获取要写入的寄存器数目。需要调用 agile_modbus_slave_register_get API 获取要写入的寄存器数据,调用 agile_modbus_slave_register_set API 将寄存器数据存放到 ctx->send_buf + send_index 开始的数据区域。
自定义功能码
需要使用到 send_index、nb、buf 属性,用户在回调中处理数据。
send_index: 发送缓冲区当前索引
nb: PUD - 1,也就是 modbus 数据域长度
buf: modbus 数据域起始位置
注意: 用户在回调中往发送缓冲区填入数据后,需要更新 agile_modbus_slave_info 的 rsp_length 值。
Agile Modbus 提供了 agile_modbus_slave_callback_t 的一种实现方式,使用户能够简单方便接入。
使用示例可查看 examples/slave。
使用方式:
agile_modbus_slave_util_callback 介绍agile_modbus_slave_callback_t 实现方式,需要 agile_modbus_slave_util_t 类型变量指针作为私有数据。agile_modbus_slave_util_t 介绍
寄存器相关
用户需要实现 bits、input_bits、registers、input_registers 定义。如果某个寄存器定义为 NULL,该寄存器对应的功能码能响应且为成功,但寄存器数据都为 0。
接口调用过程

agile_modbus_slave_util_map 介绍
map_buf 数组大小可使其变大。get 接口
将地址域内的数据全部拷贝到 buf 中。
set 接口
index: 地址域内的偏移len: 长度根据 index 和 len 修改数据。
WSL 或 Linux 下编译运行。特殊功能码的示例
RTU 点对点传输文件: 演示特殊功能码的使用方式
RTU 广播传输文件: 演示 agile_modbus_slave_handle 中 frame_length 的用处
Doxywizard 打开 Doxyfile 运行,生成的文件在 doxygen/output 下。Graphviz 路径。HTML 生成未使用 chm 格式的,如果使能需要更改 hhc.exe 路径。
如果 Agile Modbus 解决了你的问题,不妨扫描上面二维码请我 喝杯咖啡 ~