3. Modbus RTU 基础:物理层(RS-485)、帧结构、功能码(03/06/16)、CRC校验
在变量施肥系统中,控制器与变频器、电磁阀、传感器之间的数据交换,最常用的底层协议就是 Modbus RTU。它运行在 RS-485 物理层之上,采用主从问答模式。理解其物理层特性、报文帧结构、核心功能码以及 CRC 校验机制,是进行多协议对接的第一步。
3.1 物理层:RS-485 标准
RS-485 是 Modbus RTU 最常用的物理层载体,特别适合工业现场的长距离、多节点通信。
| 特性 | RS-485 参数 | 现场意义 |
|---|---|---|
| 传输方式 | 差分平衡传输(半双工) | 抗共模干扰强,适合电机变频环境 |
| 最大节点数 | 32 个标准负载(加中继可扩展) | 一台施肥控制器可挂多台设备 |
| 最大距离 | 1200 米(@ 100 kbps) | 覆盖大田或温室控制柜到执行器 |
| 逻辑电平 | A-B 电压差 > +200 mV 为 1;< -200 mV 为 0 | 与 TTL 电平不兼容,需转换芯片 |
| 终端电阻 | 120 Ω(线路两端各一个) | 消除信号反射,保证数据完整性 |
现场布线要点: 使用双绞屏蔽线,屏蔽层单端接地;A/B 线不要接反;总线两端必须各并联一个 120 Ω 终端电阻,否则长距离通信会出现乱码或丢包。
3.2 Modbus RTU 帧结构
Modbus RTU 采用二进制编码,报文以连续的字节流形式在 RS-485 总线上传输。每一帧由以下四个部分组成:
- 地址域(1 字节): 从站设备地址,范围 1~247,0 为广播地址。
- 功能码(1 字节): 指示读/写操作类型,如 03、06、16。
- 数据域(N 字节): 寄存器起始地址、数量或具体数值。
- CRC 校验(2 字节): 低字节在前,高字节在后,用于检测传输错误。
帧之间的空闲间隔必须 ≥ 3.5 个字符时间,作为帧起始和结束的判定依据。
典型读请求帧示例(读 1 路寄存器):
从站地址: 0x01
功能码: 0x03
起始地址: 0x00 0x64 (100)
寄存器数: 0x00 0x01 (1)
CRC 校验: 0x84 0x0A
3.3 核心功能码:03 / 06 / 16
变量施肥系统中最常用的三个功能码,覆盖了读取传感器数值、写入单路执行器参数、批量设置多路参数三种场景。
| 功能码 | 名称 | 方向 | 典型用途 |
|---|---|---|---|
| 0x03 | 读保持寄存器 | 主站 → 从站(请求) 从站 → 主站(响应) |
读取流量计瞬时流量、阀门开度反馈 |
| 0x06 | 写单个寄存器 | 主站 → 从站(写入) 从站 → 主站(回显) |
设定变频器频率、电磁阀开度值 |
| 0x10 (16) | 写多个寄存器 | 主站 → 从站(写入) 从站 → 主站(应答) |
批量设置施肥配方参数(N/P/K 比例) |
常见错误: 功能码 0x06 只能写 1 个寄存器(2 字节),如果试图用 0x06 写入超过 2 字节的数据,从站会返回异常码 0x86(非法数据值)。批量写入必须使用功能码 0x10。
3.4 CRC 校验原理与计算
Modbus RTU 使用 CRC-16 (Modbus 多项式) 进行帧校验,多项式为 0x8005,初始值为 0xFFFF。校验覆盖地址域、功能码和数据域,不包含帧间隔。
计算步骤:
- 将 16 位 CRC 寄存器初始化为
0xFFFF。 - 对每个字节与 CRC 寄存器低字节进行异或。
- 右移 1 位,若移出位为 1,则与多项式
0xA001(逆序)异或。 - 重复 8 次,处理完所有字节后,CRC 寄存器值即为校验码。
- 发送时 低字节在前,高字节在后。
C 语言 CRC 计算示例:
uint16_t crc16_modbus(uint8_t *data, uint16_t len) {
uint16_t crc = 0xFFFF;
for (uint16_t i = 0; i < len; i++) {
crc ^= data[i];
for (uint8_t j = 0; j < 8; j++) {
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
3.5 主从问答流程示例
以读取变频器当前频率(寄存器地址 100)为例,展示完整的主从交互过程:
| 方向 | 字节流(十六进制) | 说明 |
|---|---|---|
| 主站 → 从站 | 01 03 00 64 00 01 84 0A |
请求读取地址 01 的寄存器 100 |
| 从站 → 主站 | 01 03 02 0B B8 7A 3E |
响应:数据长度 2 字节,频率值 0x0BB8 = 3000(对应 30.00 Hz) |
调试技巧: 使用串口助手或 Modbus 调试工具(如 ModScan、Modbus Poll)发送原始报文,观察从站响应。如果收到异常码
0x83(功能码 03 的异常响应),说明地址或寄存器不存在;如果无响应,优先检查 RS-485 接线和终端电阻。