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 회원가입s | 40001~49999 | 字操作 | 单个或多个 |
| 04 | 读입력 레지스터 | Read Input 회원가입s | 30001~39999 | 字操作 | 单个或多个 |
| 05 | 写单个코일 | Write Single Coil | 00001~09999 | 位操作 | 单个 |
| 06 | 写单个유지 레지스터 | Write Single 회원가입 | 40001~49999 | 字操作 | 单个 |
| 15 | 写多个코일 | Write Multiple Coils | 00001~09999 | 位操作 | 多个 |
| 16 | 写多个유지 레지스터 | Write Multiple 회원가입s | 40001~49999 | 字操作 | 多个 |
기능 코드的操作可分为两种:
- 位操作 —— 最小单位为一位(bit),包括读코일 상태기능 코드 01、读이산 입력状态기능 코드 02、写单个코일기능 코드 05 和写多个코일기능 코드 15;
- 字操作 —— 最小单位为两个바이트,包括读유지 레지스터기능 코드 03、读입력 레지스터기능 코드 04、写单个유지 레지스터기능 코드 06 和写多个유지 레지스터기능 코드 16。
기능 코드
0x01 읽기코일/离散量출력值
- 该기능 코드用于읽기从设备的코일或离散量출력的状态,即各 DO(Discrete Output,离散출력)的 ON/OFF 状态。
- 消息帧中指定了需읽기的코일시작주소和코일数目。
- 시작주소由 2 个바이트构成,取值范围为 0x0000 到 0xFFFF。
- 코일 수량由 2 个바이트构成,取值范围为 0x0001 到 0x07D0(即10진수 1~2000)。
- 需要注意,在 Modbus 프로토콜规定的 PDU 中,规定所有코일或레지스터주소从 0 开始계산。
0x02 읽기离散量입력值
- 该기능 코드用于읽기从设备的이산 입력,即 DI(Discrete Input)的 ON/OFF 状态。
- 消息帧中指定了需읽기的离散입력 레지스터시작주소和数目,可읽기 1~2000 个连续的离散量입력 상태。
- 如果从设备接受主设备的请求则回复기능 코드 02,并返回离散量입력各변수的当前状态(如果返回的 DI 数量不是 8 的整数倍,将用 0 填充最后데이터바이트的剩余位)。
- 시작주소由 2 个바이트构成,取值范围为 0x0000 到 0xFFFF。
- 离散量数量由 2 个바이트构成,取值范围为 0x0001 到 0x07D0(即10진수 1~2000),最多一次可읽기 2000 个이산 입력状态值。
0x03 유지 레지스터 읽기 (FC03)值
- 该기능 코드用于읽기从设备유지 레지스터的콘텐츠,不支持广播모드。
- 消息帧中指定了需읽기的유지 레지스터的시작주소和数目,而유지 레지스터中各주소的具体콘텐츠和意义则由设备개발者自行规定。
- 시작주소由 2 个바이트构成,取值范围为 0x0000 到 0xFFFF。
- 레지스터 수량由 2 个바이트构成,取值范围为 0x0001 到 0x007D(即10진수 1~125),最多一次可连续읽기 125 个레지스터 값。
- 需要注意,Modbus 的유지 레지스터和입력 레지스터是以字(Word)为基本单位的(1Word 等于 2Bytes)。因此,在읽기时需要注意바이트序(大小端)문제。
0x04 입력 레지스터 읽기 (FC04)值
- 该기능 코드用于읽기从设备입력 레지스터的콘텐츠,不支持广播모드。(与 03 기능 코드类似)
- 消息帧中指定了需읽기的입력 레지스터的시작주소和数目,而입력 레지스터中各주소的具体콘텐츠和意义则由设备개발者自行规定。
- 시작주소由 2 个바이트构成,取值范围为 0x0000 到 0xFFFF。
- 레지스터 수량由 2 个바이트构成,取值范围为 0x0001 到 0x007D(即10진수 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 데이터 Query (Loop-back) | 原样返回查询프레임 |
| 08 | 01(0x01) | Re시작 Communications | 用于初始化并重新启动슬레이브设备 其中,프레임필드 0x00, 0x00 表示保持事件记录 0xFF, 0x00 表示清除事件记录 |
| 08 | 02(0x02) | Return Diagnostic 회원가입 | 返回诊断레지스터콘텐츠 |
| 08 | 03(0x03) | Change ASCII Input Delimiter | |
| 08 | 04(0x04) | Force Listen Only Mode | 强制被寻址的슬레이브设备进入只听모드 使其与네트워크中的其他设备断开,不返回响应 |
| 08 | 10(0x0A) | 지우기 Counters and Diagnostic 회원가입s | 清除计数器和诊断레지스터 |
| 08 | 11(0x0B) | Return Bus Message Count | 返回总线프레임计数值 |
| 08 | 12(0x0C) | Return Bus Communication 오답 Count | 返回总线통신 CRC 出错计数 |
| 08 | 13(0x0D) | Return Bus Exception 오답 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) | 지우기 Overrun Counter and Flag (884) |
0x0B 获取통신事件计数器
- 该기능 코드主要用于获取从设备통신计数器中的状态字和事件计数的值,不支持广播모드。
- 可以通过在통신프레임之前和之后읽기통신事件计数值,来确定从设备是否正常处理프레임。
- 对于正常完成프레임处理和传输的场合,事件计数器추가 1;而对于异常响应、轮询命令或读事件计数器(即 0x0B 기능 코드)的场合,则计数器不变。
- 通过 0x08 诊断功能中的 0x01 子功能和 0x0A 子功能,可以复位事件레지스터。
0x0C 获取통신事件记录
- 该기능 코드主要用于从从设备获取状态字、事件计数、프레임计数以及事件바이트필드。
- 其中状态字和事件计数与기능 코드 0x0B 获取的值一致。
- 프레임计数器包含了加电重启、清除计数器之后的프레임数量,프레임计数与通过 0x08 诊断功能中的 0x0B 子기능 코드获取的值一致。
- 事件바이트필드包含 0~64 个바이트,定义各种事件。
- 正常情况下响应프레임包括一个 2 바이트 状态字필드、一个 2 바이트 事件计数필드、一个 2 바이트 消息计数필드以及 0~64 个바이트的事件필드。
- 由于事件필드是变长的,因此추가了一个 1 바이트 的데이터길이필드,以方便읽기响应데이터。
0x0F 写多个코일
- 该기능 코드用于将连续的多个코일(或离散출력)设置为 ON 或 OFF,支持广播모드。
- 在广播모드下,所有슬레이브设备的同一주소的值将被统一修改。
- 消息帧中指定了需要变更的코일시작주소和코일数目。
- 시작주소由 2 个바이트构成,取值范围为 0x0000 到 0xFFFF。
- 레지스터 수량필드由 2 个바이트构成,取值范围为 0x0001 到 0x07B0。
- 데이터필드中为逻辑 1 的位对应 ON,逻辑 0 的位对应 OFF。
0x10 写多个유지 레지스터
- 该기능 코드用于设置或쓰기从设备유지 레지스터的多个连续的주소块(1~123个레지스터),支持广播모드。
- 在广播모드下,所有슬레이브设备的同一주소的值将被统一修改。
- 消息帧中需要指定从设备주소以及需要变更的유지 레지스터주소和数量。
- 시작주소由 2 个바이트构成,取值范围为 0x0000 到 0xFFFF。
- 레지스터 수량필드由 2 个바이트构成,取值范围为 0x0001 到 0x007B(即10진수 1~123)。
- 在实际개발中,该기능 코드常用于方便用户쓰기多바이트유형的데이터,例如浮点数值。因此,需要注意바이트序문제。
0x11 보고서슬레이브 ID
- 该기능 코드仅适用于串行链路,用于읽기슬레이브设备的 ID、유형설명、当前状态以及其他信息,不支持广播모드。
- 查询프레임中没有데이터필드。
- 响应消息的构成由슬레이브设备决定。
总结
常用 Modbus 公共기능 코드下表所示。

其中,支持广播모드的기능 코드有:
- 0x05 写单个코일
- 0x06 写单个유지 레지스터
- 0x0F 写多个코일
- 0x10 写多个유지 레지스터
除了广播모드的프레임以外,其他所有查询프레임都希望能够获取一个正常的响应프레임。如果一切正常,则슬레이브设备将返回一个正常响应프레임,该响应프레임的기능 코드与请求프레임的기능 코드一致。
另外,对于字操作的기능 코드,存在多바이트存储的大小端문제,因此마스터设备和슬레이브设备必须保持一致的规则处理,约定 Modbus 传输中的데이터필드的바이트序。
답글 작성