Modbus寄存器分为四种,如表1.1所示:
表1.1 寄存器分类
寄存器种类 | 数据类型 | 访问类型 | 功能码 | PLC地址 | 寄存器地址 |
---|---|---|---|---|---|
线圈寄存器 | 位 | 读写 | 01H 05H 0FH | 00001-09999 | 0000H-FFFFH |
离散输入寄存器 | 位 | 只读 | 02H | 10001-19999 | 0000H-FFFFH |
输入寄存器 | 字 | 只读 | 04H | 30001-39999 | 0000H-FFFFH |
保持寄存器 | 字 | 读写 | 03H 06H 10H | 40001-49999 | 0000H-FFFFH |
Modbus中常用的功能码有8个,可以分为位操作和字操作两类,如表2.1所示:
表2.1 常用功能码
功能码 | 描述 | PLC地址 | 寄存器地址 | 位/字操作 | 操作数量 |
---|---|---|---|---|---|
01H | 读线圈寄存器 | 00001-09999 | 0000H-FFFFH | 位操作 | 单个或多个 |
02H | 读离散输入寄存器 | 10001-19999 | 0000H-FFFFH | 位操作 | 单个或多个 |
03H | 读保持寄存器 | 40001-49999 | 0000H-FFFFH | 字操作 | 单个或多个 |
04H | 读输入寄存器 | 30001-39999 | 0000H-FFFFH | 字操作 | 单个或多个 |
05H | 写单个线圈寄存器 | 00001-09999 | 0000H-FFFFH | 位操作 | 单个 |
06H | 写单个保持寄存器 | 40001-49999 | 0000H-FFFFH | 字操作 | 单个 |
0FH | 写多个线圈寄存器 | 00001-09999 | 0000H-FFFFH | 位操作 | 多个 |
10H | 写多个保持寄存器 | 40001-49999 | 0000H-FFFFH | 字操作 | 多个 |
功能码01H读取Modbus从机中线圈寄存器的状态,可以是单个寄存器,或者多个连续的寄存器。
假设从机地址为01H,读取的线圈寄存器的起始地址为0017H,读取38个寄存器,指令如表3.1所示:
表3.1 读线圈寄存器指令:
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 寄存器数量高位 | 寄存器数量低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 01 | 00 | 17 | 00 | 26 | 0D | D4 |
各线圈的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在最后一个字节的高位补0。
表3.2.1 读线圈状态的返回结果
从机地址 | 功能码 | 返回字节数 | 数据1 | 数据2 | 数据3 | 数据4 | 数据5 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|---|---|
01 | 01 | 05 | CD | 6B | B2 | 0E | 1B | 44 | EA |
其中,第一个字节CDH对应线圈0017H到001E的状态,转为二进制是11001101,其中bit0对应0017H,bit7对应001E,如表3.2.2所示:
表3.2.2 线圈0017H到001EH的状态
001EH | 001DH | 001CH | 001BH | 001AH | 0019H | 0018H | 0017H |
---|---|---|---|---|---|---|---|
1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
ON | ON | OFF | OFF | ON | ON | OFF | ON |
最后一个字节为1BH,对应线圈0037H到003CH的状态,转为二进制是00011011,其中bit0对应0037H,bit5对应003CH,其余两位用0填充,如表3.2.3所示:
表3.2.3 线圈0037H到003CH的状态
003CH | 003BH | 003AH | 0039H | 0038H | 0037H | 0036H | 0035H |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
填充 | 填充 | OFF | ON | ON | OFF | ON | ON |
功能码02H读取Modbus从机中离散输入寄存器的状态,可以是单个寄存器,或者多个连续的寄存器。
假设从机地址为01H,读取的离散输入寄存器的起始地址为00C4H,读取22个寄存器,指令如表4.1所示:
表4.1 读离散输入寄存器指令:
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 寄存器数量高位 | 寄存器数量低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 02 | 00 | C4 | 00 | 16 | B8 | 39 |
各个离散输入寄存器的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在最后一个字节的高位补0。
表4.2.1 读离散输入寄存器的返回结果
从机地址 | 功能码 | 返回字节数 | 数据1 | 数据2 | 数据3 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 02 | 03 | AC | DB | 35 | 22 | 88 |
其中,第一个字节ACH对应00C4H到00CBH寄存器的状态,转为二进制是10101100,其中bit0对应00C4H,bit7对应00CB,如表4.2.2所示:
表4.2.2 寄存器00C4H到00CBH的状态
00CBH | 00CAH | 00C9H | 00C8H | 00C7H | 00C6H | 00C5H | 00C4H |
---|---|---|---|---|---|---|---|
1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 |
ON | OFF | ON | OFF | ON | ON | OFF | OFF |
最后一个字节为35H,对应寄存器00D4H到00D9H的状态,转为二进制是00110101,其中bit0对应00D4H,bit5对应00D9H,其余两位用0填充,如表4.2.3所示:
表4.2.3 寄存器00D4H到00D9H的状态
00DBH | 00DAH | 00D9H | 00D8H | 00D7H | 00D6H | 00D5H | 00D4H |
---|---|---|---|---|---|---|---|
0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 |
填充 | 填充 | ON | ON | OFF | ON | OFF | ON |
功能码03H读取Modbus从机中保持寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
假设从机地址为01H,读取的保持寄存器的起始地址为006BH,读取3个寄存器,指令如表5.1所示:
表5.1 读保持寄存器指令:
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 寄存器数量高位 | 寄存器数量低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 03 | 00 | 6B | 00 | 03 | 74 | 17 |
每个保持寄存器的长度为2个字节。保持寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个保持寄存器,高字节数据先传输,低字节数据后传输。
表5.2.1 读保持寄存器的返回结果
从机地址 | 功能码 | 字节数 | 006BH高字节 | 006BH低字节 | 006CH高字节 | 006CH低字节 | 006DH高字节 | 006DH低字节 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|---|---|---|
01 | 03 | 06 | 00 | 6B | 00 | 13 | 00 | 00 | F5 | 79 |
功能码04H读取Modbus从机中输入寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
假设从机地址为01H,读取的保持寄存器的起始地址为0008H,读取2个寄存器,指令如表6.1所示:
表6.1 读输入寄存器指令:
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 寄存器数量高位 | 寄存器数量低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 04 | 00 | 6B | 00 | 02 | 00 | 17 |
每个输入寄存器的长度为2个字节。输入寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个输入寄存器,高字节数据先传输,低字节数据后传输。
表6.2.1 读输入寄存器的返回结果
从机地址 | 功能码 | 字节数 | 0008H高字节 | 0008H低字节 | 0009H高字节 | 0009H低字节 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|---|
01 | 04 | 04 | 00 | 0A | 00 | 0B | 9A | 41 |
功能码05H写单个线圈寄存器,FF00H请求线圈处于ON状态,0000H请求线圈处于OFF状态。
假设从机地址为01H,线圈寄存器的地址为00ACH,使其处于ON状态的指令如表7.1所示:
表7.1 写单个线圈指令:
从机地址 | 功能码 | 寄存器地址高位 | 寄存器地址低位 | 数据高位 | 数据低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 05 | 00 | AC | FF | 00 | 4C | 1B |
如果写入成功,返回发送的指令,即010500ACFF004C1B。
功能码06H写单个保持寄存器。
假设从机地址为01H,保持寄存器的地址为0001H,数据位0003H,指令如表8.1所示:
表8.1 写单个保持寄存器指令:
从机地址 | 功能码 | 寄存器地址高位 | 寄存器地址低位 | 数据高位 | 数据低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 06 | 00 | 01 | 00 | 03 | 98 | 0B |
如果写入成功,返回发送的指令,即010600010003980B。
功能码0FH写多个线圈寄存器。如果对应的数据位为1,表示线圈状态为ON;如果对应的数据位为0,表示线圈状态为OFF。线圈寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个线圈寄存器,高字节数据先传输,低字节数据后传输。如果写入的线圈寄存器的个数不是8的倍数,则在最后一个字节的高位补0。
假设从机地址为01H,线圈寄存器的起始地址为0013H,写入10个寄存器,指令如表9.1.1所示:
表9.1.1 写入多个线圈寄存器指令
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 数量高位 | 数量低位 | 字节数 | 数据1 | 数据2 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|---|---|---|
01 | 0F | 00 | 13 | 00 | 0A | 02 | CD | 01 | 72 | CB |
其中,CDH对应线圈0013H到001AH的内容,01H对应线圈001B到001CH的内容,未使用位用0填充。
此时,线圈寄存器的内容如表9.1.2所示:
表9.1.2 线圈寄存器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 |
如果写入成功,返回写入的寄存器数量,如表9.2所示:
表9.2 写多个线圈寄存器的返回结果
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 数量高位 | 数量低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 0F | 00 | 13 | 00 | 0A | 24 | 09 |
功能码10H写多个保持寄存器,其中每个保持寄存器的长度为两个字节。
假设从机地址为01H,保持寄存器的起始地址为0001H,写入2个寄存器,指令如表10.1所示:
表10.1 写入多个保持寄存器指令
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 数量高位 | 数量低位 | 字节数 | 0001H高位 | 0001H低位 | 0002H高位 | 0002H低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
01 | 10 | 00 | 01 | 00 | 02 | 04 | 00 | 0A | 01 | 02 | 92 | 30 |
如果写入成功,返回写入的寄存器数量,如表10.2所示:
表10.2 写多个保持寄存器的返回结果
从机地址 | 功能码 | 起始地址高位 | 起始地址低位 | 数量高位 | 数量低位 | CRC高位 | CRC低位 |
---|---|---|---|---|---|---|---|
01 | 10 | 00 | 01 | 00 | 02 | 10 | 08 |