深入解析Modbus RTU命令与应答机制插图1

Modbus RTU协议描述

Modbus是基于主从结构的通信协议。它使用RS-485, RS-422, RS-232接口,以及Ethernet TCP/IP网络(Modbus TCP协议)进行数据传输。

Modbus RTU消息包括:

  • SlaveID设备的地址
  • 功能码
  • 依赖于功能码的特殊数据
  • CRC-16(Modbus)

结构如下:

SlaveID    功能码 特殊数据    CRC16

如果你去掉SlaveID地址和CRC-16(Modbus),你将得到PDU(协议数据单元)。

SlaveID是设备的地址,可以从0到247之间选择值。值得注意的是,从248到255的地址是保留的。

模块中的数据存储在四个表中,其中两个是只读的,另外两个是读写的。每个表可以容纳9999个值。

以下是表的总结:

  • 离散输出线圈 (DO):读写;寄存器号1-9999;HEX地址范围0000到270E
  • 离散输入触点 (DI):只读;寄存器号10001-19999;HEX地址范围0000到270E
  • 模拟输入寄存器 (AI):只读;寄存器号30001-39999;HEX地址范围0000到270E
  • 模拟输出保持寄存器 (AO):读写;寄存器号40001-49999;HEX地址范围0000到270E

每个表都有一个寄存器号(例如AO的40001),它对应于一个地址(例如0000)。这种差异被称为”偏移”。表的偏移量分别为1, 10001, 30001和40001。

以一个例子说明:从40108到40110寄存器为设备地址17获取AI值的Modbus RTU请求如下:

11 03 006B 0003 7687

这个分解如下:

  • 11:SlaveID设备地址(十进制中的17或HEX中的11)
  • 03:功能码
  • 006B:第一个寄存器的地址(计算为40108-40001 = 107,这是HEX中的6B)
  • 0003:所需的寄存器数量(从40108到40110获取三个寄存器)
  • 7687:CRC校验和

Modbus RTU从设备会回复:

11 03 06 AE41 5652 4340 49AD

这转化为:

  • 设备地址:11(或十进制中的17)
  • 功能码:03
  • 字节计数(表示后面跟随6字节):06
  • 注册值AO0、AO1和AO2作为两字节序列
  • CRC值由49AD给出

模拟输出寄存器的值可以通过多种方式解释,例如:

  • 作为16位无符号整数(范围0至65535)
  • 作为16位有符号整数(范围-32768至32767)
  • 作为两个字符的ASCII字符串
  • 作为离散开/关值(0或1)
  • 作为32位无符号整数(范围0到4,294,967,295)
  • 作为32位有符号整数(范围-2,147,483,648至2,147,483,647)
  • 作为32位单精度IEEE浮点数(范围1.2×10^−38至3.4×10^+38)
  • 作为四字符ASCII字符串
深入解析Modbus RTU命令与应答机制插图3

Modbus RTU命令是什么?

以下是用于读取和写入Modbus RTU寄存器的代码表。

功能代码功能操作数据类型访问类型
01 (0x01)读取DO离散输出线圈状态读取
02 (0x02)读取DI离散输入状态读取
03 (0x03)读取AO保持寄存器16位
04 (0x04)读取AI输入寄存器16位
05 (0x05)写入一个DO强制单线圈离散
06 (0x06)写入一个AO预设单寄存器16位
15 (0x0F)多DO写入强制多线圈离散
16 (0x10)多AO写入预设多寄存器16位

如何发送Modbus RTU命令来读取离散输出?命令0x01

此命令用于读取DO数字输出的值。

PDU请求指定第一个DO寄存器的起始地址和后续所需的DO值数量。在PDU中,DO值从零开始寻址。

响应中的DO值为一个字节,对应位的值。

位值定义为1 = ON,0 = OFF。

第一个数据字节的低位包含在请求中指定地址的DO值。其余的DO值按照增加的值到字节的最高值。即从右到左。

如果请求的DO值少于八个,则响应中的其余位将填充为零(从低字节到高字节的方向)。字节计数进一步表示响应中数据的完整字节数。

一个从20到56的DO查询示例,针对设备的SlaveID地址17。第一个寄存器的地址将是0013十六进制=19,因为帐户是从0地址开始的(0014十六进制=20, -1零偏移=我们得到0013十六进制=19)。

