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 TCP 与 Modbus 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(官方标准文档)

相关推荐
sunoo-22932 分钟前
【ARM嵌入式学习笔记第十天】i.MX6ULL eLCDIF控制器驱动RGB LCD全解析(硬件原理+寄存器配置+裸机代码)
arm开发·笔记·学习
kaiyou20261 小时前
用户研究岗秋招,统计分析能力怎么学习和证明?
数据库·python·学习
知识分享小能手1 小时前
C++ 学习教程,从入门到精通,string类和标准模板库 — 完整知识点详解(16)
开发语言·c++·学习
听风若依2 小时前
数据在内存中的存储-纸面笔记整理
c语言·笔记
xiaominngtongxue2 小时前
从中职技能节看实训教学的组织逻辑
笔记
杨逢昌工厂6S管理2 小时前
109-杨逢昌车间管理负熵循环:三环体系持续输出负熵的机制解析
经验分享·笔记·职场和发展·学习方法
inferno2 小时前
SVN学习笔记(二)
笔记·学习·svn
传奇开心果编程3 小时前
【ArkUI进阶练中学】第12课:应用架构演进与遗留系统迁移
学习·ui·华为·harmonyos
我想我不够好。3 小时前
装一个纯净的系统
学习