
Modbus RTU프로토콜설명
Modbus是基于主从结构的통신 프로토콜。它使用RS-485, RS-422, RS-232인터페이스,以及이더넷 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设备주소(10진수中的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(或10진수中的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命令是什么?
以下是用于읽기和쓰기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。第一个레지스터的주소将是001316진수=19,因为帐户是从0주소开始的(001416진수=20, -1零偏移=我们得到001316진수=19)。
| 바이트 | 请求 | 바이트 | 回复 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 11 | 设备주소 | 11 | 设备주소 |
| 01 | 功能代码 | 01 | 功能代码 |
| 00 | 第一个레지스터주소高바이트 | 05 | 更多的바이트数 |
| 13 | 第一个레지스터주소低바이트 | CD | DO 27-20的레지스터 값 (1100 1101) |
| 00 | 레지스터 수량高바이트 | 6B | DO 35-28的레지스터 값 (0110 1011) |
| 25 | 레지스터 수량低바이트 | B2 | DO 43-36的레지스터 값 (1011 0010) |
| 0E | CRC-16(Modbus) | 0E | DO 51-44的레지스터 값 (0000 1110) |
| 84 | CRC-16(Modbus) | 1B | DO 56-52的레지스터 값 (0001 1011) |
| 45 | CRC-16(Modbus) | ||
| E6 | CRC-16(Modbus) | ||
| DO 27-20的출력 상태显示为바이트CD16진수值,或在2진수系统中为1100 1101。 |
在레지스터DO 56-52中,右边请求了5位,其余的位填充为零以得到完整的바이트(0001 1011)。
| 通道 | - | - | - | DO 56 | DO 55 | DO 54 | DO 53 | DO 52 |
|---|---|---|---|---|---|---|---|---|
| 位 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
| 16진수 | 1B |
如何보내기Modbus RTU命令来읽기数字입력?命令0x02
此命令用于읽기数字입력DI的值。
从레지스터# 10197到10218的DI请求예제,针对设备的SlaveID주소17。第一个레지스터的주소将是00C416진수=196,因为帐户是从0주소开始的。
| 바이트 | 请求 | 바이트 | 回复 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 11 | 设备주소 | 11 | 设备주소 |
| 02 | 功能代码 | 02 | 功能代码 |
| 00 | 第一个레지스터주소高바이트 | 03 | 更多的바이트数 |
| C4 | 第一个레지스터주소低바이트 | AC | DI 10204-10197的레지스터 값 (1010 1100) |
| 00 | 레지스터 수량高바이트 | DB | DI 10212-10205的레지스터 값 (1101 1011) |
| 16 | 레지스터 수량低바이트 | 35 | DI 10218-10213的레지스터 값 (0011 0101) |
| BA | CRC-16(Modbus) | 20 | CRC-16(Modbus) |
| A9 | CRC-16(Modbus) | 18 | CRC-16(Modbus) |
如何보내기Modbus RTU命令来읽기模拟출력?命令0x03
此命令用于읽기模拟출력AO的值。
从레지스터# 40108到40110的AO请求예제,针对设备的SlaveID주소17。第一个레지스터的주소将是006B16진수=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。第一个레지스터的주소是000816진수=8,因为帐户是从0주소开始的。
| 바이트 | 请求 | 바이트 | 回复 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 11 | 设备주소 | 11 | 设备주소 |
| 04 | 功能代码 | 04 | 功能代码 |
| 00 | 第一个레지스터주소高바이트 | 02 | 更多的바이트数 |
| 08 | 第一个레지스터주소低바이트 | 00 | #30009的레지스터 값高位 |
| 00 | 레지스터 수량高바이트 | 0A | #30009的레지스터 값低位 |
| 01 | 레지스터 수량低바이트 | F8 | CRC-16(Modbus) |
| B2 | CRC-16(Modbus) | F4 | CRC-16(Modbus) |
| 98 | CRC-16(Modbus) |
如何보내기Modbus RTU命令来쓰기离散출력?命令0x05
此命令用于记录DO数字출력的一个值。
值FF 0016진수将출력设置为ON。
值00 0016진수将출력设置为OFF。
所有其他值都无效,且不会影响출력值。
对这样的请求的正常响应是回声(响应中的重复请求),在DO状态已更改后返回。
예제,使用设备的SlaveID주소17的레지스터# 173的DO记录。레지스터주소为00AC16진수=172,因为从0주소开始记录。
| 바이트 | 请求 | 바이트 | 回复 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 11 | 设备주소 | 11 | 设备주소 |
| 05 | 功能代码 | 05 | 功能代码 |
| 00 | 第一个레지스터주소高바이트 | 00 | 第一个레지스터주소高바이트 |
| AC | 第一个레지스터주소低바이트 | AC | 第一个레지스터주소低바이트 |
| FF | 高바이트值 | FF | 高바이트值 |
| 00 | 低바이트值 | 00 | 低바이트值 |
| 4E | CRC-16(Modbus) | 4E | CRC-16(Modbus) |
| 8B | CRC-16(Modbus) | 8B | CRC-16(Modbus) |
| DO173출력 상태已从OFF更改为ON。 |
如何보내기Modbus RTU命令来记录模拟출력?命令0x06
此命令用于记录模拟출력AO的一个值。
예제,使用设备的SlaveID주소17的레지스터# 40002的AO记录。第一个레지스터的주소为000116진수=1,因为从0주소开始记录。
| 바이트 | 请求 | 바이트 | 回复 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 11 | 设备주소 | 11 | 设备주소 |
| 06 | 功能代码 | 06 | 功能代码 |
| 00 | 第一个레지스터주소高바이트 | 00 | 第一个레지스터주소高바이트 |
| 01 | 第一个레지스터주소低바이트 | 01 | 第一个레지스터주소低바이트 |
| 00 | 高바이트值 | 00 | 高바이트值 |
| 03 | 低바이트值 | 03 | 低바이트值 |
| 9A | CRC-16(Modbus) | 9A | CRC-16(Modbus) |
| 9B | CRC-16(Modbus) | 9B | CRC-16(Modbus) |
如何보내기Modbus RTU命令来쓰기多个离散引脚?命令0x0F
此命令用于记录DO数字출력的多个值。
예제,쓰기多个DO,从设备的SlaveID주소17的레지스터# 20到# 29。레지스터주소为001316진수=19,因为从0주소开始记录。
| 바이트 | 请求 | 바이트 | 回复 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 11 | 设备주소 | 11 | 设备주소 |
| 0F | 功能代码 | 0F | 功能代码 |
| 00 | 第一个레지스터주소高바이트 | 00 | 第一个레지스터주소高바이트 |
| 13 | 第一个레지스터주소低바이트 | 13 | 第一个레지스터주소低바이트 |
| 00 | 레지스터 수량高바이트 | 00 | 记录的레지스터 수량高바이트 |
| 0A | 레지스터 수량低바이트 | 0A | 记录的레지스터 수량低바이트 |
| 02 | 更多的바이트数 | 26 | CRC-16(Modbus) |
| CD | DO 27-20的바이트值 (1100 1101) | 99 | CRC-16(Modbus) |
| 01 | DO 29-28的바이트值 (0000 0001) | ||
| BF | CRC-16(Modbus) | ||
| 0B | CRC-16(Modbus) |
答案返回已记录的레지스터 수량。
如何보내기Modbus RTU命令来记录多个模拟출력?命令0x10
此命令用于记录模拟출력AO的多个值。
예제,记录多个AO,从设备的SlaveID주소17的레지스터# 40002和# 40003。第一个레지스터的주소为000116진수=1,因为从0주소开始记录。
| 바이트 | 请求 | 바이트 | 回复 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 11 | 设备주소 | 11 | 设备주소 |
| 10 | 功能代码 | 10 | 功能代码 |
| 00 | 第一个레지스터주소高바이트 | 00 | 第一个레지스터주소高바이트 |
| 01 | 第一个레지스터주소低바이트 | 01 | 第一个레지스터주소低바이트 |
| 00 | 레지스터 수량高바이트 | 00 | 记录的레지스터 수량高바이트 |
| 02 | 레지스터 수량低바이트 | 02 | 记录的레지스터 수량低바이트 |
| 04 | 更多的바이트数 | 12 | CRC-16(Modbus) |
| 00 | 40002高位值 | 98 | CRC-16(Modbus) |
| 0A | 40002低位值 | ||
| 01 | 40003高位值 | ||
| 02 | 40003低位值 | ||
| C6 | CRC-16(Modbus) | ||
| F0 | CRC-16(Modbus) |

Modbus请求的错误
如果设备수신到一个请求,但无法处理该请求,该设备将以错误代码进行响应。
响应将包含修改后的功能代码,高位바이트为1。
예제:
| 原始值 | 结果值 |
|---|---|
| 요청 내功能代码 | 响应中的功能错误代码 |
| 01 (01 hex) 0000 0001 | 129 (81 hex) 1000 0001 |
| 02 (02 hex) 0000 0010 | 130 (82 hex) 1000 0010 |
| 03 (03 hex) 0000 0011 | 131 (83 hex) 1000 0011 |
| 04 (04 hex) 0000 0100 | 132 (84 hex) 1000 0100 |
| 05 (05 hex) 0000 0101 | 133 (85 hex) 1000 0101 |
| 06 (06 hex) 0000 0110 | 134 (86 hex) 1000 0110 |
| 15 (0F hex) 0000 1111 | 143 (8F hex) 1000 1111 |
| 16 (10 hex) 0001 0000 | 144 (90 hex) 1001 0000 |
带有错误的请求和响应예제:
| 바이트 | 请求 | 바이트 | 响应 |
|---|---|---|---|
| (Hex) | 필드名 | (Hex) | 필드名 |
| 0A | 设备주소 | 0A | 设备주소 |
| 01 | 功能代码 | 81 | 已更改的功能代码 |
| 04 | 第一个레지스터주소高바이트 | 02 | 错误代码 |
| A1 | 第一个레지스터주소低바이트 | B0 | CRC-16(Modbus) |
| 00 | 레지스터 수량高바이트 | 53 | CRC-16(Modbus) |
| 01 | 레지스터 수량低바이트 | ||
| AC | CRC-16(Modbus) | ||
| 63 | CRC-16(Modbus) |
错误代码설명
01 | 不能处理已接受的功能代码。
02 | 请求中指定的데이터주소不可用。
03 | 查询데이터필드中包含的值是无效值。
04 | 슬레이브尝试执行请求的操作时发生不可恢复的错误。
05 | 슬레이브已接受请求并正在处理,但需要较长时间。此响应防止主机生成超时错误。
06 | 슬레이브正忙于处理命令。主机在슬레이브空闲时必须重复消息。
07 | 슬레이브无法执行请求中指定的程序功能。使用功能번호13或14的不成功的程序请求返回此代码。主机必须从슬레이브请求诊断信息或错误信息。
08 | 슬레이브在읽기扩展内存时检测到奇짝수 패리티错误。主机可以重复请求,但通常在这种情况下需要维修。
답글 작성