在上一篇文章《 libmodbus 源码分析(1)基本框架、关键数据结构、接口 》中,分析了libmodbus的源码基本框架和关键的数据结构、接口,本文就分析一下 libmodbus 作为 主机(客户端)的功能源码实现,这里我们以 modbus rtu 协议 的读 4x 区保持寄存器功能 进行举例说明,
我们简单的写一下 modbus rtu 下读 4x 区保持寄存器的 伪代码 流程:
-
int main()
-
{
-
modbus_t *ctx =
NULL;
-
-
uint16_t tab_rp_register[
200];
// 不一定是200个,根据自己的需要来定义
-
-
/* 创建并初始化 modbus_t 指针 */
-
ctx = modbus_new_rtu(
"/dev/ttyUSB1",
115200,
'N',
8,
1);
-
-
/* 设置 错误 恢复模式 */
-
modbus_set_error_recovery(ctx,
-
MODBUS_ERROR_RECOVERY_LINK |
-
MODBUS_ERROR_RECOVERY_PROTOCOL);
-
-
/* 设置 从机 (服务器) 地址, 支持运行中 设定,也就是可以 实现多从机的轮询 */
-
modbus_set_slave(ctx, SERVER_ID);
-
-
-
/* 4x区保持寄存器 的读 功能, 从 地址 start_addr开始,共读 nb 个寄存器
-
* 读到的寄存器值存放到 tab_rp_registers 中
-
*/
-
modbus_read_registers(ctx, start_addr, nb, tab_rp_registers);
-
-
/* 关闭 modbus */
-
modbus_close( ctx );
-
-
/* 释放 modbus 资源 */
-
modbus_free( ctx );
-
}
上面的伪代码是 是读1次的实现,如果想要对不同的从设备进行轮询,我们只需要在while(1)循环中 先设定 从设备地址,然后再 调用 modbus_read_registers即可。
上面的代码中,大部分的接口函数都是比较容易理解,只有 modbus_read_registers 相对复杂一些,因为它实现的功能也比较多,分别为:
① 创建并打包 读命令。
② 发送 步骤①中的读指令。
③ 接收从机返回数据,分三次接收数据,先接收前2个字节(功能),再接收 第3个字节(数据长度),再接收剩下的字节数。
选择3次进行接收,一方面是为了随时校验,在linux下接收不定长数据的实现不太方便,所以根据modbus协议框架,先接收 到总数据长度,然后就能按照指定长度进行接收。
④ 对返回数据 进行各种校验,比如设备地址,地址、数量、CRC校验等。
⑤ 将正确的返回 有效数据 存放到 我们指定的 缓存中。
接下来就通过层层的调用关系来分析该代码功能,如下图所示:
其他的 modbus_read_xxx和write功能代码实现与上面的类似。
转载:https://blog.csdn.net/u012351051/article/details/104088551