Modbus 功能码
Modbus 功能码是 Modbus 消息帧(报文)的重要组成部分,是 Modbus 协议中通信事务处理的基础。
概述
Modbus 功能码占用一个字节,取值范围是 1~127(即 0x01~0x7F)。同时,使用功能码 + 0x80 表示异常状态,即 129~255 代表异常码。
在 Modbus 标准协议中,一共规定了三类 Modbus 功能码。
- 公共功能码
- 被明确定义的功能码;
- 保证唯一性;
- 由 Modbus 协会确认,并提供公开的文档;
- 可进行一致性测试;
- 包括协议定义的功能码和保留将来使用的功能码。
- 用户自定义功能码
- 有两个用户自定义功能码区域,分别是 65
72 和 100110; - 用户自定义,不保证唯一性。
- 有两个用户自定义功能码区域,分别是 65
- 保留功能码
- 保留功能码是因为历史遗留原因,某些公司的传统产品上现行使用的功能码不作为公共使用。
本教程主要介绍公共功能码,下表展示了 Modbus 协议中的部分公共功能码。
代码 | 名称 | 英文 | 寄存器 PLC 地址 | 位/字操作 | 操作数量 |
---|---|---|---|---|---|
01 | 读线圈状态 | Read Coils | 00001~09999 | 位操作 | 单个或多个 |
02 | 读离散输入状态 | Read Discrete Inputs | 10001~19999 | 位操作 | 单个或多个 |
03 | 读保持寄存器 | Read Holding Registers | 40001~49999 | 字操作 | 单个或多个 |
04 | 读输入寄存器 | Read Input Registers | 30001~39999 | 字操作 | 单个或多个 |
05 | 写单个线圈 | Write Single Coil | 00001~09999 | 位操作 | 单个 |
06 | 写单个保持寄存器 | Write Single Register | 40001~49999 | 字操作 | 单个 |
15 | 写多个线圈 | Write Multiple Coils | 00001~09999 | 位操作 | 多个 |
16 | 写多个保持寄存器 | Write Multiple Registers | 40001~49999 | 字操作 | 多个 |
功能码的操作可分为两种:
- 位操作 —— 最小单位为一位(bit),包括读线圈状态功能码 01、读离散输入状态功能码 02、写单个线圈功能码 05 和写多个线圈功能码 15;
- 字操作 —— 最小单位为两个字节,包括读保持寄存器功能码 03、读输入寄存器功能码 04、写单个保持寄存器功能码 06 和写多个保持寄存器功能码 16。
功能码
0x01 读取线圈/离散量输出值
- 该功能码用于读取从设备的线圈或离散量输出的状态,即各 DO(Discrete Output,离散输出)的 ON/OFF 状态。
- 消息帧中指定了需读取的线圈起始地址和线圈数目。
- 起始地址由 2 个字节构成,取值范围为 0x0000 到 0xFFFF。
- 线圈数量由 2 个字节构成,取值范围为 0x0001 到 0x07D0(即十进制 1~2000)。
- 需要注意,在 Modbus 协议规定的 PDU 中,规定所有线圈或寄存器地址从 0 开始计算。
0x02 读取离散量输入值
- 该功能码用于读取从设备的离散输入,即 DI(Discrete Input)的 ON/OFF 状态。
- 消息帧中指定了需读取的离散输入寄存器起始地址和数目,可读取 1~2000 个连续的离散量输入状态。
- 如果从设备接受主设备的请求则回复功能码 02,并返回离散量输入各变量的当前状态(如果返回的 DI 数量不是 8 的整数倍,将用 0 填充最后数据字节的剩余位)。
- 起始地址由 2 个字节构成,取值范围为 0x0000 到 0xFFFF。
- 离散量数量由 2 个字节构成,取值范围为 0x0001 到 0x07D0(即十进制 1~2000),最多一次可读取 2000 个离散输入状态值。
0x03 读取保持寄存器值
- 该功能码用于读取从设备保持寄存器的内容,不支持广播模式。
- 消息帧中指定了需读取的保持寄存器的起始地址和数目,而保持寄存器中各地址的具体内容和意义则由设备开发者自行规定。
- 起始地址由 2 个字节构成,取值范围为 0x0000 到 0xFFFF。
- 寄存器数量由 2 个字节构成,取值范围为 0x0001 到 0x007D(即十进制 1~125),最多一次可连续读取 125 个寄存器值。
- 需要注意,Modbus 的保持寄存器和输入寄存器是以字(Word)为基本单位的(1Word 等于 2Bytes)。因此,在读取时需要注意字节序(大小端)问题。
0x04 读取输入寄存器值
- 该功能码用于读取从设备输入寄存器的内容,不支持广播模式。(与 03 功能码类似)
- 消息帧中指定了需读取的输入寄存器的起始地址和数目,而输入寄存器中各地址的具体内容和意义则由设备开发者自行规定。
- 起始地址由 2 个字节构成,取值范围为 0x0000 到 0xFFFF。
- 寄存器数量由 2 个字节构成,取值范围为 0x0001 到 0x007D(即十进制 1~125),最多一次可连续读取 125 个寄存器值。
- 同样需要注意字节序问题。
0x05 写单个线圈/单个离散输出
- 该功能码用于将单个线圈寄存器(或离散输出)设置为 ON 或 OFF,支持广播模式。
- 在广播模式下,所有从站设备的同一地址的值将被统一修改。
- 消息帧中指定了需要变更的线圈地址和设定的状态值。
- 起始地址由 2 个字节构成,取值范围为 0x0000 到 0xFFFF。
- 目标数据(即查询报文中的 ON/OFF 状态)由报文数据字段的常数指定,0xFF00 表示 ON 状态,0x0000 表示 OFF 状态,其余所有值均是非法的。