Modbus功能码详解
创作时间:
作者:
@小白创作中心
Modbus功能码详解
引用
1
来源
1.
https://www.modbus.cn/27934.html
Modbus功能码是Modbus协议中通信事务处理的基础,主要用于实现主从设备之间的数据读写操作。本文详细介绍了Modbus协议中的各类功能码,包括其分类、具体功能和使用场景。
概述
Modbus功能码占用一个字节,取值范围是1127(即0x010x7F)。同时,使用功能码+0x80表示异常状态,即129~255代表异常码。
在Modbus标准协议中,一共规定了三类Modbus功能码:
- 公共功能码
- 被明确定义的功能码;
- 保证唯一性;
- 由Modbus协会确认,并提供公开的文档;
- 可进行一致性测试;
- 包括协议定义的功能码和保留将来使用的功能码。
- 用户自定义功能码
- 有两个用户自定义功能码区域,分别是6572和100110;
- 用户自定义,不保证唯一性。
- 保留功能码
- 保留功能码是因为历史遗留原因,某些公司的传统产品上现行使用的功能码不作为公共使用。
本教程主要介绍公共功能码,下表展示了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传输中的数据字段的字节序。
热门推荐
专家推荐:预防抽筋小妙招
孕妈必备:缓解小腿抽筋的最佳食物
抽筋竟是这种病的预警信号?专家教你识别风险
第二十六届哈尔滨冰雪大世界:以“冰雪同梦 亚洲同心”为主题,打造世界级冰雪盛宴
冬日为什么要去大同:有雪中奇观、北方年味,还有运动和震撼
银行自助银行功能布局的优化策略
高丰文、施拉普纳亮相央视春晚:中国足球的辉煌与困境
春晚中的国足:从拜年到调侃,再到期待
【对话三十年·发现崂山美】崂山风景区:山海诗意共远方
三亚旅游攻略:未来一周最佳出行时间
三亚水上运动大挑战:你敢来吗?
冬日海南游:亚龙湾&骑楼老街必打卡!
畅游梁山县:必去景点与美食攻略
千年古县|东平:水泊梁山发源地,全国第二移民大县
同学聚会致辞指南:如何写出一篇感人至深的新年致辞?
马拉松跑者必看:小腿抽筋的真相揭秘
抽筋怎么办?这些方法快速缓解你的痛苦
五贝(彭飞)讲天干地支中国古代时间哲学的精妙体现
天干地支与生肖对照表
春运期间高速路保障是如何运作?记者探访,巡查实时测道路“体温”,无人机作业排堵点
补充电解质喝什么
青椒肉丝怎么炒好吃又简单?从选材、腌肉、火候,到炒制保姆教学
鉴定古董其实只用一招!
豪迈超逸、再续写意——著名写意画家姜国华上海展览侧记
漳浦美食:从传统小吃到特色糕点,一文详解漳浦美食文化
丽江古城:云南自驾游必打卡摄影圣地
冬日云南自驾游:抚仙湖、建水古城、元阳梯田7日游
自驾云南,探秘百草村和小渔村!
秋日云南自驾游:最美路线大揭秘!
《南方周末》新年献词:39年坚持背后的写作智慧