Modbus RTU 与 TCP 学习笔记

本文系统介绍 Modbus TCP 与 Modbus RTU 的帧格式、核心差异,并对常用功能码进行逐一举例说明,帮助开发者快速掌握这一工业通信领域最常用的协议之一。


一、Modbus 协议简介

Modbus 是一种应用于工业控制领域的串行通信协议,由 Modicon(现为施耐德电气)于 1979 年发布。因其协议简单、公开透明、无需授权费用,已成为工业设备之间事实上的通信标准。

常见的 Modbus 传输模式有三种:

模式 传输介质 特点
Modbus RTU RS-232 / RS-485 二进制编码,紧凑高效,带 CRC 校验
Modbus ASCII RS-232 / RS-485 ASCII 字符编码,可读性强,效率较低
Modbus TCP 以太网 基于 TCP/IP,加入 MBAP 报文头,无 CRC

本文重点讲解 Modbus TCPModbus RTU 两种模式。


二、Modbus TCP 数据帧格式

Modbus TCP 的数据帧由两部分组成:MBAP 报文头 + PDU 数据单元

2.1 MBAP 报文头(7 字节)

MBAP(Modbus Application Protocol Header)是 Modbus TCP 特有的报文头:

字段 长度 说明
事务处理标识(Transaction ID) 2 字节 报文序列号,每次通信后加 1,用于区分不同报文
协议标识(Protocol ID) 2 字节 固定为 0x0000,表示 Modbus TCP 协议
长度(Length) 2 字节 后续数据的长度(包括单元标识符 1 字节 + PDU)
单元标识符(Unit ID) 1 字节 从机设备地址(类似 RTU 中的从机地址)

示例:一帧 Modbus TCP 报文如下:

复制代码
00 01 00 00 00 06 01 06 08 00 12 34
│  ─┘│  ─┘│  ─┘│  ││  ─┘│  ─┘│  ─┘
│    │    │    │  ││    │    │    └── 写入值 0x1234
│    │    │    │  ││    │    └─────── 寄存器地址 0x0800
│    │    │    │  ││    └──────────── 功能码 0x06(写单个寄存器)
│    │    │    │  │└───────────────── 单元标识符(设备号 01)
│    │    │    │  └────────────────── 长度(6 字节)
│    │    │    └───────────────────── 协议标识(Modbus TCP)
│    │    └────────────────────────── 事务处理标识(序号 0001)
└──────────────────────────────────── 事务处理标识(序号 0001)

2.2 PDU 数据单元

PDU(Protocol Data Unit)由 1 字节功能码 + N 字节数据 组成,数据长度由具体功能决定。

Modbus 的操作对象有四种:

操作对象 类型 功能码范围 访问权限
线圈(Coils) 布尔量 01、05、0F 读写
离散输入(Discrete Inputs) 布尔量 02 只读
保持寄存器(Holding Registers) 16 位整型 03、06、10 读写
输入寄存器(Input Registers) 16 位整型 04 只读

三、常用功能码详解与示例

3.1 0x01 ------ 读线圈状态(Read Coils)

读取从机中线圈的 ON/OFF 状态,属于位操作

请求 :从地址 0x0002 开始,读 0x0008 个线圈状态。

复制代码
00 01 00 00 00 06 01 01 00 02 00 08
字段 说明
事务处理标识 00 01 序号
协议标识 00 00 Modbus TCP
长度 00 06 后续 6 字节
单元标识符 01 设备号 1
功能码 01 读线圈
起始地址 00 02 从地址 0x0002 开始
操作个数 00 08 读 8 个线圈

响应

复制代码
00 01 00 00 00 04 01 01 01 01

响应数据中,01 表示 8 个线圈的状态字节:0x01 = 0000 0001(二进制),从右往左数第 1 个线圈为 ON,其余为 OFF


3.2 0x02 ------ 读离散量输入(Read Discrete Inputs)

读取离散量输入状态,只读,同样是位操作。

请求 :从地址 0x0000 开始,读 0x0012(18)个离散量输入。

复制代码
00 01 00 00 00 06 01 02 00 00 00 12

响应

复制代码
00 01 00 00 00 06 01 02 03 01 04 00

响应数据为 01 04 00,对应二进制:

  • 0x01 = 0000 0001 → 第 1 个输入为 ON
  • 0x04 = 0000 0100 → 第 11 个输入为 ON
  • 0x00 = 0000 0000 → 其余均为 OFF

3.3 0x03 ------ 读保持寄存器(Read Holding Registers)

读取保持寄存器的值,16 位整型,是最常用的功能码之一。

请求 :从地址 0x0000 开始,读 0x0003 个寄存器。

复制代码
00 01 00 00 00 06 01 03 00 00 00 03

响应

复制代码
00 01 00 00 00 09 01 03 06 00 21 00 00 00 00

响应数据 06 表示后面有 6 字节数据(3 个寄存器 × 2 字节):

  • 寄存器 0:00 21 = 0x0021
  • 寄存器 1:00 00 = 0x0000
  • 寄存器 2:00 00 = 0x0000

3.4 0x04 ------ 读输入寄存器(Read Input Registers)

读取输入寄存器的值,只读,格式与 0x03 相同。

请求 :从地址 0x0002 开始,读 0x0005 个连续输入寄存器。

复制代码
00 01 00 00 00 06 01 04 00 02 00 05

响应

复制代码
00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00

响应数据 0A = 10 字节(5 个寄存器 × 2 字节):

  • 寄存器 2:00 0C = 0x000C
  • 其余寄存器均为 0x0000

