Modbus由MODICON公司于1979年开发,是一种工业现场总线协议标准。1996年施耐德公司推出基于以太网TCP/IP的Modbus协议:* ModbusTCP*。
Modbus协议是一项应用层报文传输协议,包括ASCII、RTU、TCP三种报文类型。
标准的Modbus协议物理层接口有RS232、RS422、RS485和以太网接口,采用master/slave方式通信。
Modbus TCP的数据帧可分为两部分: MBAP+PDU
MBAP为报文头,长度为7字节,组成如下:
事务处理标识 | 协议标识 | 长度 | 单元标识符 |
---|---|---|---|
2字节 | 2字节 | 2字节 | 1字节 |
内容 | 解释 |
---|---|
事务处理标识 | 可以理解为报文的序列号,一般每次通信之后就要加1以区分不同的通信数据报文。 |
协议标识符 | 0x00 0x00标识Modbus TCP协议 |
长度 | 表示接下来的数据长度,单位为字节。 |
单元标识符 | 可以理解为设备地址。 |
PDU由 功能码 +数据组成。功能码为1字节,数据长度不定,由具体功能决定。
Modbus的操作对象有四种:线圈、离散输入、保持寄存器、输入寄存器。
对象 | 含义 |
---|---|
线圈 | PLC的输出位,开关量,在Modbus中可读可写 |
离散量 | PLC的输入位,开关量,在Modbus中只读 |
输入寄存器 | PLC中只能从模拟量输入端改变的寄存器,在Modbus中只读 |
保持寄存器 | PLC中用于输出模拟量信号的寄存器,在Modbus中可读可写 |
根据对象的不同,Modbus的功能码有:
代码 | 含义 | 位操作/字操作 | 操作数量 |
---|---|---|---|
0x01 | 读线圈状态 | 位操作 | 单个或多个 |
0x02 | 读离散输入状态 | 位操作 | 单个或多个 |
0x03 | 读保持寄存器 | 字操作 | 单个或多个 |
0x04 | 读输入寄存器 | 字操作 | 单个或多个 |
0x05 | 写线圈状态 | 位操作 | 单个 |
0x06 | 写单个保持寄存器 | 字操作 | 单个 |
0x0F | 写多个线圈 | 位操作 | 多个 |
0x10 | 写多个保持寄存器 | 字操作 | 多个 |
在从站中读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
将从站中的一个输出写成ON或OFF,0xFF00为ON,0x0000为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
从一个从站中读1~2000个连续的离散量输入状态
- 请求:MBAP功能码 起始地址H 起始地址L 数量H 数量L(共12字节)
- 响应:MBAP功能码 数据长度 数据(长度:9+ceil(数量/8))
- 发:从地址0x0000开始读0x0012个离散量输入
00 01 00 00 00 06 01 02 00 00 00 12 - 回:数据长度为0x03个字节,数据为0x01 04 00,表示第一个离散量输入和第11个离散量输入为ON,其余为OFF
00 01 00 00 00 06 01 02 03 01 04 00
从一个远程设备中读1~2000个连续输入寄存器
- 请求:MBAP功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12个字节)
- 响应:MBAP功能码 数据长度 寄存器数据(长度:9+寄存器数量*2)
- 发:读起始地址为0x0002,数量为0x0005的寄存器数据
00 01 00 00 00 06 01 04 00 02 00 05 - 回:数据长度为0x0A,第一个寄存器数据为0x0c,其余为0x00
00 01 00 00 00 0D 01 04 0A 00 0C 00 00 00 00 00 00 00 00
从远程设备中读保持寄存器连续块的内容
- 请求:MBAP功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12个字节)
- 响应:MBAP功能码 数据长度 寄存器数据(长度:9+寄存器数量*2)
- 发:起始地址为0x0000,寄存器数量为0x0003
00 01 00 00 00 06 01 03 00 00 00 03 - 回:数据长度为0x06,第一个寄存器的数据为0x21,其余为0x00
00 01 00 00 00 09 01 03 06 00 21 00 00 00 00
在一个远程设备中写一个保持寄存器
- 请求:MBAP功能码 起始地址H 起始地址L 寄存器值H 寄存器值L(共12个字节)
- 响应:MBAP功能码 起始地址H 起始地址L 寄存器值H 寄存器值L(共12个字节)
- 发:向地址为0x0000的寄存器中写入数据0x000A
00 01 00 00 00 06 00 00 00 0A - 回:写入成功
00 01 00 00 00 06 00 00 00 0A
在一个远程设备中写连续寄存器块(1~123个寄存器)
- 请求:MBAP功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L 字节长度 寄存器值(长度:13+寄存器数量*2)
- 响应:MBAP功能码 起始地址H 起始地址L 寄存器数量H 寄存器数量L(共12个字节)
- 发:向起始地址为0x0000,数量为0x0001的寄存器写入数据,数据长度为0x02,数据为0x000F
00 01 00 00 00 09 01 10 00 00 00 01 02 00 0F - 回:写入成功
00 01 00 00 00 06 01 10 00 00 00 01
Modbus RTU通信主要基于一个主/从模式,其中一个设备充当主设备(Master),负责发起请求;其他设备作为从设备(Slave),响应主设备的请求。
报文格式
从站地址(设备编号) | 功能码 | 数据 | 校验 |
---|---|---|---|
1字节 | 1字节 | N字节 | 2字节 |
代码 | 含义 | 位操作/字操作 | 操作数量 |
---|---|---|---|
0x01 | 读线圈状态 | 位操作(1字节) | 单个或多个 |
0x02 | 读离散输入状态 | 位操作(1字节) | 单个或多个 |
0x03 | 读保持寄存器 | 字操作(2字节) | 单个或多个 |
0x04 | 读输入寄存器 | 字操作(2字节) | 单个或多个 |
0x05 | 写单个线圈 | 位操作(1字节) | 单个 |
0x06 | 写单个保持寄存器 | 字操作(2字节) | 单个 |
0x0F | 写多个线圈 | 位操作(1字节) | 多个 |
0x10 | 写多个保持寄存器 | 字操作(2字节) | 多个 |
例,查询从机地址为0x01,线圈寄存器的起始地址为0x0013,结束地址为0x0037。该次查询总共访问37个线圈寄存器。
字节序号 | 功能 | 16进制数据 |
---|---|---|
1 | 从机地址 | 01 |
2 | 功能码 | 01 |
3 | 寄存器起始地址高字节 | 00 |
4 | 寄存器起始地址低字节 | 13 |
5 | 寄存器数量高字节 | 00 |
6 | 寄存器数量低字节 | 25 |
7 | CRC校验低字节 | 0C |
8 | CRC校验高字节 | 14 |