Modbus TCP 协议
1 ModbusTCP数据帧
ModbusTCP的数据帧可分为两部分:MBAP+PDU。
1.1 报文头MBAP
MBAP为报文头,长度为7字节,组成如下:
事务处理标识 协议标识 长度 单元标识符
2字节 2字节 2字节 1字节
事务处理标识 :可以理解为报文的序列号,一般每次通信之后就要加1以区别不同的通信数据报文。
协议标识符 :00 00表示ModbusTCP协议。
长度 :表示接下来的数据长度,单位为字节。
单元标识符 :可以理解为设备地址。
1.2 帧结构PDU
PDU由功能码+数据组成。功能码为1字节,数据长度不定,由具体功能决定。
1.2.1 功能码
modbus的操作对象有四种:线圈、离散输入、输入寄存器、保持寄存器。
线圈:PLC的输出位,开关量,在MODBUS中可读可写
离散量:PLC的输入位,开关量,在MODBUS中只读
输入寄存器:PLC中只能从模拟量输入端改变的寄存器,在MODBUS中只读
保持寄存器:PLC中用于输出模拟量信号的寄存器,在MODBUS中可读可写
根据对象的不同,modbus的功能码有:
1.2.2PDU详细结构
0x01:读线圈
在从站中读1~2000个连续线圈状态,ON=1,OFF=0
请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
响应:MBAP 功能码 数据长度 数据(一个地址的数据为1位)
如:在从站0x01中,读取开始地址为0x0002的线圈数据,读0x0008位
00 01 00 00 00 06 01 01 00 02 00 08
回:数据长度为0x01个字节,数据为0x01,第一个线圈为ON,其余为OFF
00 01 00 00 00 04 01 01 01 01
0x05:写单个线圈
将从站中的一个输出写成ON或OFF,0xFF00请求输出为ON,0x000请求输出为OFF
请求:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
响应:MBAP 功能码 输出地址H 输出地址L 输出值H 输出值L(共12字节)
如:将地址为0x0003的线圈设为ON
00 01 00 00 00 06 01 05 00 03 FF 00
回:写入成功
00 01 00 00 00 06 01 05 00 03 FF 00
0x0F:写多个线圈
将一个从站中的一个线圈序列的每个线圈都强制为ON或OFF,数据域中置1的位请求相应输出位ON,置0的位请求响应输出为OFF
请求:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L 字节长度 输出值H 输出值L
响应:MBAP 功能码 起始地址H 起始地址L 输出数量H 输出数量L
Tx:11 CC 00 00 00 09 01 0F 00 00 00 0A 02 0F 00 数据长度000A(10)个,地址为0000,数据为 00 0000 1111
Rx:11 CC 00 00 00 06 01 0F 00 00 00 0A
0x02:读离散量输入
从一个从站中读1~2000个连续的离散量输入状态
请求:MBAP 功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
响应:MBAP 功能码 数据长度 数据(长度:9+ceil(数量/8))
如:从地址0x0000开始读10个离散量输入
Tx:12 A3 00 00 00 06 01 02 00 00 00 0A
Rx:12 A3 00 00 00 05 01 02 02 00 00
0x04:读输入寄存器
从一个远程设备中读1~2000个连续输入寄存器
请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
如:读起始地址为0x0000,数量为10个寄存器数据
Tx:15 C4 00 00 00 06 01 04 00 00 00 0A
Rx:15 C4 00 00 00 17 01 04 14 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x03:读保持寄存器
从远程设备中读保持寄存器连续块的内容
请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
响应:MBAP 功能码 数据长度 寄存器数据(长度:9+寄存器数量×2)
如:TX:读起始地址为0x0000,数量为10(0x000A)个寄存器数据
RX:回地址为0x0000,字节长度为0x14,数据为12 0 33 26562 33 0 55 78 0 56
Tx:19 D8 00 00 00 06 01 03 00 00 00 0A
Rx:19 D8 00 00 00 17 01 03 14 00 0C 00 00 00 21 67 C2 00 21 00 00 00 37 00 4E 00 00 00 38
0x10:写多个保持寄存器
在一个远程设备中写连续寄存器块(1~123个寄存器)
请求:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L 字节长度 寄存器值(13+寄存器数量×2)
响应:MBAP 功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12字节)
如:读起始地址为0x0000,数量为10(0x000A)个寄存器数据 字节长度20(0x14)数据为 12 0 33 26562 33 0 55 78 0 56
Tx:17 52 00 00 00 1B 01 10 00 00 00 0A 14 00 0C 00 00 00 21 67 C2 00 21 00 00 00 37 00 4E 00 00 00 38
Rx:17 51 00 00 00 06 01 10 00 00 00 0A
0x06:写单个保持寄存器
在一个远程设备中写一个保持寄存器
请求:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
响应:MBAP 功能码 寄存器地址H 寄存器地址L 寄存器值H 寄存器值L(共12字节)
如:向地址是0x0000的寄存器写入数据0x0017(23)
Tx:1A B9 00 00 00 06 01 06 00 00 00 17
Rx:1A B9 00 00 00 06 01 06 00 00 00 17