字节请求字节回复
(Hex)字段名(Hex)字段名
11设备地址11设备地址
01功能代码01功能代码
00第一个寄存器地址高字节05更多的字节数
13第一个寄存器地址低字节CDDO 27-20的寄存器值 (1100 1101)
00寄存器数量高字节6BDO 35-28的寄存器值 (0110 1011)
25寄存器数量低字节B2DO 43-36的寄存器值 (1011 0010)
0ECRC-16(Modbus)0EDO 51-44的寄存器值 (0000 1110)
84CRC-16(Modbus)1BDO 56-52的寄存器值 (0001 1011)
45CRC-16(Modbus)
E6CRC-16(Modbus)
DO 27-20的输出状态显示为字节CD十六进制值,或在二进制系统中为1100 1101。

在寄存器DO 56-52中,右边请求了5位,其余的位填充为零以得到完整的字节(0001 1011)。

通道DO 56DO 55DO 54DO 53DO 52
00011011
十六进制1B

如何发送Modbus RTU命令来读取数字输入?命令0x02

此命令用于读取数字输入DI的值。

从寄存器# 10197到10218的DI请求示例,针对设备的SlaveID地址17。第一个寄存器的地址将是00C4十六进制=196,因为帐户是从0地址开始的。

字节请求字节回复
(Hex)字段名(Hex)字段名
11设备地址11设备地址
02功能代码02功能代码
00第一个寄存器地址高字节03更多的字节数
C4第一个寄存器地址低字节ACDI 10204-10197的寄存器值 (1010 1100)
00寄存器数量高字节DBDI 10212-10205的寄存器值 (1101 1011)
16寄存器数量低字节35DI 10218-10213的寄存器值 (0011 0101)
BACRC-16(Modbus)20CRC-16(Modbus)
A9CRC-16(Modbus)18CRC-16(Modbus)

如何发送Modbus RTU命令来读取模拟输出?命令0x03

此命令用于读取模拟输出AO的值。

从寄存器# 40108到40110的AO请求示例,针对设备的SlaveID地址17。第一个寄存器的地址将是006B十六进制=107,因为帐户是从0地址开始的。

字节请求字节回复
(Hex)字段名(

Hex) | 字段名
11 | 设备地址 | 11 | 设备地址
03 | 功能代码 | 03 | 功能代码
00 | 第一个寄存器地址高字节 | 06 | 更多的字节数
6B | 第一个寄存器地址低字节 | AE | #40108的寄存器值高位
00 | 寄存器数量高字节 | 41 | #40108的寄存器值低位
03 | 寄存器数量低字节 | 56 | #40109的寄存器值高位
76 | CRC校验和 | 52 | #40109的寄存器值低位
87 | CRC校验和 | 43 | #40110的寄存器值高位
40 | #40110的寄存器值低位
49 | CRC-16(Modbus)
AD | CRC-16(Modbus)

如何发送Modbus RTU命令来读取模拟输入?命令0x04

此命令用于读取模拟输入AI的值。

从寄存器# 30009的AI请求示例,针对设备的SlaveID地址17。第一个寄存器的地址是0008十六进制=8,因为帐户是从0地址开始的。

字节请求字节回复
(Hex)字段名(Hex)字段名
11设备地址11设备地址
04功能代码04功能代码
00第一个寄存器地址高字节02更多的字节数
08第一个寄存器地址低字节00#30009的寄存器值高位
00寄存器数量高字节0A#30009的寄存器值低位
01寄存器数量低字节F8CRC-16(Modbus)
B2CRC-16(Modbus)F4CRC-16(Modbus)
98CRC-16(Modbus)

如何发送Modbus RTU命令来写入离散输出?命令0x05

此命令用于记录DO数字输出的一个值。

值FF 00十六进制将输出设置为ON。

值00 00十六进制将输出设置为OFF。

所有其他值都无效,且不会影响输出值。

对这样的请求的正常响应是回声(响应中的重复请求),在DO状态已更改后返回。

示例,使用设备的SlaveID地址17的寄存器# 173的DO记录。寄存器地址为00AC十六进制=172,因为从0地址开始记录。

字节请求字节回复
(Hex)字段名(Hex)字段名
11设备地址11设备地址
05功能代码05功能代码
00第一个寄存器地址高字节00第一个寄存器地址高字节
AC第一个寄存器地址低字节AC第一个寄存器地址低字节
FF高字节值FF高字节值
00低字节值00低字节值
4ECRC-16(Modbus)4ECRC-16(Modbus)
8BCRC-16(Modbus)8BCRC-16(Modbus)
DO173输出状态已从OFF更改为ON。

如何发送Modbus RTU命令来记录模拟输出?命令0x06

此命令用于记录模拟输出AO的一个值。

