Modbus RTU(Remote Terminal Unit)是一种在工业自动化领域应用极为广泛的串行通信协议。它以其结构简单、开放性强、可靠性高和硬件成本低等特点,成为连接可编程逻辑控制器(PLC)、传感器、执行器、智能仪表等设备的事实标准。理解其报文结构是进行设备通信、调试和开发的基础。以下将从协议基础、帧结构、各字段详解、校验算法及实例等多个维度进行深入剖析。
一、 协议概述与核心特点
在深入报文细节前,需了解Modbus RTU的基本工作模式与特点,这是理解报文设计初衷的基石。
主从(客户端/服务器)架构:Modbus RTU采用严格的主从式通信。网络中存在一个主设备(Master/Client)和最多247个(理论上)从设备(Slave/Server)。所有通信均由主设备发起,从设备仅在收到针对自身地址的请求后才进行响应。这种模式简化了网络冲突管理,但也决定了通信的时序性。
串行传输介质:协议基于RS-232或RS-485串行总线实现。其中,RS-485因其支持差分信号、抗干扰能力强、传输距离远(可达1200米)且可连接多个设备(通常最多32个),在工业现场更为常见。
二进制编码与紧凑帧结构:与Modbus ASCII模式使用ASCII字符传输不同,RTU模式采用紧凑的二进制编码,所有数据(地址、功能、数据、校验)均以原始字节形式传输,无起始和结束字符,传输效率更高。
数据模型:协议定义了四种基本的数据模型,映射到设备的存储区:
线圈(Coils) :可读写的1位(比特)变量,通常表示开关量输出。
离散输入(Discrete Inputs) :只读的1位变量,通常表示开关量输入。
保持寄存器(Holding Registers) :可读写的16位(2字节)变量,通常存储设备参数、设定值等。
输入寄存器(Input Registers) :只读的16位变量,通常存储模拟量输入、状态信息等。
可靠性保障:通过 循环冗余校验(CRC-16) 确保报文在传输过程中的完整性。同时,通过帧间至少3.5个字符时间的静默间隔来界定帧的起始与结束。

