跳转至

Modbus RTU 规范详解 🔧

RTU 协议概述

Modbus RTU (Remote Terminal Unit) 是 Modbus 协议的串行传输版本,采用二进制编码和 CRC 校验,具有数据密度高、传输效率好的特点。

📋 协议基础

传输特性

物理层:

  • 接口标准: RS-232 / RS-485
  • 传输方式: 异步串行传输
  • 编码方式: 二进制
  • 校验方式: CRC-16

电气特性:

  • 信号电平: RS-232 (±3V to ±15V) / RS-485 (差分 ±1.5V to ±6V)
  • 传输距离: RS-232 (15m) / RS-485 (1200m)
  • 节点数量: RS-232 (点对点) / RS-485 (最多32个节点)

帧结构

RTU 帧格式:

[从站地址] [功能码] [数据] [CRC校验]
  1字节    1字节   N字节   2字节

帧组成部分:

  • 起始: 隐式开始,通过帧间间隔识别
  • 地址域: 1字节,范围 0-247 (0为广播地址)
  • 功能码: 1字节,定义操作类型
  • 数据域: N字节,具体操作数据
  • 校验域: 2字节,CRC-16校验码
  • 结束: 隐式结束,通过帧间间隔识别

⚙️ 通信参数

标准配置

参数 标准值 可选值 说明
波特率 9600 bps 1200, 2400, 4800, 19200, 38400, 57600, 115200 数据传输速率
数据位 8 bits 7, 8 每个字符的数据位数
停止位 1 bit 1, 2 停止位数量
奇偶校验 无、奇校验、偶校验 错误检测方式
从站地址 1-247 1-247 设备地址标识

推荐配置组合

1
2
3
4
波特率: 9600 bps
数据位: 8
停止位: 1
奇偶校验: 无

适用场景: 大多数工业应用

1
2
3
4
波特率: 115200 bps
数据位: 8
停止位: 1
奇偶校验: 无

适用场景: 需要高速数据传输

1
2
3
4
波特率: 9600 bps
数据位: 8
停止位: 1
奇偶校验: 偶校验

适用场景: 电磁干扰严重环境

⏱️ 时序要求

字符时序

字符间超时 (Inter-Character Timeout):

  • 定义: 1.5个字符时间
  • 用途: 检测字符传输中断
  • 计算: 1.5 × (1 + 数据位 + 停止位 + 奇偶位) / 波特率

示例计算 (9600 bps, 8-N-1):

字符时间 = (1 + 8 + 1) / 9600 = 10 / 9600 = 1.0417 ms
字符间超时 = 1.5 × 1.0417 = 1.5625 ms

帧时序

帧间间隔 (Inter-Frame Gap):

  • 定义: 3.5个字符时间
  • 用途: 区分不同数据帧
  • 计算: 3.5 × (1 + 数据位 + 停止位 + 奇偶位) / 波特率

示例计算 (9600 bps, 8-N-1):

字符时间 = 1.0417 ms
帧间间隔 = 3.5 × 1.0417 = 3.6458 ms

响应超时

典型超时设置:

  • 最小超时: 1秒
  • 标准超时: 3-5秒
  • 最大超时: 10秒
  • 具体设置: 根据网络条件和设备性能调整

🔐 CRC-16 校验

算法原理

CRC多项式:

  • 标准多项式: x^16 + x^15 + x^2 + 1
  • 十六进制: 0xA001
  • 初始值: 0xFFFF

计算步骤:

  1. 初始化CRC寄存器为0xFFFF
  2. 对每个数据字节执行以下操作:
  3. 将数据字节与CRC寄存器低字节异或
  4. 右移CRC寄存器8次,每次检查最低位
  5. 如果最低位为1,则与0xA001异或

实现代码

