- 1. 概述
- 2. function code
- 3. 0x01 读取线圈/离散量输出值
- 4. 0x02 读取离散量输入值
- 5. 0x03 Read and hold register值
- 6. 0x04 Read input register值
- 7. 0x05 写单个线圈/单个离散输出
- 8. 0x06 写单个保持register
- 9. 0x08 诊断Function
- 10. 0x0B 获取通信事件计数器
- 11. 0x0C 获取通信事件记录
- 12. 0x0F 写多个线圈
- 13. 0x10 写多个保持register
- 14. 0x11 报告从站 ID
- 15. 总结
Modbus function code是 Modbus 消息帧(message)的重要组成部分,是 Modbus protocol中通信事务处理的基础。

概述
Modbus function code占用一个byte,取值范围是 1~127(即 0x01~0x7F)。同时,使用function code + 0x80 表示异常状态,即 129~255 代表Exception Code。
在 Modbus 标准协议中,一共规定了三类 Modbus function code。
- 公共function code
- 被明确定义的function code;
- 保证唯一性;
- 由 Modbus 协会Confirm,并提供公开的Document;
- 可进行一致性测试;
- 包括协议定义的function code和保留将来使用的function code。
- 用户Customizationfunction code
- 有两个用户Customizationfunction code区域,分别是 65
72 和 100110; - 用户Customization,不保证唯一性。
- 有两个用户Customizationfunction code区域,分别是 65
- 保留function code
- 保留function code是因为历史遗留原因,某些公司的传统产品上现行使用的function code不作为公共使用。
本Tutorial主要介绍公共function code,下表展示了 Modbus protocol中的部分公共function code。
| 代码 | 名称 | 英文 | register PLC address | 位/字Operation | Operationquantity |
|---|---|---|---|---|---|
| 01 | 读Coil status | Read Coils | 00001~09999 | 位Operation | 单个或多个 |
| 02 | 读离散input state | Read Discrete Inputs | 10001~19999 | 位Operation | 单个或多个 |
| 03 | 读保持register | Read Holding Registers | 40001~49999 | 字Operation | 单个或多个 |
| 04 | 读输入register | Read Input Registers | 30001~39999 | 字Operation | 单个或多个 |
| 05 | 写单个线圈 | Write Single Coil | 00001~09999 | 位Operation | 单个 |
| 06 | 写单个保持register | Write Single Register | 40001~49999 | 字Operation | 单个 |
| 15 | 写多个线圈 | Write Multiple Coils | 00001~09999 | 位Operation | 多个 |
| 16 | 写多个保持register | Write Multiple Registers | 40001~49999 | 字Operation | 多个 |
function code的Operation可分为两种:
- 位Operation —— 最小单位为一位(bit),包括读Coil statusfunction code 01、读离散input statefunction code 02、写单个线圈function code 05 和写多个线圈function code 15;
- 字Operation —— 最小单位为两个byte,包括读保持registerfunction code 03、读输入registerfunction code 04、写单个保持registerfunction code 06 和写多个保持registerfunction code 16。
function code
0x01 读取线圈/离散量输出值
- 该function code用于读取从设备的线圈或离散量输出的状态,即各 DO(Discrete Output,离散输出)的 ON/OFF 状态。
- 消息帧中指定了需读取的线圈starting address和线圈数目。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- 线圈quantity由 2 个byte构成,取值范围为 0x0001 到 0x07D0(即decimal 1~2000)。
- 需要注意,在 Modbus protocol规定的 PDU 中,规定所有线圈或register address从 0 开始计算。
0x02 读取离散量输入值
- 该function code用于读取从设备的离散输入,即 DI(Discrete Input)的 ON/OFF 状态。
- 消息帧中指定了需读取的离散输入registerstarting address和数目,可读取 1~2000 个连续的离散量input state。
- 如果从设备接受主设备的Request则回复function code 02,并返回离散量输入各变量的当前状态(如果返回的 DI quantity不是 8 的整数倍,将用 0 填充最后databyte的剩余位)。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- 离散量quantity由 2 个byte构成,取值范围为 0x0001 到 0x07D0(即decimal 1~2000),最多一次可读取 2000 个离散input state值。
0x03 Read and hold register值
- 该function code用于读取从设备保持register的内容,不支持广播模式。
- 消息帧中指定了需读取的保持register的starting address和数目,而保持register中各address的具体内容和意义则由设备developer自行规定。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- number of registers由 2 个byte构成,取值范围为 0x0001 到 0x007D(即decimal 1~125),最多一次可连续读取 125 个register value。
- 需要注意,Modbus 的保持register和输入register是以字(Word)为基本单位的(1Word 等于 2Bytes)。因此,在读取时需要注意endianness(大小端)问题。
0x04 Read input register值
- 该function code用于读取从设备输入register的内容,不支持广播模式。(与 03 function code类似)
- 消息帧中指定了需读取的输入register的starting address和数目,而输入register中各address的具体内容和意义则由设备developer自行规定。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- number of registers由 2 个byte构成,取值范围为 0x0001 到 0x007D(即decimal 1~125),最多一次可连续读取 125 个register value。
- 同样需要注意endianness问题。
0x05 写单个线圈/单个离散输出
- 该function code用于将单个线圈register(或离散输出)设置为 ON 或 OFF,支持广播模式。
- 在广播模式下,所有从站设备的同一address的值将被统一修改。
- 消息帧中指定了需要变更的Coil address和设定的状态值。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- 目标data(即查询message中的 ON/OFF 状态)由messagedatafield的constant指定,0xFF00 表示 ON 状态,0x0000 表示 OFF 状态,其余所有值均是非法的。
- 需要注意,在 Modbus protocol规定的 PDU 中,规定所有线圈或register address从 0 开始计算。
0x06 写单个保持register
- 该function code用于更新从设备的单个保持register的值,支持广播模式。
- 在广播模式下,所有从站设备的同一address的值将被统一修改。
- 消息帧中需要指定从Device address以及需要变更的保持register address和设定值。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- 变更目标data由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- 保持register以字(Word)为基本单位,写入时需要注意目标data的endianness问题。
0x08 诊断Function
- 该function code仅用于串行链路,主要用于检测主设备和从设备之间的通信故障,或检测从设备的各种内部故障,该Function不支持广播。
- 查询message中需要指定从Device address、function code(Modbus Command)以及子function code(Diagnostic Sub-function)。其中,子function codefield为 2 个byte,用于区别各诊断Type。
- 在正常的Responsemessage中,从设备将原样回复function code和子function code。
常用的 Modbus 诊断子function code定义如下:
| function code | 子function code | 描述 | 说明 |
|---|---|---|---|
| 08 | 00(0x00) | Return Data Query (Loop-back) | 原样返回查询message |
| 08 | 01(0x01) | Restart Communications | 用于初始化并重新启动从站设备 其中,messagefield 0x00, 0x00 表示保持事件记录 0xFF, 0x00 表示Clear事件记录 |
| 08 | 02(0x02) | Return Diagnostic Register | 返回诊断register内容 |
| 08 | 03(0x03) | Change ASCII Input Delimiter | |
| 08 | 04(0x04) | Force Listen Only Mode | 强制被寻址的从站设备进入只听模式 使其与网络中的其他设备断开,不返回Response |
| 08 | 10(0x0A) | Clear Counters and Diagnostic Registers | Clear计数器和诊断register |
| 08 | 11(0x0B) | Return Bus Message Count | 返回总线message计numerical value |
| 08 | 12(0x0C) | Return Bus Communication Error Count | 返回总线通信 CRC 出错计数 |
| 08 | 13(0x0D) | Return Bus Exception Error Count | 返回总线异常计数 |
| 08 | 14(0x0E) | Return Slave Message Count | 返回从站设备receive的messagequantity |
| 08 | 15(0x0F) | Return Slave No Response Count | 返回从站设备没有返回Response的messagequantity |
| 08 | 16(0x10) | Return Slave NAK Count | |
| 08 | 17(0x11) | Return Slave Busy Count | 返回从站设备Response忙的messagequantity |
| 08 | 18(0x12) | Return Bus Character Overrun Count | 返回总线字符超限的messagequantity |
| 08 | 19(0x13) | Return IOP Overrun Count (884) | |
| 08 | 20(0x14) | Clear Overrun Counter and Flag (884) |
0x0B 获取通信事件计数器
- 该function code主要用于获取从设备通信计数器中的状态字和事件计数的值,不支持广播模式。
- 可以通过在通信message之前和之后读取通信事件计numerical value,来确定从设备是否正常处理message。
- 对于正常Completemessage处理和传输的场合,事件计数器增加 1;而对于Exception Response、轮询命令或读事件计数器(即 0x0B function code)的场合,则计数器不变。
- 通过 0x08 诊断Function中的 0x01 子Function和 0x0A 子Function,可以复位事件register。
0x0C 获取通信事件记录
- 该function code主要用于从从设备获取状态字、事件计数、message计数以及事件bytefield。
- 其中状态字和事件计数与function code 0x0B 获取的值一致。
- message计数器包含了加电重启、Clear计数器之后的messagequantity,message计数与通过 0x08 诊断Function中的 0x0B 子function code获取的值一致。
- 事件bytefield包含 0~64 个byte,定义各种事件。
- 正常情况下Responsemessage包括一个 2 Bytes 状态字field、一个 2 Bytes 事件计数field、一个 2 Bytes 消息计数field以及 0~64 个byte的事件field。
- 由于事件field是变长的,因此增加了一个 1 Byte 的dataLengthfield,以方便读取Responsedata。
0x0F 写多个线圈
- 该function code用于将连续的多个线圈(或离散输出)设置为 ON 或 OFF,支持广播模式。
- 在广播模式下,所有从站设备的同一address的值将被统一修改。
- 消息帧中指定了需要变更的线圈starting address和线圈数目。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- number of registersfield由 2 个byte构成,取值范围为 0x0001 到 0x07B0。
- datafield中为逻辑 1 的位对应 ON,逻辑 0 的位对应 OFF。
0x10 写多个保持register
- 该function code用于设置或写入从设备保持register的多个连续的address块(1~123个register),支持广播模式。
- 在广播模式下,所有从站设备的同一address的值将被统一修改。
- 消息帧中需要指定从Device address以及需要变更的保持register address和quantity。
- starting address由 2 个byte构成,取值范围为 0x0000 到 0xFFFF。
- number of registersfield由 2 个byte构成,取值范围为 0x0001 到 0x007B(即decimal 1~123)。
- 在实际开发中,该function code常用于方便用户写入多byteType的data,例如浮点numerical value。因此,需要注意endianness问题。
0x11 报告从站 ID
- 该function code仅适用于串行链路,用于读取从站设备的 ID、Type描述、当前状态以及其他信息,不支持广播模式。
- 查询message中没有datafield。
- Response消息的构成由从站设备决定。
总结
常用 Modbus 公共function code下表所示。

其中,支持广播模式的function code有:
- 0x05 写单个线圈
- 0x06 写单个保持register
- 0x0F 写多个线圈
- 0x10 写多个保持register
除了广播模式的message以外,其他所有查询message都希望能够获取一个正常的Responsemessage。如果一切正常,则从站设备将返回一个正常Responsemessage,该Responsemessage的function code与Requestmessage的function code一致。
另外,对于字Operation的function code,existence多byte存储的大小端问题,因此主站设备和从站设备必须保持一致的Rules处理,约定 Modbus 传输中的datafield的endianness。
发表回复