目录
1. 简介
Modbus 是一种串 行通信协议,是Modicon 于 1979年,为使用可编程逻辑控制器(PLC)而发表的。Modbus是工业领域通信协议的业界标准,并且现在是工业电子设备之间相当常用的连接方式。Modbus 比其他通信协议使用的更广泛的主要原因有:
(1)公开发表并且无版税要求;
(2)相对容易的工业网络部署;
(3)对供应商来说,修改移动原生的位元或字节限制较少。
Modbus网络示意图:
2. Modbus RTU功能码简述
功能码 | 功能 | 寄存器PLC地址 | 位操作/字操作 | 操作数量 |
01H | 读线圈状态 | 00001-09999 | 位操作(1字节) | 单个或多个 |
02H | 读离散输入状态 | 10001-19999 | 位操作(1字节) | 单个或多个 |
03H | 读保持寄存器 | 40001-49999 | 字操作(2字节) | 单个或多个 |
04H | 读输入寄存器 | 30001-39999 | 字操作(2字节) | 单个或多个 |
05H | 写单个线圈 | 00001-09999 | 位操作(1字节) | 单个 |
06H | 写单个保持寄存器 | 40001-49999 | 字操作(2字节) | 单个 |
0FH | 写多个线圈 | 00001-09999 | 位操作(1字节) | 多个 |
10H | 写多个保持寄存器 | 40001-49999 | 字操作(2字节) | 多个 |
2.1 功能码说明
功能码可以分为位操作和字操作两类。位操作的最小单位为BIT,字操作的最小单位为两个字节。
(1)位操作指令
读线圈状态 01H,读(离散)输入状态 02H,写单个线圈 05H 和写多个线圈OFH.
(2)字操作指令
读保持寄存器 03H,写单个寄存器 06H,写多个保持寄存器 10H。
2.2 寄存器地址分配
寄存器PLC地址 | 寄存器协议地址 | 功能码 | 位操作/字操作 | 操作数量 |
00001-09999 | 0000H-FFFFH | 01H、05H、0FH | 线圈状态 | 可读可写 |
10001-19999 | 0000H-FFFFH | 02H | 离散输入状态 | 可读 |
30001-39999 | 0000H-FFFFH | 04H | 输入寄存器 | 可读 |
40001-49999 | 0000H-FFFFH | 03H、06H、10H | 保持寄存器 | 可读可写 |
2.4 寄存器种类说明
寄存器种类 | 说明 | PLC 类比 | 举例说明 |
线圈状态 | 输出端口。可设定端口的输出状态,也可以读取该位的输出状态 | DO 数字量输出 | 继电器输出,MOSFET(晶体管)输出等 |
离散输入状态 | 输入端口。通过外部设定改变输入状态,可读但不可写 | DI 数字量输入 | 按钮开关,光电开关等 |
保持寄存器 | 输出参数或保持参数。控制器运行时被设定的某些参数。可读可写 | AO 模拟量输出 | 模拟量输出设定值,PID 运行参数,变量阀输出大小,传感器报警上限下限 |
输入寄存器 | 输入参数。控制器运行时从外部设备获得的参数。可读但不可写 | AI 模拟量输入 | 模拟量输入 |
2.5 PLC地址和协议地址区别
PLC地址可以理解为协议地址的变种,在触摸屏的PLC编程中应用较为广泛。
2.5.1 寄存器 PLC 地址
寄存器PLC地址指存放于控制器中的地址,这些控制器可以是PLC,也可以是触摸屏,或是文本显示器。PLC地址一般采用10进制描述,共有5位,其中第一位代码寄存器类型。第一位数字和寄存器类型的对应关系如表1 所示。PLC地址例如 40001、30002等。
2.5.2 寄存器协议地址
寄存器协议地址指指通信时使用的寄存器地址,例如PLC地址40001对应寻址地址0000H, 40002对应寻址地址 0001H,寄存器寻址地址一般使用 16进制描述。再如,PLC寄存器地址 40003 对应协议地址 0002,PLC 寄存器地址 30003 对应协议地址 0002,虽然两个PLC 寄存器寄存器通信时使用相同的地址,但是需要使用不同的命令访问,所以访问时不存在冲突。
3. Modbus RTU指令说明
3.1 读线圈寄存器01H
3.1.1 描述
读线圈寄存器当前状态。
3.1.2 查询
假设一个例子:
例如从机地址位01H,线圈寄存器的起始地址位0013H,结束地址位0037H,该次查询总共访问37个线圈寄存器。
线圈寄存器01H-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 01 |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 13 |
5 | 寄存器数量高字节 | 00 |
6 | 寄存器数量低字节 | 25 |
7 | CRC校验低字节 | 0C |
8 | CRC校验高字节 | 14 |
3.1.3 响应
响应负载中的各线圈状态与数据内容每位相对应,1代表ON,0代表OFF。若返回的线圈数部位8的倍数,则在最后数据字节末尾使用0代替。
读线圈寄存器01H-模块返回:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 01 |
3 | 返回字节数 | 05 |
4 | 数据1(线圈0013H-线圈001AH) | CD |
5 | 数据2(线圈001BH-线圈0022H) | 6B |
6 | 数据3(线圈0023H-线圈002AH) | B2 |
7 | 数据4(线圈0032H-线圈002BH) | 0E |
8 | 数据5(线圈0037H-线圈0033H) | 1B |
9 | CRC校验低字节 | 44 |
10 | CRC校验高字节 | EA |
线圈 0013H 到线圈 001AH的状态为CDH,二进制值为 11001101,该字节的最高位为线圈 001AH,最低位 为线圈 0013H。线 圈 001AH 到线 圈 0013H 的状态 分 别 为ON-ON-OFF-OFF-ON-ON-OFF-ON。
线圈0013H到001AH状态:
001AH | 0019H | 0018H | 0017H | 0016H | 0015H | 0014H | 0013H |
1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
最后一个数据字节中,线圈0033H到线圈0037的状态为1BH (二进制00011011),线圈0037H是左数第4位,线圈0033H为该字节的最低位,线圈0037H至线圈0033H的状态分别为 ON-ON-OFF-ON-ON,剩余 3 位使用 0 填充。
线圈0033H到0037H状态:
003AH | 0039H | 0038H | 0037H | 0036H | 0035H | 0034H | 0033H |
0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
3.2 读离散输入寄存器02H
3.2.1 说明
读离散输入寄存器状态。
3.2.2 查询
假设一个例子:
从机地址为01H,离散输入寄存器的起始地址为00C4H,结束寄存器地址为00D9H。
总共访问22个离散输入寄存器。
读离散输入寄存器02H-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 02 |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | C4 |
5 | 寄存器数量高字节 | 00 |
6 | 寄存器数量低字节 | 16 |
7 | CRC校验低字节 | B8 |
8 | CRC校验高字节 | 39 |
3.2.3 响应
响应各离散输入寄存器状态,分别对应数据区中的每位值, 1代表ON: 0代表OFF。器第一个数据字节的LSB (最低位)为查询的寻址地址寄存器值,其他输入口按顺序在该字节中由低位向高位节排列,直到填充满8位。下一个字节中的8个输入位也是从低字节到高字节排列。若返回的输入位数不是8的倍数,则在最后的数据字节中的剩余位至该字节的最高位使用 0填充。
读离散输入寄存器02H-模块返回:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 02 |
3 | 返回字节数 | 03 |
4 | 数据1(00C4H-00CBH) | AC |
5 | 数据2(00CCH-00D3H) | DB |
6 | 数据3(00D4H-00D9H) | 35 |
7 | CRC校验低字节 | 22 |
8 | CRC校验高字节 | 88 |
离散输入寄存器 00D4H 到0OD9H 的状态为35H(二进制00110101)。输入寄存器 00D9H为左数第3位,输入寄存器00D4为最低位,输入寄存器00D9H到00D4H的状态分别为ON-ON-OFF-ON-OFF-ON。00DBH寄存器和00DAH寄存器被0填充。
离散输入寄存器00C4H到00DBH状态:
00CBH | 00CAH | 00C9H | 00C8H | 00C7H | 00C6H | 00C5H | 00C4H |
0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 |
00D3H | 00D2H | 00D1H | 00D0H | 00CFH | 00CEH | 00CDH | 00CCH |
1 | 1 | 1 | 0 | 1 | 0 | 1 | 1 |
00DBH | 00DAH | 00D9H | 00D8H | 00D7H | 00D6H | 00D5H | 00D4H |
0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 |
3.3 读保持寄存器03H
3.3.1 说明
读保持寄存器。可读取单个或者多个保持寄存器。
3.3.2 查询
假设一个例子:
从机地址为01H,保持寄存器的起始地址为006BH,结束寄存器地址为006DH。
总共访问3个保持寄存器。
读保持寄存器03-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 03 |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 6B |
5 | 寄存器数量高字节 | 00 |
6 | 寄存器数量低字节 | 03 |
7 | CRC校验低字节 | 74 |
8 | CRC校验高字节 | 17 |
3.3.3 响应
保持寄存器的长度为2个字节。对于单个保持寄存器而言,寄存器高字节数据先被传输,低字节数据后被传输。保持寄存器之间,低地址寄存器先被传输,高地址寄存器后被传输。
读保持寄存器03H-模块返回:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 03 |
3 | 返回字节数 | 06 |
4 | 数据1高字节(006BH) | 00 |
5 | 数据1低字节(006BH) | 6B |
6 | 数据2高字节(006CH) | 00 |
7 | 数据2低字节(006CH) | 13 |
8 | 数据3高字节(006DH) | 00 |
9 | 数据3低字节(006DH) | 00 |
10 | CRC校验低字节 | F5 |
11 | CRC校验高字节 | 79 |
保持寄存器006BH到006DH结果:
006BH高字节 | 006BH低字节 | 006CH高字节 | 006CH低字节 | 006DH高字节 | 006DH低字节 |
00 | 6B | 00 | 13 | 00 | 00 |
3.4 读输入寄存器04H
3.4.1 说明
读输入寄存器命令。该命令支持单个寄存器访问也支持多个寄存器访问。
3.4.2 查询
从机地址为01H。输入寄存器的起始地址为0008H,寄存器的结束地址为0009H。本次访问2个输入寄存器。
读输入寄存器04H-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 04 |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 08 |
5 | 寄存器数量高字节 | 00 |
6 | 寄存器数量低字节 | 02 |
7 | CRC校验低字节 | F0 |
8 | CRC校验高字节 | 09 |
3.4.3 响应
输入寄存器长度为2个字节。对于单个输入寄存器而言,寄存器高字节数据先被传输,低字节数据后被传输。输入寄存器之间,低地址寄存器先被传输,高地址寄存器后被传输。
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 04 |
3 | 返回字节数 | 04 |
4 | 数据1高字节(006BH) | 00 |
5 | 数据1低字节(006BH) | 0A |
6 | 数据2高字节(006CH) | 00 |
7 | 数据2低字节(006CH) | 0B |
8 | CRC校验低字节 | 9A |
9 | CRC校验高字节 | 41 |
输入寄存器0008H到0009H的结果:
006BH高字节 | 006BH低字节 | 006CH高字节 | 006CH低字节 |
00 | 0A | 00 | 0B |
3.5 写单个线圈寄存器05H
3.5.1 说明
写单个线圈寄存器。FFOOH 值请求线圈处于 ON 状态,0000H 值请求线圈处于 OFF 状态。05H指令设置单个线圈的状态, 15H指令可以设置多个线圈的状态,两个指令虽然都设定线圈的 ON/OFF 状态,但是 ON/OFF 的表达方式却不同。
3.5.2 请求
从机地址为01H,线圈寄存器的地址为00ACH。使00ACH线圈处于ON状态,即数据内容为FFOOH。
写单个线圈寄存器05H-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 05 |
3 | 寄存器地址高字节 | 00 |
4 | 寄存器地址低字节 | AC |
5 | 数据 1 高字节 | FF |
6 | 数据 1 低字节 | 00 |
7 | CRC校验低字节 | 4C |
8 | CRC校验高字节 | 1B |
3.5.3 响应
写单个线圈响应:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 05 |
3 | 寄存器地址高字节 | 00 |
4 | 寄存器地址低字节 | AC |
5 | 数据 1 高字节 | FF |
6 | 数据 1 低字节 | 00 |
7 | CRC校验低字节 | 4C |
8 | CRC校验高字节 | 1B |
3.6 写单个保持寄存器06H
3.6.1 说明
写保持寄存器。注意06H指令只能操作单个保持寄存器, 10H指令可以设置单个或多个保持寄存器。
3.6.2 请求
从机地址为01H.保持寄存器地址为0000H.寄存器内容为0001H。
写单个保持寄存器 06H-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 06 |
3 | 寄存器地址高字节 | 00 |
4 | 寄存器地址低字节 | 00 |
5 | 数据高字节 | 00 |
6 | 数据低字节 | 01 |
7 | CRC校验低字节 | 48 |
8 | CRC校验高字节 | 0A |
3.6.2 响应
写单个保持寄存器06H-模块返回:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 06 |
3 | 寄存器地址高字节 | 00 |
4 | 寄存器地址低字节 | 00 |
5 | 寄存器数据高字节 | 00 |
6 | 寄存器数据低字节 | 01 |
7 | CRC校验低字节 | 48 |
8 | CRC校验高字节 | 0A |
3.7 写多个线圈寄存器0FH
3.7.1 说明
写多个线圈寄存器。若数据区的某位值为“1”表示被请求的相应线圈状态为 ON,若某位值为“0”,则为状态为0FF。
3.7.2 请求
从机地址为 01H,线圈寄存器的起始地址为 0013H,线圈寄存器的结束地址为 001CH。总共访问 10 个寄存器。寄存器内容如下表所示。
线圈寄存器 0013H 到 001CH:
001AH | 0019H | 0018H | 0017H | 0016H | 0015H | 0014H | 0013H |
1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
0022H | 0021H | 0020H | 001FH | 001EH | 001DH | 001CH | 001BH |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
传输的第一个字节CDH对应线圈为0013H到001AH,LSB(最低位)对应线圈0013H,传输第二个字节为01H,对应的线圈为001BH到001CH,LSB (最低位)对应线圈001BH,其余未使用位使用0填充。
写多个线圈寄存器0FH-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 0F |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 13 |
5 | 寄存器数据高字节 | 00 |
6 | 寄存器数据低字节 | 0A |
7 | 字节数 | 02 |
8 | 数据1(0013H-001AH) | CD |
9 | 数据1(001BH-001CH) | 01 |
10 | CRC校验低字节 | 72 |
11 | CRC校验高字节 | CB |
3.7.3 响应
写多个线圈寄存器0FH-模块返回:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 0F |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 13 |
5 | 寄存器数据高字节 | 00 |
6 | 寄存器数据低字节 | 0A |
7 | CRC校验低字节 | 24 |
8 | CRC校验高字节 | 09 |
3.8 写多个保持寄存10H
3.8.1 说明
写多个保持寄存器。
3.8.2 请求
从机地址为 01H。保持 寄存器的起始地址为 0001H,寄存器的结束地址为 0002H.总共访问2个寄存器。保持寄存器0001H的内容为000AH,保持寄存器0002H的内容为0102H.
写多个保持寄存器 10H-主机发送:
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 10 |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 01 |
5 | 寄存器数据高字节 | 00 |
6 | 寄存器数据低字节 | 02 |
7 | 字节数 | 04 |
8 | 数据 1 高字节 | 00 |
9 | 数据 1 低字节 | 0A |
10 | 数据 2 高字节 | 01 |
11 | 数据 2 低字节 | 02 |
12 | CRC校验低字节 | 92 |
13 | CRC校验高字节 | 30 |
保持寄存器0001H到0002H的内容:
0001H | 0001H | 0002H | 0002H |
高字节 | 低字节 | 高字节 | 低字节 |
00 | 0A | 01 | 12 |
3.8.3 响应
字节序号 | 功能 | 16进制数据 |
1 | 从机地址 | 01 |
2 | 功能码 | 10 |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 01 |
5 | 寄存器数据高字节 | 00 |
6 | 寄存器数据低字节 | 02 |
7 | CRC校验低字节 | 10 |
8 | CRC校验高字节 | 08 |