一、知识点
1. 什么是Modbus协议?
Modbus 是一种工业通信协议,最早由 Modicon 公司在1979年提出,目的是用于 PLC(可编程逻辑控制器)之间的数据通信。它是主从式通信,即一个主机(主设备)控制一个或多个从机(从设备)。
它常用于 RS-232、RS-485 串口通信,也可以用于 TCP/IP 网络通信(叫做 Modbus TCP)。
2. 核心特征
特征项 | 内容 |
通信结构 | 主从式(Master/Slave) |
通信方式 | 请求-响应(Request-Response) |
通信介质 | 串口(Modbus RTU/ASCII)或以太网(Modbus TCP) |
编码格式 | RTU(二进制),ASCII(文本),TCP(基于网络) |
最大从设备 | 通常为247个 |
3. 常见的几种 Modbus 协议类型
Modbus RTU
使用二进制格式传输
帧紧凑,效率高
常用于 RS-485
Modbus ASCII
使用 ASCII 文本格式传输
更易调试,但效率低
常用于 RS-232
Modbus TCP
基于以太网,使用 TCP/IP 协议栈
没有 CRC 校验(TCP 自带校验)
4. Modbus RTU 数据帧结构
字段 说明 从机地址(1字节) 目标设备地址,0x01 ~ 0xF7,总共:1~247 功能码(1字节) 表示请求类型(如读取、写入等) 数据(N字节) 请求的具体数据(如寄存器地址、数量、值) CRC 校验(2字节) 校验数据正确性,CRC_L CRC_H (1)地址域:主站要访问的从站地址,其范围 0~247
地址范围是
0~247
(即十进制0x00~0xF7
),最大支持 247 个从站。地址 0 是一个特殊广播地址(所有从站接收但不应应答)。
(2)功能码:主站想对从站执行的操作
功能码表示主站具体请求什么操作,如“读取保持寄存器(0x03)”“写单个线圈(0x05)”等。
每种功能码都对应 特定的数据区。
功能码 操作 数据区名称 地址前缀 01 读线圈(输出位) Coils 0xxxx 02 读离散输入位 Discrete Inputs 1xxxx 03 读保持寄存器 Holding Registers 4xxxx 04 读输入寄存器 Input Registers 3xxxx 05 写单个线圈 Coils 0xxxx 06 写单个保持寄存器 Holding Registers 4xxxx 0F(15) 写多个线圈 Coils 0xxxx 10(16) 写多个保持寄存器 Holding Registers 4xxxx (3)数据字段(Data):包含具体的操作内容
操作类型 数据字段内容 读操作 起始地址(2字节) + 数据数量(2字节) 写单个 起始地址(2字节) + 要写的数据(2字节) 写多个 起始地址 + 数据数量 + 字节数 + 实际数据 (4)差错校验:确保数据传输正确
为了保证数据传输的正确性,Modbus协议会在数据帧最后面加上两个字节的差错校验。
二、传输示例
示例一:主机请求读取从机0x01的保持寄存器1
从机地址:
0x01
功能码:
0x03
寄存器地址:
0x0000
(Modbus地址 40001 -> 实际为0)寄存器数量:
0x0001
CRC:
自动计算
→ 十六进制完整帧为:
01 03 00 00 00 01 CRC_L CRC_H
示例二:主站请求读取从站 0x03 的输入寄存器9
从站地址:
0x03
功能码:
0x04
(读取输入寄存器)寄存器起始地址:
0x0008
(Modbus地址 40009 → 实际地址为 8)寄存器数量:
0x0001
(读取 1 个寄存器)CRC校验:
0xB03B
(低字节在前)→ 十六进制完整帧为:
03 04 00 08 00 01 B0 3B
从机接收后的响应 。响应帧(从站 → 主站)
从站地址:
0x03
功能码:
0x04
(读取输入寄存器)字节数:
0x02
(表示读取了 1 个寄存器 = 2 字节)寄存器值:
0x000A
(实际读取到的寄存器数据,十进制为 10)CRC校验:
0x40F7
(低字节在前)→ 十六进制完整帧为:
03 04 02 00 0A 40 F7
示例三:主站向从站 0x03 的保持寄存器地址 0x0001 开始写入 2 个寄存器(共 4 字节)。请求帧(主站→ 从站)
从站地址:
0x03
功能码:
0x10
(写多个保持寄存器)起始地址:
0x0001
(Modbus地址 40002 → 实际地址为 1)寄存器数量:
0x0002
(写入 2 个保持寄存器 = 4 字节)字节数:
0x04
(后续数据长度,共 4 字节)写入数据:
第一个寄存器数据:
0x000A
第二个寄存器数据:
0x0102
CRC校验:
0x9988
(低字节在前)→ 十六进制完整帧为:
03 10 00 01 00 02 04 00 0A 01 02 99 88
从机接收后的响应 。响应帧(从站 → 主站)
从站地址:
0x03
功能码:
0x10
(写多个保持寄存器)起始地址:
0x0001
(原样返回主站请求的起始地址)寄存器数量:
0x0002
(原样返回主站请求写入的寄存器数量)CRC校验:
0x11EA
(低字节在前)→ 十六进制完整帧为:
03 10 00 01 00 02 11 EA