1. 课程导入

Modbus RTU 是工业现场最广泛使用的串行通信协议之一。它结构简单、实现成本低、兼容性强,几乎所有的 PLC、变频器、仪表、传感器都支持它。对于嵌入式开发者来说,掌握 Modbus RTU 从站开发,意味着能够把一块普通的单片机板卡变成工业现场可被主站轮询、可被组态软件识别的标准设备。本课程的目标,就是带你从零构建一个稳定、可测试、可移植的 Modbus RTU 从站固件。

一、学习目标:从“能通”到“可靠”

很多初学者第一次实现 Modbus RTU 时,往往只关注“能不能读到数据”。但工业现场真正考验的是:帧间隔是否严格、CRC 校验是否无误、异常码是否规范、寄存器映射是否清晰、断线重连是否稳定。因此本课程的学习目标分为四个层次:

  • 协议层:理解 RTU 帧结构、功能码语义、异常响应机制与 CRC16 算法。
  • 驱动层:掌握 UART + 定时器实现 3.5 字符静默间隔的收发状态机。
  • 应用层:设计寄存器映射表,实现线圈、离散输入、保持寄存器、输入寄存器的读写。
  • 工程层:完成调试、抓包、异常注入、压力测试与移植封装。

核心判断标准:一个合格的 Modbus RTU 从站,不是“主站能读到数”,而是“在任何合法或非法请求下,都能在正确的时间返回正确的响应或正确的异常码”。

二、核心概念:四个必须刻在脑子里的对象

Modbus 的数据模型非常简洁,所有内容都围绕四张表展开。理解这四张表的区别,是后续开发不混乱的前提。

数据区 对象类型 读写属性 常见功能码 典型用途
线圈 Coils 1 位 读写 0x01 / 0x05 / 0x0F 继电器输出、开关控制
离散输入 Discrete Inputs 1 位 只读 0x02 限位开关、按钮状态
保持寄存器 Holding Registers 16 位 读写 0x03 / 0x06 / 0x10 参数设定、阈值配置
输入寄存器 Input Registers 16 位 只读 0x04 温度、电压、采样值

除了数据模型,RTU 帧的物理边界也至关重要。RTU 不使用起始符和结束符,而是用时间间隔来划分帧:帧内字符间隔不得超过 1.5 个字符时间,帧与帧之间至少保持 3.5 个字符时间。这个规则决定了从站接收状态机的设计方式。

典型 RTU 请求帧(读保持寄存器):
[从站地址][功能码][起始地址Hi][起始地址Lo][数量Hi][数量Lo][CRC Lo][CRC Hi]
   0x01      0x03      0x00        0x00        0x00      0x02      0xC4    0x0B

典型正常响应:
[从站地址][功能码][字节数][数据...][CRC Lo][CRC Hi]

典型异常响应:
[从站地址][功能码|0x80][异常码][CRC Lo][CRC Hi]
异常码 0x02 表示非法数据地址,0x03 表示非法数据值。

三、整体框架:从硬件到协议栈的分层结构

一个可维护的从站工程,不应把所有逻辑塞进一个中断函数。推荐按“物理层—链路层—协议层—应用层”四层组织。下面的 SVG 展示了本课程贯穿始终的整体架构与数据流关系。

Modbus RTU 从站工程整体框架 Modbus 主站 PLC / 组态软件 物理层 RS-485 收发器 UART 波特率 / 校验 链路层 3.5T 帧间隔定时 CRC16 校验 协议层 功能码解析 异常码生成 应用层 寄存器映射表 业务数据绑定 四张数据表(共享内存区) 线圈 离散输入 保持寄存器 输入寄存器 请求 字节流 完整帧 读写指令 映射访问 地址校验 响应回传 数据自下而上解析,响应自上而下回传;四张表是协议层与应用层之间的唯一契约。

四、实战路线图:30 章如何一步步走完

本课程不是协议手册的复述,而是一条可执行的工程路线。整体节奏可以概括为“先通链路,再通协议,最后通工程”。

  1. 基础准备阶段:串口参数、RS-485 硬件、CRC16 实现、帧间隔定时。
  2. 协议实现阶段:功能码 0x01/0x02/0x03/0x04/0x05/0x06/0x0F/0x10 的请求解析与响应组帧。
  3. 数据建模阶段:寄存器映射表设计、大小端处理、32 位浮点数的寄存器拆分。
  4. 健壮性阶段:异常码、超时、噪声帧、地址越界、广播地址 0x00 的处理。
  5. 工程化阶段:分层封装、单元测试、Modbus Poll 联调、长时间压力测试。

学习建议:每学完一个功能码,就立刻用 Modbus Poll 或串口助手发一帧真实报文验证。不要等“全部写完再测”,Modbus 的问题往往藏在字节序和地址偏移里。

五、常见误区与复盘提醒

在开始动手之前,先避开几个高频坑,可以节省大量调试时间。

  • 误区一:把寄存器地址直接当成数组下标。Modbus 报文中的地址是协议地址,实际映射时通常需要减去 1 或按文档偏移处理,必须与主站组态保持一致。
  • 误区二:忽略 3.5 字符间隔。如果接收端用固定超时或“收到就处理”,在高速轮询下会把两帧粘成一帧,导致 CRC 失败。
  • 误区三:异常时直接不回帧。规范要求从站对非法地址、非法数量返回异常响应,否则主站会一直等待超时。
  • 误区四:CRC 字节序写反。Modbus RTU 的 CRC 是低字节在前、高字节在后,这是最常见的“看起来对但就是不通”的原因。

复盘要点:调试 Modbus RTU 时,优先确认三件事——波特率与校验位是否一致、从站地址是否匹配、CRC 字节序是否正确。这三项能解决绝大多数“完全无响应”问题。

接下来,课程将从最基础的串口参数与 RS-485 电气特性开始,逐步搭建起一个完整的 Modbus RTU 从站。你需要的不是死记协议,而是建立“帧—状态机—寄存器表”三者之间的清晰对应关系。只要这条主线不丢,后面的每一章都会落在同一个工程骨架上。