示例,使用设备的SlaveID地址17的寄存器# 40002的AO记录。第一个寄存器的地址为0001十六进制=1,因为从0地址开始记录。

字节请求字节回复
(Hex)字段名(Hex)字段名
11设备地址11设备地址
06功能代码06功能代码
00第一个寄存器地址高字节00第一个寄存器地址高字节
01第一个寄存器地址低字节01第一个寄存器地址低字节
00高字节值00高字节值
03低字节值03低字节值
9ACRC-16(Modbus)9ACRC-16(Modbus)
9BCRC-16(Modbus)9BCRC-16(Modbus)

如何发送Modbus RTU命令来写入多个离散引脚?命令0x0F

此命令用于记录DO数字输出的多个值。

示例,写入多个DO,从设备的SlaveID地址17的寄存器# 20到# 29。寄存器地址为0013十六进制=19,因为从0地址开始记录。

字节请求字节回复
(Hex)字段名(Hex)字段名
11设备地址11设备地址
0F功能代码0F功能代码
00第一个寄存器地址高字节00第一个寄存器地址高字节
13第一个寄存器地址低字节13第一个寄存器地址低字节
00寄存器数量高字节00记录的寄存器数量高字节
0A寄存器数量低字节0A记录的寄存器数量低字节
02更多的字节数26CRC-16(Modbus)
CDDO 27-20的字节值 (1100 1101)99CRC-16(Modbus)
01DO 29-28的字节值 (0000 0001)
BFCRC-16(Modbus)
0BCRC-16(Modbus)

答案返回已记录的寄存器数量。

如何发送Modbus RTU命令来记录多个模拟输出?命令0x10

此命令用于记录模拟输出AO的多个值。

示例,记录多个AO,从设备的SlaveID地址17的寄存器# 40002和# 40003。第一个寄存器的地址为0001十六进制=1,因为从0地址开始记录。

字节请求字节回复
(Hex)字段名(Hex)字段名
11设备地址11设备地址
10功能代码10功能代码
00第一个寄存器地址高字节00第一个寄存器地址高字节
01第一个寄存器地址低字节01第一个寄存器地址低字节
00寄存器数量高字节00记录的寄存器数量高字节
02寄存器数量低字节02记录的寄存器数量低字节
04更多的字节数12CRC-16(Modbus)
0040002高位值98CRC-16(Modbus)
0A40002低位值
0140003高位值
0240003低位值
C6CRC-16(Modbus)
F0CRC-16(Modbus)
深入解析Modbus RTU命令与应答机制插图5

Modbus请求的错误

如果设备接收到一个请求,但无法处理该请求,该设备将以错误代码进行响应。

响应将包含修改后的功能代码,高位字节为1。

示例:

原始值结果值
请求中的功能代码响应中的功能错误代码
01 (01 hex) 0000 0001129 (81 hex) 1000 0001
02 (02 hex) 0000 0010130 (82 hex) 1000 0010
03 (03 hex) 0000 0011131 (83 hex) 1000 0011
04 (04 hex) 0000 0100132 (84 hex) 1000 0100
05 (05 hex) 0000 0101133 (85 hex) 1000 0101
06 (06 hex) 0000 0110134 (86 hex) 1000 0110
15 (0F hex) 0000 1111143 (8F hex) 1000 1111
16 (10 hex) 0001 0000144 (90 hex) 1001 0000

带有错误的请求和响应示例:

字节请求字节响应
(Hex)字段名(Hex)字段名
0A设备地址0A设备地址
01功能代码81已更改的功能代码
04第一个寄存器地址高字节02错误代码
A1第一个寄存器地址低字节B0CRC-16(Modbus)
00寄存器数量高字节53CRC-16(Modbus)
01寄存器数量低字节
ACCRC-16(Modbus)
63CRC-16(Modbus)

错误代码说明

01 | 不能处理已接受的功能代码。
02 | 请求中指定的数据地址不可用。
03 | 查询数据字段中包含的值是无效值。
04 | 从站尝试执行请求的操作时发生不可恢复的错误。
05 | 从站已接受请求并正在处理,但需要较长时间。此响应防止主机生成超时错误。
06 | 从站正忙于处理命令。主机在从站空闲时必须重复消息。
07 | 从站无法执行请求中指定的程序功能。使用功能编号13或14的不成功的程序请求返回此代码。主机必须从从站请求诊断信息或错误信息。
08 | 从站在读取扩展内存时检测到奇偶校验错误。主机可以重复请求,但通常在这种情况下需要维修。

相关新闻

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

邮箱

cloud@modbus.cn

QQ
QQ
微信
微信
SHARE
TOP