uint16_t crc16(uint8_t *data, uint16_t length) {
    uint16_t crc = 0xFFFF;
    for (uint16_t i = 0; i < length; i++) {
        crc ^= data[i];
        for (uint8_t j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}
def crc16(data: bytes) -> int:
    crc = 0xFFFF
    for byte in data:
        crc ^= byte
        for _ in range(8):
            if crc & 0x0001:
                crc = (crc >> 1) ^ 0xA001
            else:
                crc >>= 1
    return crc
// CRC预计算表
static const uint16_t crc16_table[256] = {
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    // ... 完整的256项查表
};

uint16_t crc16_fast(uint8_t *data, uint16_t length) {
    uint16_t crc = 0xFFFF;
    for (uint16_t i = 0; i < length; i++) {
        crc = (crc >> 8) ^ crc16_table[(crc ^ data[i]) & 0xFF];
    }
    return crc;
}

🔌 物理层连接

RS-485 网络配置

网络拓扑:

  • 总线型拓扑: 所有设备并联在总线上
  • 终端电阻: 在总线两端添加120Ω终端电阻
  • 接地: 单点接地,避免地环路

接线规范:

  • 线缆类型: 屏蔽双绞线
  • 线缆颜色: A+(绿色), B-(白色), GND(屏蔽层)
  • 连接方式: 菊花链或T型连接

设备地址分配

地址范围:

  • 广播地址: 0 (所有设备响应,但不返回响应)
  • 从站地址: 1-247
  • 保留地址: 248-255

地址分配原则:

  • 每个设备唯一地址
  • 避免地址冲突
  • 便于维护和管理

📊 性能指标

传输效率

数据吞吐量计算:

有效数据率 = (数据字节数 / 总字节数) × 波特率

示例 (读保持寄存器, 9600 bps):

1
2
3
4
5
请求帧: 8字节 (1地址 + 1功能码 + 4数据 + 2CRC)
响应帧: 9字节 (1地址 + 1功能码 + 1字节计数 + 4数据 + 2CRC)
总传输: 17字节
有效数据: 4字节
效率: (4 / 17) × 9600 ≈ 2259 bps

响应时间

典型响应时间:

  • 设备处理: 1-10 ms
  • 传输延迟: 取决于波特率和帧长度
  • 总响应时间: 通常 10-100 ms

🛡️ 错误处理

CRC错误处理

检测到CRC错误:

  1. 丢弃错误帧
  2. 不发送任何响应
  3. 等待主站重传

重传策略:

  • 最大重试次数: 3次
  • 重试间隔: 指数退避
  • 超时处理: 记录错误日志

通信故障诊断

排查步骤:

  1. 检查物理连接
  2. 验证从站地址
  3. 确认通信参数
  4. 检查从站电源
  5. 测试线路信号

排查步骤:

  1. 检查线路质量
  2. 验证波特率设置
  3. 检查终端电阻
  4. 测试电磁干扰
  5. 验证CRC算法

排查步骤:

  1. 核对寄存器映射
  2. 验证数据类型
  3. 检查字节序
  4. 确认缩放因子

🔧 调试工具

硬件工具

示波器/逻辑分析仪:

  • 信号质量分析
  • 时序测量
  • 故障诊断

协议分析仪:

  • 实时数据监控
  • 协议解析
  • 错误统计

软件工具

串口调试助手:

  • 数据收发测试
  • 十六进制显示
  • 自动CRC计算

专业Modbus工具:

  • ModbusPoll
  • ModbusSlave
  • 自动化测试脚本

📝 实现注意事项

软件实现要点

帧边界检测:

  • 严格遵循3.5字符时间规则
  • 实现可靠的超时机制
  • 处理不完整的帧数据

错误恢复:

  • 实现重试机制
  • 提供故障恢复策略
  • 记录详细的错误日志

硬件设计建议

接口保护:

  • 添加ESD保护器件
  • 使用隔离器件
  • 提供过压保护

信号质量:

  • 使用屏蔽电缆
  • 合理布置终端电阻
  • 避免信号反射

总结

Modbus RTU 协议虽然简单,但在实际应用中需要注意时序、校验和物理层连接的细节。遵循这些规范可以确保通信的可靠性和稳定性。

相关文档: