问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Modbus功能码详解

创作时间:
作者:
@小白创作中心

Modbus功能码详解

引用
1
来源
1.
https://www.modbus.cn/27934.html

Modbus功能码是Modbus协议中通信事务处理的基础,主要用于实现主从设备之间的数据读写操作。本文详细介绍了Modbus协议中的各类功能码,包括其分类、具体功能和使用场景。

概述

Modbus功能码占用一个字节,取值范围是1127(即0x010x7F)。同时,使用功能码+0x80表示异常状态,即129~255代表异常码。

在Modbus标准协议中,一共规定了三类Modbus功能码:

  1. 公共功能码
  • 被明确定义的功能码;
  • 保证唯一性;
  • 由Modbus协会确认,并提供公开的文档;
  • 可进行一致性测试;
  • 包括协议定义的功能码和保留将来使用的功能码。
  1. 用户自定义功能码
  • 有两个用户自定义功能码区域,分别是6572和100110;
  • 用户自定义,不保证唯一性。
  1. 保留功能码
  • 保留功能码是因为历史遗留原因,某些公司的传统产品上现行使用的功能码不作为公共使用。

本教程主要介绍公共功能码,下表展示了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状态,其余所有值均是非法的。
  • 需要注意,在Modbus协议规定的PDU中,规定所有线圈或寄存器地址从0开始计算。

0x06 写单个保持寄存器

  • 该功能码用于更新从设备的单个保持寄存器的值,支持广播模式。
  • 在广播模式下,所有从站设备的同一地址的值将被统一修改。
  • 消息帧中需要指定从设备地址以及需要变更的保持寄存器地址和设定值。
  • 起始地址由2个字节构成,取值范围为0x0000到0xFFFF。
  • 变更目标数据由2个字节构成,取值范围为0x0000到0xFFFF。
  • 保持寄存器以字(Word)为基本单位,写入时需要注意目标数据的字节序问题。

0x08 诊断功能

  • 该功能码仅用于串行链路,主要用于检测主设备和从设备之间的通信故障,或检测从设备的各种内部故障,该功能不支持广播。
  • 查询报文中需要指定从设备地址、功能码(Modbus Command)以及子功能码(Diagnostic Sub-function)。其中,子功能码字段为2个字节,用于区别各诊断类型。
  • 在正常的响应报文中,从设备将原样回复功能码和子功能码。

常用的Modbus诊断子功能码定义如下:

功能码
子功能码
描述
说明
08
00(0x00)
Return Data Query (Loop-back)
原样返回查询报文
08
01(0x01)
Restart Communications
用于初始化并重新启动从站设备其中,报文字段0x00, 0x00 表示保持事件记录0xFF, 0x00 表示清除事件记录
08
02(0x02)
Return Diagnostic Register
返回诊断寄存器内容
08
03(0x03)
Change ASCII Input Delimiter
08
04(0x04)
Force Listen Only Mode
强制被寻址的从站设备进入只听模式使其与网络中的其他设备断开,不返回响应
08
10(0x0A)
Clear Counters and Diagnostic Registers
清除计数器和诊断寄存器
08
11(0x0B)
Return Bus Message Count
返回总线报文计数值
08
12(0x0C)
Return Bus Communication Error Count
返回总线通信CRC出错计数
08
13(0x0D)
Return Bus Exception Error Count
返回总线异常计数
08
14(0x0E)
Return Slave Message Count
返回从站设备接收的报文数量
08
15(0x0F)
Return Slave No Response Count
返回从站设备没有返回响应的报文数量
08
16(0x10)
Return Slave NAK Count
08
17(0x11)
Return Slave Busy Count
返回从站设备响应忙的报文数量
08
18(0x12)
Return Bus Character Overrun Count
返回总线字符超限的报文数量
08
19(0x13)
Return IOP Overrun Count (884)
08
20(0x14)
Clear Overrun Counter and Flag (884)

0x0B 获取通信事件计数器

  • 该功能码主要用于获取从设备通信计数器中的状态字和事件计数的值,不支持广播模式。
  • 可以通过在通信报文之前和之后读取通信事件计数值,来确定从设备是否正常处理报文。
  • 对于正常完成报文处理和传输的场合,事件计数器增加1;而对于异常响应、轮询命令或读事件计数器(即0x0B功能码)的场合,则计数器不变。
  • 通过0x08诊断功能中的0x01子功能和0x0A子功能,可以复位事件寄存器。

0x0C 获取通信事件记录

  • 该功能码主要用于从从设备获取状态字、事件计数、报文计数以及事件字节字段。
  • 其中状态字和事件计数与功能码0x0B获取的值一致。
  • 报文计数器包含了加电重启、清除计数器之后的报文数量,报文计数与通过0x08诊断功能中的0x0B子功能码获取的值一致。
  • 事件字节字段包含0~64个字节,定义各种事件。
  • 正常情况下响应报文包括一个2Bytes状态字字段、一个2Bytes事件计数字段、一个2Bytes消息计数字段以及0~64个字节的事件字段。
  • 由于事件字段是变长的,因此增加了一个1Byte的数据长度字段,以方便读取响应数据。

0x0F 写多个线圈

  • 该功能码用于将连续的多个线圈(或离散输出)设置为ON或OFF,支持广播模式。
  • 在广播模式下,所有从站设备的同一地址的值将被统一修改。
  • 消息帧中指定了需要变更的线圈起始地址和线圈数目。
  • 起始地址由2个字节构成,取值范围为0x0000到0xFFFF。
  • 寄存器数量字段由2个字节构成,取值范围为0x0001到0x07B0。
  • 数据字段中为逻辑1的位对应ON,逻辑0的位对应OFF。

0x10 写多个保持寄存器

  • 该功能码用于设置或写入从设备保持寄存器的多个连续的地址块(1~123个寄存器),支持广播模式。
  • 在广播模式下,所有从站设备的同一地址的值将被统一修改。
  • 消息帧中需要指定从设备地址以及需要变更的保持寄存器地址和数量。
  • 起始地址由2个字节构成,取值范围为0x0000到0xFFFF。
  • 寄存器数量字段由2个字节构成,取值范围为0x0001到0x007B(即十进制1~123)。
  • 在实际开发中,该功能码常用于方便用户写入多字节类型的数据,例如浮点数值。因此,需要注意字节序问题。

0x11 报告从站 ID

  • 该功能码仅适用于串行链路,用于读取从站设备的ID、类型描述、当前状态以及其他信息,不支持广播模式。
  • 查询报文中没有数据字段。
  • 响应消息的构成由从站设备决定。

总结

常用Modbus公共功能码下表所示。

其中,支持广播模式的功能码有:

  • 0x05 写单个线圈
  • 0x06 写单个保持寄存器
  • 0x0F 写多个线圈
  • 0x10 写多个保持寄存器

除了广播模式的报文以外,其他所有查询报文都希望能够获取一个正常的响应报文。如果一切正常,则从站设备将返回一个正常响应报文,该响应报文的功能码与请求报文的功能码一致。

另外,对于字操作的功能码,存在多字节存储的大小端问题,因此主站设备和从站设备必须保持一致的规则处理,约定Modbus传输中的数据字段的字节序。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号