Modbus学习笔记
Modbus通信协议
1.Modbus简介——来自维基百科
Modbus是一种串行通信协议,是Modicon于1979年,为使用可编程逻辑控制器(PLC)而发表的。Modbus是工业领域通信协议的业界标准,并且现在是工业电子设备之间相当常用的连接方式。Modbus比其他通信协议使用的更广泛的主要原因有:
- 【1】公开发表并且无版税要求
- 【2】相对容易的工业网络部署
- 【3】对供应商来说,修改移动原生的位元或字节没有很多限制
Modbus官网:http://www.modbus.org
- PDU(协议数据单元)包括功能码和数据
- ADU(应用数据单元)包括地址域、功能码、数据、差错校验
术语:
- Master: 主设备
- Slave: 从设备
- Client: 客户端
- Server: 服务器端
- ADU: 应用数据单元
- PDU: 协议数据单元
- MSB: 最高有效位
- LSB: 最低有效位
- MBAP: Modbus应用协议
- PLC: 可编程逻辑控制器
一、Modbus开发环境:
- Modbus Poll
下载地址:http://www.modbustools.com/
Modbus主站设备仿真器,可以用于测试和调试Modbus从站设备,便于观察Modbus通信过程中的各种报文数据。
该软件支持Modbus RTU、ASCII、TCP/IP等协议模式。 - Modbus Slave:
下载地址:http://www.modbustools.com/
用来模拟Modbus从设备的工具。它用于接收主设备的命令包,并回送数据包;可用于测试和调试Modbus主站设备,便于
观察Modbus通信过程中的各种报文数据。 - Visual Serial Port Driver
下载地址:http://www.eltima.com/ - Mthings
- Visual Studio 2019
二、Modbus协议概要:
Modbus协议是一种单主/多从的通信协议,其特点是在同一时间,总线上只能有一个主设备,但可以有一个或者多个(最多247个)从设备。
Modbus通信总是由主设备发起,当从设备没有收到来自主设备的请求时,不会主动发送数据。
从设备之间不能相互通信,主设备同时只能启动一个Modbus访问事务处理。
三、Modbus通信模式:
-
- 单播模式
-
- 广播模式
四、Modbus寄存器
四种寄存器:
- 线圈状态(Coil Status)
- 离散输入状态(Input Status)
- 保持寄存器(Holding Register)
- 输入寄存器(Input Register)
五、Modbus功能码
分为两类:位操作和字操作。
位操作的最小单位为一位(bit),字操作的最小单位为两个字节。
-
位操作指令:
- 读线圈状态功能码 01
- 读(离散)输入状态功能码 02
- 写单个线圈功能码 05
- 写多个线圈功能码 15
-
字操作指令:
- 读保持寄存器功能码 03
- 读输入寄存器功能码 04
- 写单个保持寄存器功能码 06
- 写多个保持寄存器功能码 16
1. 读取线圈/离散量输出状态(0x01x) 位操作
该功能码用于读取从设备的线圈或离散量输出的状态,即各DO(Discrete Output)的ON/OFF状态。
发送报文
Tx:000-01 01 00 13 00 25 0C 14
从设备地址(01)+功能码(01)+起始地址(0013)+寄存器数(0025)+差错校验(0C 14)
接收报文:
Rx:001-01 01 05 53 6B 01 F4 1B 5E 71
从设备地址(01)+功能码(01)+数据域字节数(05)+数据(53 6B 01 F4 1B)+差错校验(5E 71)
2. 读取离散量输入值(0x02) 位操作
该功能码用于读取从设备的离散输入即DI(Discrete Input)的ON/OFF状态。
发送报文
Tx:008-03 02 00 64 00 14 38 38
从设备地址(03)+功能码(02)+起始地址(00 64)+寄存器数(00 14)+差错校验(38 38)
接收报文
Rx:009-03 02 03 13 E7 06 43 9B
从设备地址(03)+功能码(02)+数据域字节数(03)+数据(13 E7 06)+差错校验(43 9B)
注意一个寄存器代表一位 寄存器数为0x14,数据为3个字节
3. 读取保持寄存器值(0x03) 字操作
该功能码用于读取从设备保持寄存器的内容,不支持广播模式。
发送报文
Tx:020-03 03 00 C8 00 03 85 D7
从设备地址(03)+功能码(03)+起始地址(00 C8)+寄存器数(00 03)+差错校验(85 D7)
接收报文
Rx:021-03 03 06 03 53 01 F3 01 05 8C 76
从设备地址(03)+功能码(03)+数据域字节数(06)+数据(53 01 F3 01 05 8C)+差错校验(8C 76)
4. 读取输入寄存器值(0x04) 字操作
该功能码用于读取从设备输入寄存器的内容,不支持广播模式。
发送报文:
Tx:000-07 04 01 2C 00 03 70 58
从设备地址(07)+功能码(04)+起始地址(01 2C)+寄存器数(00 03)+差错校验(85 D7)
接收报文:
Rx:001-07 04 06 03 53 01 F3 01 05 FF 50
从设备地址(07)+功能码(04)+数据域字节数(06)+数据(03 53 01 F3 01 05)+差错校验(FF 50)
5. 写单个线圈或单个离散输出(0x05) 位操作
本功能码用于将单个线圈寄存器(或离散输入)设置为ON或OFF,该功能码支持广播模式,在广播模式下,所有从站设备的同一地址的值将被统一修改。
0xFF00表示ON状态,0x0000标识0FF状态
发送报文:
Tx:368-07 05 00 95 FF 00 9C 70
从设备地址(07)+功能码(05)+起始地址(00 95)+变更数据(FF00)+差错校验(9C 70)
接收报文:
Rx:369-07 05 00 95 FF 00 9C 70
从设备地址(07)+功能码(05)+起始地址(00 95)+变更数据(FF00)+差错校验(9C 70)
6. 写单个保持寄存器(0x06) 字操作
本功能码用于更新从设备的单个保持寄存器的值。该功能码支持广播模式,在广播模式下,所有从设备的同一地址的值将被统一修改。
发送报文:
Tx:387-03 06 00 95 04 B0 9B 70
从设备地址(03)+功能码(06)+起始地址(00 95)+变更数据(04 B0)+差错校验(9B 70)
接收报文:
Rx:388-03 06 00 95 04 B0 9B 70
从设备地址(03)+功能码(06)+起始地址(00 95)+变更数据(04 B0)+差错校验(9B 70)
8. 诊断功能(0x08)
该功能码仅用于串行链路,主要用于检测主设备和从设备之间的通信故障或检测从设备的各种内部故障,该功能码不支持广播。为了区别各诊断类型,查询报文中提供了2个字节的子功能码字段。
通常,在正常的响应报文中,从设备将原样回复功能码和子功能码。
未测试
9. 获取通信事件计数器(0x0B)
该功能码主要用于获取从设备通信计数器中的状态字和事件计数的值,本功能不支持广播模式。通过在通信报文之前和之后读取通信事件计数值,可以确定从设备是否正常处理报文。
未测试
10. 获取通信事件记录(0x0C)
该功能码主要用于从从设备获取状态字、事件计数、报文计数以及事件字节字段。
11. 写多个线圈(0x0F) 位操作
该功能码用于将连续的多个线圈或离散输出设置位ON/OFF状态,支持广播模式,在广播模式下,所有从站设备的同一地址的值将被统一修改。
本功能码中,起始地址字段由2各字节构成,取值范围为0x0000-0xFFFF;而寄存器数量字段由2个字节构成,取值范围为0x0001-0x07B0。
示例:从站设备为5,需要设置线圈地址20-30的状态:
值 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
线圈 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | — | — | — | — | — | 30 | 29 | 28 |
写入数据从20-30,分为两个字节,0xD1(27-20),0x05(30-28)
Modbus起始地址比线圈起始地址20少1,也就是19,所以发送的报文如下:
发送报文:
Tx:458-05 0F 00 13 00 0B 02 D1 05 48 F4
从设备地址(05)+功能码(0F)+起始地址(00 13)+寄存器数(00 0B)+字节数(02)+变更数据(D1 05)+差错校验(9B 70)
响应报文:
Rx:459-05 0F 00 13 00 0B E4 4D
从设备地址(05)+功能码(0F)+起始地址(00 13)+寄存器数(00 0B)+差错校验(E4 4D)
12. 写多个保持寄存器(0x10) 字操作
该功能码用于设置或写入从设备保持寄存器的多个连续的地址块(1-123个寄存器),支持广播模式,在广播模式下,所有从站设备的同一地址的值将被统一修改。
本功能码中,起始地址字段由2各字节构成,取值范围为0x0000-0xFFFF;而寄存器数量字段由2个字节构成,取值范围为0x0001-0x07B0。
示例:从站设备地址为5,需要将保持寄存器地址40020-40022设置为如下表所示的数值:
寄存器地址 | 设定值 | 寄存器地址 | 设定值 |
---|---|---|---|
40020 | 0x0155 | 40022 | 0x0157 |
40021 | 0x0156 |
Modbus起始地址为19(0x13),比寄存器起始地址少1
发送报文:
Tx:462-05 10 00 13 00 03 06 01 55 01 56 01 57 B5 C1
从设备地址(05)+功能码(10)+起始地址(00 13)+寄存器数(00 03)+字节数(06)+变更数据(01 55 01 56 01 57)+差错校验(B5 C1)
响应报文:
Rx:463-05 10 00 13 00 03 70 49
从设备地址(05)+功能码(10)+起始地址(00 13)+寄存器数(00 03)+差错校验(70 49)
13. 报告从站ID(仅用于串行链路)
该功能码用于读取从站设备的ID、类型描述、当前状态及其他信息,不支持广播模式。