为什么不直接用现成的 Modbus 协议栈

PipeMonitor 现场的从站既包括压力变送器、超声波流量计,也包括 PT100 温度模块,节点数和测点数都会变。如果把 Modbus 帧发送、寄存器布局、轮询调度都耦合在一起,每加一个传感器型号都要动多处代码。

所以这里把 Modbus 拆成了三层:

PipeMonitor/
├── Modbus_Master.*    # 串口/总线收发、帧校验
├── Modbus_Service.*   # 轮询调度、超时与异常节点处理
└── nanomodbus.*       # 轻量级 Modbus 协议核心库(深度封装)

nanomodbus 是协议本体,Modbus_Master 负责把它接到 RT-Thread 的 UART 设备上,Modbus_Service 负责把”什么时候轮询哪个测点”这件事抽象成可配置的任务。

轮询调度

每个传感器都有一张测点表,描述它在 Modbus 总线上的从站地址、寄存器起始地址、寄存器数量、采集间隔。Modbus_Service 在调度循环里按以下顺序工作:

  1. 遍历测点表,找到下一个到期的测点
  2. 通过 Modbus_Master 发出对应的读寄存器请求
  3. 解析回包,按测点的标定参数写回内存中的最新值快照
  4. 如果连续多次失败,把节点标记为异常并降级轮询频率

这样:

  • 采集间隔分配:高频量(如压力)和低频量(如累积总流量)可以单独配置,不会因为低频量挤占高频量的轮询窗口
  • 超时容错nanomodbus 拿不到回包时返回错误码,调度层不会卡死
  • 异常节点过滤:节点掉线后会自动降级,不会无限制地拖慢整体轮询

三类传感器的接入方式

模块文件说明
PXW 压力温度PXW_Pressure.*单设备多寄存器,压力与温度成对读取
超声波流量计Flowmeter.*瞬时流量、流速、累积总流量;累积量单独低频轮询
PT100 4 通道PT100_4.*一台从站映射 4 路温度
PT100 5 通道PT100_5.*一台从站映射 5 路温度,与 4 通道版本走相同的服务接口

每个文件都暴露两类接口:

  • *_init(...) —— 把测点注册到 Modbus_Service
  • *_get_latest(...) —— 给上层(LCD、存储)拿到最近一次采集的快照值

上层永远不直接访问 Modbus 总线,只读快照,所以 LCD 渲染线程和存储线程都不会被串口收发阻塞。

与 RT-Thread 的协同

  • 串口读写走 RT-Thread UART 设备框架,Modbus_Master 内部用 RT-Thread 的 IPC 等待应答
  • 测点快照用互斥锁保护,写入端是采集线程,读取端是显示线程和存储线程
  • 异常事件(连续超时、CRC 错误)通过 RT-Thread 消息队列发给上层告警逻辑,由 LCD 模块切换到告警颜色显示

后续阅读