二、 RTU报文帧结构详解
Modbus RTU的报文帧(或称数据帧)是通信的基本单位。一个完整的RTU帧由以下几个部分按顺序连续构成:
| 字段名称 | 长度(字节) | 描述 |
|---|---|---|
| 从站地址 (Slave Address) | 1 | 标识目标从设备的地址。 |
| 功能码 (Function Code) | 1 | 指示从设备需要执行的操作类型。 |
| 数据域 (Data Field) | N (0 – 252) | 承载请求参数或响应数据,内容依功能码而定。 |
| CRC校验码 (CRC Checksum) | 2 | 对整个帧(地址、功能码、数据域)进行循环冗余校验的结果。 |
帧长度限制:整个RTU帧的最大长度为256字节。因此,数据域(N)的最大长度受此限制,通常为252字节(256 – 地址1 – 功能码1 – CRC2)。
时序要求:
帧间间隔 (Inter-frame Delay) :前后两帧之间必须保持至少3.5个字符时间的静默期。接收方以此来判断一帧的结束和新一帧的开始。
帧内间隔:帧内各个字节之间的传输间隔应小于1.5个字符时间,否则接收方可能认为帧传输不完整。
“字符时间”取决于波特率(Baud Rate)。例如,在9600波特率下,传输1个字符(包括起始位、数据位、停止位,通常11位)的时间约为1.14ms。因此,3.5个字符时间约为4ms。
三、 各字段深度解析
1. 从站地址域 (Address Field)
作用:在多点通信网络中,唯一标识目标从设备,实现寻址。只有地址匹配的从设备才会处理该帧并作出响应。
取值范围:通常为1 – 247(十进制)。部分设备也支持地址0.此地址被保留用于广播。主设备向地址0发送请求时,所有从设备都会接收但不作响应(某些写操作例外)。每个从设备在总线上必须配置唯一的地址。
2. 功能码域 (Function Code Field)
作用:定义请求的操作类型,是报文的“指令”核心。它决定了数据域的格式和从设备的响应方式。
取值范围:1 – 255(0x01 – 0xFF)。其中,1-127为公共功能码,128-255用于异常响应。
常见功能码列表:
| 功能码 (十六进制) | 名称 | 操作对象 | 访问类型 |
|---|---|---|---|
| 0x01 | Read Coils | 线圈 | 读 |
| 0x02 | Read Discrete Inputs | 离散输入 | 读 |
| 0x03 | Read Holding Registers | 保持寄存器 | 读 |
| 0x04 | Read Input Registers | 输入寄存器 | 读 |
| 0x05 | Write Single Coil | 单个线圈 | 写 |
| 0x06 | Write Single Register | 单个保持寄存器 | 写 |
| 0x0F | Write Multiple Coils | 多个线圈 | 写 |
| 0x10 | Write Multiple Registers | 多个保持寄存器 | 写 |
异常响应:如果从设备处理请求时发生错误(如非法地址、非法数据值等),它会返回一个异常响应帧。此时,功能码 = 请求功能码 + 0x80,并在数据域中携带一个异常代码以说明错误原因。
3. 数据域 (Data Field)
作用:承载与功能码相关的具体信息。在请求帧中,它包含操作所需的参数(如起始地址、数量、要写入的数据等);在响应帧中,它包含操作结果(如读取到的数据)。
长度可变:其内容完全取决于功能码。例如:
读寄存器请求 (0x03) :数据域包含2字节的起始地址(高字节在前)和2字节的寄存器数量。
读寄存器正常响应 (0x03) :数据域包含1字节的“数据字节数”,后跟读取到的寄存器值(每个寄存器2字节)。
写单个线圈请求 (0x05) :数据域包含2字节的输出地址和2字节的输出值(0x0000表示关,0xFF00表示开)。
4. CRC校验域 (CRC Field)
作用:提供强大的错误检测机制,验证从地址域到数据域的所有内容在传输过程中是否发生错误。发送方计算CRC并附加在帧尾;接收方重新计算并与接收到的CRC比较,若不一致则丢弃该帧。
算法:Modbus RTU采用CRC-16算法,多项式为 0x8005(或表示为反转多项式 0xA001)。
计算步骤:
初始化一个16位的CRC寄存器为 0xFFFF。
将帧中第一个字节(地址)与CRC寄存器的低8位进行异或运算,结果存回CRC寄存器。
将CRC寄存器右移一位(向LSB方向),最高位补零。
4. 检查移出的最低位(LSB):
* 若为 1,则将CRC寄存器与多项式 0xA001 进行异或。
* 若为 0,则不做处理。
5. 重复步骤3和4.共8次(处理完一个字节的所有位)。
6. 对帧中的下一个字节重复步骤2~5.直到处理完除CRC字段本身外的所有字节。
7. 最终CRC寄存器中的值即为CRC校验码。
8. 字节顺序:将计算得到的16位CRC校验码,低字节在前,高字节在后附加到报文末尾。
四、 不同功能码报文格式实例分析
以下通过几个典型功能码的请求与响应帧示例,展示数据域的具体构成(假设从站地址为0x01.CRC已计算并附加)。
1. 读取保持寄存器 (功能码 0x03)
请求帧:读取从地址0x0002开始的3个保持寄存器。
帧结构:[地址][功能码][起始地址高][起始地址低][数量高][数量低][CRC低][CRC高]
示例:01 03 00 02 00 03 CRC (00 02 = 地址2. 00 03 = 数量3)
正常响应帧:
帧结构:[地址][功能码][字节数][数据1高][数据1低][数据2高][数据2低]…[CRC低][CRC高]
示例:01 03 06 00 0A 00 64 01 F4 CRC (06表示后续有6个数据字节;00 0A=10. 00 64=100. 01 F4=500)
2. 写入单个保持寄存器 (功能码 0x06)
请求帧:向地址0x0003的保持寄存器写入值0x1234.
帧结构:[地址][功能码][寄存器地址高][寄存器地址低][数据高][数据低][CRC低][CRC高]
示例:01 06 00 03 12 34 CRC
正常响应帧:成功执行后,从设备回显完整的请求帧作为响应。
示例:01 06 00 03 12 34 CRC (与请求帧完全相同)
3. 写入多个线圈 (功能码 0x0F)
请求帧:从线圈地址0x0013开始,写入5个线圈的状态(例如:开、开、关、开、关 -> 二进制11010.即0x1A,但需按字节对齐填充)。
帧结构更复杂:[地址][功能码][起始地址高][起始地址低][数量高][数量低][字节数][数据字节…][CRC低][CRC高]
示例:01 0F 00 13 00 05 01 1A CRC (00 05=数量5;01=后续数据占1字节;1A=二进制0001 1010.代表5个线圈状态)
4. 异常响应示例
如果主站发送了一个非法的读请求(例如,读取不存在的寄存器地址),从站可能返回:
帧结构:[地址][异常功能码][异常码][CRC低][CRC高]
示例:01 83 02 CRC (83 = 0x03 + 0x80;02 = 异常码,表示“非法数据地址”)
五、 总结与要点回顾
Modbus RTU报文的核心在于其简洁而严谨的四段式结构。理解报文的关键在于:
- 寻址:通过地址域在总线网络中精准定位设备。
- 指令:通过功能码明确操作意图和对象。
- 参数与载荷:通过数据域传递操作的具体细节和结果。
- 保障:通过CRC校验和严格的时序规则确保通信的可靠性。
在实际应用和调试中,通常使用如Modbus Poll、Modbus Slave等专业软件或串口助手,通过比对发送的请求报文和接收的响应报文(包括正常响应和异常响应),可以快速定位通信故障是源于物理连接、参数配置(波特率、地址)、报文格式错误还是设备本身的问题。掌握报文的每一个字节含义,是进行工业设备通信互联和深度开发的必备技能。