3.5 0x05 ------ 写单个线圈(Write Single Coil)

将指定地址的线圈设置为 ON 或 OFF。

请求 :将地址 0x0003 的线圈设置为 ON。

复制代码
00 01 00 00 00 06 01 05 00 03 FF 00

写线圈时,FF 00 表示 ON,00 00 表示 OFF。

响应

复制代码
00 01 00 00 00 06 01 05 00 03 FF 00

响应与请求完全一致,表示写入成功。


3.6 0x06 ------ 写单个保持寄存器(Write Single Register)

向指定保持寄存器写入一个 16 位值。

请求 :向地址 0x0000 的保持寄存器写入 0x000A

复制代码
00 01 00 00 00 06 01 06 00 00 00 0A

响应

复制代码
00 01 00 00 00 06 01 06 00 00 00 0A

响应与请求一致,表示写入成功。


3.7 0x0F(15)------ 写多个线圈状态(Write Multiple Coils)

一次性写入多个线圈的 ON/OFF 状态。

请求 :从地址 0x0000 开始,写入前 5 个线圈状态为 ON。

复制代码
00 01 00 00 00 08 01 0F 00 00 00 05 01 1F
字段 说明
起始地址 00 00 从地址 0x0000 开始
操作个数 00 05 写 5 个线圈
写入字节数 01 后续 1 字节数据
写入数据 1F = 0001 1111 前 5 个线圈均为 ON

响应

复制代码
00 01 00 00 00 06 01 0F 00 00 00 05

响应返回起始地址和操作个数,表示写入成功。


3.8 0x10(16)------ 写多个保持寄存器(Write Multiple Registers)

一次性写入多个保持寄存器的值。

请求 :从地址 0x0000 开始,写入前 5 个保持寄存器,数据均为 0x0000

复制代码
00 01 00 00 00 11 01 10 00 00 00 05 0A 00 00 00 00 00 00 00 00 00 00
字段 说明
起始地址 00 00 从地址 0x0000 开始
操作个数 00 05 写 5 个寄存器
写入字节数 0A = 10 5 个寄存器 × 2 字节
写入数据 00 00 ... 5 个寄存器均为 0x0000

响应

复制代码
00 01 00 00 00 06 01 10 00 00 00 05

响应返回起始地址和写入寄存器个数,表示写入成功。


四、Modbus RTU 与 Modbus TCP 的核心区别

对比项 Modbus RTU Modbus TCP
传输介质 RS-232 / RS-485 串口 以太网(TCP/IP)
报文头 无 MBAP 头 7 字节 MBAP 头
地址字段 1 字节从机地址(帧首) 1 字节单元标识符(MBAP 中)
校验方式 CRC16(帧尾 2 字节) 无 CRC(TCP 自带校验)
帧间隔 需满足 3.5 个字符时间的静默间隔 无需额外帧间隔,由 TCP 流控制
主从模式 一主多从 支持多主多从(基于 TCP 连接)

实例对比 :向从机 01 的地址 0x0105 写入 0x0190

  • Modbus RTU 请求01 06 01 05 01 90 99 CB

    • 01 = 从机地址
    • 06 = 功能码
    • 01 05 = 寄存器地址
    • 01 90 = 写入值
    • 99 CB = CRC16 校验码
  • Modbus TCP 请求00 01 00 00 00 06 01 06 01 05 01 90

    • 前 7 字节为 MBAP 头
    • 无 CRC 校验

五、功能码速查表

功能码 名称 操作对象 读写属性
0x01 读线圈状态 线圈
0x02 读离散量输入 离散输入
0x03 读保持寄存器 保持寄存器
0x04 读输入寄存器 输入寄存器
0x05 写单个线圈 线圈
0x06 写单个保持寄存器 保持寄存器
0x0F 写多个线圈 线圈
0x10 写多个保持寄存器 保持寄存器

六、总结

Modbus 协议之所以在工业领域长盛不衰,核心在于其简单、开放、易实现

  • Modbus TCP 适合现代以太网环境,借助 MBAP 头实现多设备区分,无需担心校验问题;
  • Modbus RTU 适合传统串口总线场景,帧结构紧凑,CRC 校验保证可靠性;
  • 两者在 PDU 层面完全一致,仅帧头和校验方式不同,因此上层应用代码可以高度复用。

掌握上述 8 个常用功能码,即可覆盖绝大多数 Modbus 通信场景。希望本文对你有所帮助!


参考资料:Modbus_Application_Protocol_V1_1b.pdf(官方标准文档)

相关推荐
轻闲一号机1 小时前
【语音】笔记
前端·笔记·算法
叶子野格1 小时前
《C语言学习:位运算》17
c语言·开发语言·c++·学习·visual studio
aWty_1 小时前
实分析入门(12)--可测函数
学习·数学·算法·实变函数
词元Max2 小时前
4.1 监督学习入门:线性回归与分类
学习·分类·线性回归
-To be number.wan2 小时前
计算机组成原理 | 位扩展、字扩展与片选逻辑
学习·计算机组成原理
小烤箱2 小时前
ROS2 学习资源与学习方法
学习·ros·学习方法·ros2
casual~2 小时前
十六届蓝桥杯国赛个人题解
经验分享·学习·算法·蓝桥杯
小陈phd2 小时前
多模态大模型学习笔记(四十六)——图像-文本生成(Image-Text Generation):跨模态创作与语义互通
笔记·学习·计算机视觉
噜噜噜阿鲁~2 小时前
python学习笔记 | 11.4、面向对象高级编程-定制类
笔记·python·学习