跳到正文

Modbus、CAN 与工业协议

本文性质声明:本机无开发板,全部内容未实测,为手册级框架。站内对照:net-application-protocol-design(帧格式/序号/心跳的本机实测)、emb-bus(UART/DMA 收发)、dbg-log(日志与可观测性)。

一、Modbus:寄存器表的远程读写

Modbus 的本质是”主从轮询 + 寄存器地址表”——协议极老极简单,因此活得极好。

RTU 帧(串口二进制):

[从站地址 1B][功能码 1B][数据 N B][CRC16 2B(低字节在前)]

常用功能码:01 读线圈、02 读离散输入、03 读保持寄存器、04 读输入寄存器、06 写单寄存器、16 写多寄存器。请求-响应一一对应:主站发 03 00 00 00 0A(读从站 1 的 10 个保持寄存器),从站回 03 14 <20 字节> CRC——字节数 0x14 = 20 跟着,这是响应帧的自描述字段。

TCP 帧:同样的 PDU,外面包 MBAP 头(事务号/协议号/长度)+ 端口 502——没有 CRC 了(TCP 有校验),但多了”一个连接多个从站”的多路复用(事务号区分)。

从站实现五要点:CRC16 查表法(别逐位算,本站 net-application-protocol-design 量过表 vs 计算的取舍族)、超时与静默丢弃(帧不完整/CRC 错 = 一个字不回,等主站超时——别回错误帧,那会让总线更乱)、异常响应(功能码 | 0x80 + 异常码 02 非法地址/03 非法值)、广播地址 0(只写不读,从站不应答)、寄存器表的合法性(地址映射到实际变量——映射表是协议层和业务层之间唯一的翻译处,写错地址的故障全在这儿)。

二、CAN:仲裁、报文与 DBC

CAN 的基因决定它的性格:多主竞争、按 ID 仲裁、报文短、错误帧机制激进。

仲裁:节点同时发,逐位比较,显性位(0)压过隐性位(1)——ID 数值小的赢,且输家自动退出让道。推论:ID 就是优先级——关键报文(制动、急停)分配小 ID。

帧:标准帧 11 位 ID / 扩展帧 29 位 ID,数据 0–8 字节。超过 8 字节的 payload 要用应用层分包(CANopen 的 SDO、J1939 的传输协议)。

DBC 文件:文本格式的”报文字典”——哪个 ID、叫什么名字、几个信号、每个信号几位、缩放系数(物理值 = 原始值 × factor + offset)、枚举定义、发送周期。DBC 是 CAN 团队的共同语言:工具(CANoe/dbc 解析库)读它生成代码,两个人对”这个字节是什么”的争论终结于 DBC。没有 DBC 的 CAN 项目 = 用甲骨文写业务代码。

三、错误帧与总线关闭恢复

CAN 控制器自己有一套错误治理,理解它才能解释”总线突然全体安静”:

  1. 五种错误:位错误、填充错误、CRC 错误、形式错误、应答错误——任一节点检测到就发错误帧打断当前传输(6 个显性位,所有人都听见)。
  2. TEC/REC 计数器:发送错误计数 / 接收错误计数,随收发错误增减、随成功收发递减。TEC > 255 → 总线关闭(Bus Off)——节点自己把自己关掉了,不再收发。
  3. 恢复:总线关闭后节点要等 128 次 ×11 隐性位的”恢复序列”,自动重进;反复关闭进”总线关闭保护”状态。软件侧的对应处理:检测到 Bus Off → 复位 CAN 控制器 + 记录现场(emb-reliability 的取证),别静默重试。

排障口径:ip -s link show can0 看 error counters、candump 看谁在发错误帧。总线 100% 负载 + 错误帧飞舞 = 波特率不匹配或终端电阻错(120Ω 两端各一,万用表量总线 60Ω 才对)。

四、网关与协议转换

工业现场的常态是”多协议并存”:Modbus 的老设备、CAN 的车上网络、MQTT 的上云通道——网关就是翻译层:

Modbus 从站 ─┐
CAN 节点   ──┼─→ [网关:协议栈 × N + 数据模型] ──→ MQTT/HTTP 上云
MQTT 设备  ─┘

网关内部四层(照抄 OSI 的务实版):接入层(各协议的收发,用 DMA/中断,emb-bus)、数据模型层(所有协议翻译成统一的”点表”:地址、类型、值、时间戳、质量位——这是网关的核心资产)、路由层(点表到点表的映射/告警/聚合)、出口层(对上协议的组帧)。

三条工程教训:数据模型先行(没有统一点表的网关,加第三种协议时必然重写前两种的代码);质量位(quality)不可少(值是旧的/通道坏了/超时未更新——下游需要知道”这个数可不可信”,本站 net-application-protocol-design 的 heartbeat 是同一思想的协议层版本);背压与丢弃策略(上游刷得快下游发不出——环形缓冲 + 明确丢弃最旧/阻塞,本站 conc-task-queue 量过无界队列的危险)。

五、排障索引

症状入口
Modbus 全体无响应CRC 错/帧不完整(从站静默丢弃);波特率校验位不匹配
单设备无响应地址配错;RS-485 方向脚(DE/RE)时序——发完没关驱动会锁总线
CAN 总线静默Bus Off(第三节);终端电阻;波特率
信号值差一个系数DBC 的 factor/offset 与实际不符(第二节);字节序(Motorola vs Intel)
网关数据延迟/丢无界队列堆积或丢弃策略太激进;质量位缺了下游无法判断
加新协议就崩数据模型层没独立(第四节)——前两种协议的代码被第三次污染

六、未实测清单

  • 本文所有协议行为——无开发板,未测。
  • Modbus CRC/CAN 控制器的具体行为——以你的器件手册和协议规范为准。
  • 网关的吞吐与延迟——未部署。
  • 用户 Linux 开发机上的项目总线——该机不可达,未涉及。