- 1. 一、Modbus Daten模型与Funktionscode的关系
- 2. 二、FunktionscodeKlassifizierung体系
- 3. 三、位OperationenFunktionscode(Bit Access)深度Analyse
- 4. 3.1 Funktionscode 0x01 — 读线圈(Read Coils)
- 5. 3.2 Funktionscode 0x02 — Lesen Sie getrennte Eingabe(Read Discrete Inputs)
- 6. 3.3 Funktionscode 0x05 — Schreiben Sie eine einzelne Schleife.(Write Single Coil)
- 7. 3.4 Funktionscode 0x0F — Schreiben Sie mehrere Schleife.(Write Multiple Coils)
- 8. 四、Register.OperationenFunktionscode(16-bit Access)深度Analyse
- 9. 4.1 Funktionscode 0x03 — Lesen Sie das Register(Read Holding Registers)
- 10. 4.2 Funktionscode 0x04 — Eingangsregister lesen(Read Input Registers)
- 11. 4.3 Funktionscode 0x06 — Schreiben eines einzelnen Registers(Write Single Register)
- 12. 4.4 Funktionscode 0x10 — Schreiben mehrerer Register(Write Multiple Registers)
- 13. 五、高级Funktionscode ausführlich
- 14. 5.1 Funktionscode 0x07 — 读异常Status(Read Exception Status)
- 15. 5.2 Funktionscode 0x08 — 诊断(Diagnostics)
- 16. 5.3 Funktionscode 0x0B — 读KommunikationEreignisse计数器
- 17. 5.4 Funktionscode 0x16 — 掩码写Register.(Mask Write Register)
- 18. 六、Funktionscode对比速查表
- 19. 七、FunktionscodeAuswahl决策树
- 20. 八、Häufig陷阱与最佳实践
- 21. 8.1 Byte序陷阱
- 22. 8.2 RundfunkAdresse(Adresse 0)
- 23. 8.3 一次Bitte勿贪多
- 24. 九、实际案例:构建 Modbus DatenerfassungDas System
- 25. 十、总结
Modbus Funktionscode完全Analyse:从基础zu进阶的 21 个标准Funktionscode实战指南
关键词:Modbus Funktionscode、Modbus Function Code、Modbus 01 02 03 04 05 06 15 16、Modbus 读Register.、Modbus 写线圈
Funktionscode(Function Code)是 Das Modbus-Protokoll的灵魂。它定义了Hauptstation要对Von der Station执行的Operationen——是Daten lesen还是写入Daten,Operationen的对象是线圈、离散输入、保持Register.还是输入Register.。理解每一个Funktionscode的用途、MeldungDas Format和适用Szene,是精通 Modbus Kommunikation的基石。
本文以 Modbus-Protokollspezifikation V1.1b3 为蓝本,Das System化地AnalyseAlles 21 个标准Funktionscode(包括公共Funktionscode、用户定义Funktionscode和保留Funktionscode),并配以vollständig的MeldungBeispiel和编程实现,帮助您从「会用的工程师」进阶为「真正理解的专家」。
一、Modbus Daten模型与Funktionscode的关系
在深入Funktionscode之前,必须先理解 Modbus 的Daten模型。Modbus 定义了四种Datenzone域:
| Datenzone域 | 访问Typus | 大小 | Adresse范围 | 典型用途 |
|---|---|---|---|---|
| 线圈(Coils) | 读写 | 1 bit | 00001-09999 | 数字Quantität输出(DO) |
| 离散输入(Discrete Inputs) | 只读 | 1 bit | 10001-19999 | 数字Quantität输入(DI) |
| 保持Register.(Holding Registers) | 读写 | 16 bit | 40001-49999 | 模拟Quantität输出/Parameter |
| 输入Register.(Input Registers) | 只读 | 16 bit | 30001-39999 | 模拟Quantität输入(AI) |
重要提示:在实际VereinbarungMeldung中,使用的是从 0 开始的「VereinbarungAdresse」。例如,保持Register. 40001 对应的VereinbarungAdresse是 0x0000。这个「偏移 1」的设计是初学者最容易混淆的地方。
二、FunktionscodeKlassifizierung体系
Modbus FunktionscodeUnterteilung为三大类:
- 公共Funktionscode(1-64, 73-99, 111-127):由 Modbus 组织标准化定义,确保不同厂商Ausrüstung之间的互Operationen性
- 用户定义Funktionscode(65-72, 100-110):留给Ausrüstung厂商Custom definiert实现,不具备通用性
- 保留Funktionscode:已被某些Unternehmen用于传统产品(如 8-11, 12-15 等)
三、位OperationenFunktionscode(Bit Access)深度Analyse
3.1 Funktionscode 0x01 — 读线圈(Read Coils)
Funktion:LesenVon der Station中连续线圈(DO)的 ON/OFF Status。这是最基本的位LesenOperationen。
BitteMeldung(RTU):
von der Station Adresse | 0x01 | Ausgang Adresse高 | Ausgang Adresse低 | Anzahl高 | Anzahl低 | CRC
Beispiel:LesenVon der Station 1 的线圈 0x0013~0x0037(20~56 Nr.线圈,共 37 个)
01 01 00 13 00 25 [CRC]
→ von der Station Adresse=1, Funktionscode=0x01, Ausgang Adresse=0x0013(19), Anzahl=0x0025(37)
AntwortMeldung:
von der Station Adresse | 0x01 | Anzahl der Bytes | Daten... | CRC
01 01 05 CD 6B B2 0E 1B [CRC]
→ 5 个Anzahl der Bytes据, CD=1100 1101 (线圈 27-20 的Status)
关键约束:
- 单次最多Lesen 2000 个线圈(0x07D0)
- Antwort中的位打包Regeln:Die一个Bytes的 LSB 对应Ausgang Adresse线圈
- 如果Bitte的Anzahl不是 8 的倍数,最后一个Bytes的高位用 0 填充
3.2 Funktionscode 0x02 — Lesen Sie getrennte Eingabe(Read Discrete Inputs)
Funktion:LesenVon der Station中连续离散输入(DI)的Status。MeldungDas Format与 0x01 完全相同,但Operationen的是只读的离散输入区。
与 0x01 的区别:0x01 Lesen的是可读写的线圈(通常对应物理 DO),而 0x02 Lesen的是只读的离散输入(通常对应物理 DI 如限位Schalter!、Der SensorStatus等)。
Beispiel:LesenVon der Station 1 的离散输入 0x00C4~0x00DB(197~220,共 24 个)
Bitte: 01 02 00 C4 00 18 [CRC]
Antwort: 01 02 03 AC DB 35 [CRC]
→ 3 个Bytes, AC=1010 1100, DB=1101 1011, 35=0011 0101
3.3 Funktionscode 0x05 — Schreiben Sie eine einzelne Schleife.(Write Single Coil)
Funktion:将单个线圈设置为 ON 或 OFF。这是最简单的写Operationen。
BitteMeldung:
von der Station Adresse | 0x05 | Schleife Adresse高 | Schleife Adresse低 | 输出值高 | 输出值低 | CRC
输出值: 0xFF00 表示 ON, 0x0000 表示 OFF
Beispiel:将Von der Station 1 的线圈 0x00AC(173 Nr.)置为 ON
01 05 00 AC FF 00 [CRC]
AntwortMeldung:正常Antwort与Bitte完全一致(回显)。
编程Beispiel(Python):
import minimalmodbus
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1)
instrument.serial.baudrate = 9600
# Schreiben Sie eine einzelne Schleife.: Adresse 0x00AC = ON
instrument.write_bit(0x00AC, 1)
3.4 Funktionscode 0x0F — Schreiben Sie mehrere Schleife.(Write Multiple Coils)
Funktion:一次性写入多个连续线圈。当需要同时控制多个 DO 时,0x0F 比多次调用 0x05 高效得多。
BitteMeldungDas Format:
von der Station Adresse | 0x0F | Ausgang Adresse高 | Ausgang Adresse低 | Anzahl高 | Anzahl低 | Anzahl der Bytes | Daten... | CRC
Beispiel:将Von der Station 1 的线圈 0x0013~0x001C(20~29,共 10 个线圈)Unterteilung别置为:
20: ON, 21: OFF, 22: ON, 23: ON, 24: OFF, 25: ON, 26: ON, 27: OFF, 28: ON, 29: OFF
Binärsystem: 01 0110 1101 → 高位补0 → 0xCD01... 等等这里需要仔细Berechnung
实际Meldung: 01 0F 00 13 00 0A 02 CD 01 [CRC]
四、Register.OperationenFunktionscode(16-bit Access)深度Analyse
4.1 Funktionscode 0x03 — Lesen Sie das Register(Read Holding Registers)
Funktion:Lesen连续保持Register.的值。这是 Modbus 中使用频率最高的Funktionscode,没有之一。几乎所有DatenerfassungSzene都使用 0x03。
BitteMeldungDas Format:
von der Station Adresse | 0x03 | Ausgang Adresse高 | Ausgang Adresse低 | Anzahl der Register高 | Anzahl der Register低 | CRC
Beispiel:LesenVon der Station 1 的保持Register. 0x006B~0x006D(108~110,共 3 ein Register.)
Bitte: 01 03 00 6B 00 03 [CRC]
Antwort: 01 03 06 02 2B 00 00 00 64 [CRC]
→ 6 个Bytes = 3 ein Register. × 2
→ Register. 108: 0x022B = 555
→ Register. 109: 0x0000 = 0
→ Register. 110: 0x0064 = 100
关键约束:
- 单次最多Lesen 125 ein Register.(0x007D)
- 如果Lesen 32 位Daten(float32/int32),确保Anzahl der Register为偶数
- Befehlseite问题:不同Ausrüstung可能使用大端或小端存储多Anzahl der Bytes据
4.2 Funktionscode 0x04 — Eingangsregister lesen(Read Input Registers)
Funktion:Lesen连续输入Register.的值。MeldungDas Format与 0x03 完全相同,但Operationen的是只读的输入Register.区(如 ADC 采样值、Der Sensor原始值等)。
Beispiel:LesenVon der Station 1 的输入Register. 0x0008(Adresse 9,AI 通道 1)
Bitte: 01 04 00 08 00 01 [CRC]
Antwort: 01 04 02 00 0A [CRC]
→ 输入Register. 9 的值 = 0x000A = 10
4.3 Funktionscode 0x06 — Schreiben eines einzelnen Registers(Write Single Register)
Funktion:向单个保持Register.写入 16 位Zahlenwert。
BitteMeldungDas Format:
von der Station Adresse | 0x06 | Register-Adresse高 | Register-Adresse低 | Schreiben Sie Wert高 | Schreiben Sie Wert低 | CRC
Beispiel:将Von der Station 1 的保持Register. 0x0001 Schreiben Sie Wert 0x0003
Bitte: 01 06 00 01 00 03 [CRC]
Antwort: 01 06 00 01 00 03 [CRC](回显)
编程Beispiel(C#):
// 使用 NModbus4 库
using Modbus.Device;
using System.IO.Ports;
var port = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
port.Open();
var master = ModbusSerialMaster.CreateRtu(port);
master.WriteSingleRegister(1, 0x0001, 3); // Von der Station1, Adresse1, 值3
4.4 Funktionscode 0x10 — Schreiben mehrerer Register(Write Multiple Registers)
Funktion:一次性写入多个连续保持Register.。这是批Quantität配置Parameter的效率利器。
BitteMeldungDas Format:
von der Station Adresse | 0x10 | Ausgang Adresse高 | Ausgang Adresse低 | Anzahl der Register高 | Anzahl der Register低 | Anzahl der Bytes | Daten... | CRC
Beispiel:向Von der Station 1 的Register. 0x0001 和 0x0002 Unterteilung别写入 0x000A 和 0x0102
Bitte: 01 10 00 01 00 02 04 00 0A 01 02 [CRC]
→ Anzahl der Bytes=4(2ein Register.×2)
Antwort: 01 10 00 01 00 02 [CRC]
→ Antwort仅返回Ausgang Adresse和Anzahl der Register
关键约束:
- 单次最多写入 123 ein Register.(0x007B)
- Anzahl der Bytes必须gleich ist「Anzahl der Register × 2」
- 写入失败可能导致Von der StationParameter混乱,建议先备份
五、高级Funktionscode ausführlich
5.1 Funktionscode 0x07 — 读异常Status(Read Exception Status)
Funktion:快速LesenVon der Station的 8 个异常Status位。这是一个简单但强大的诊断Funktionscode,BitteMeldung只有 2 个Bytes(Adresse+Funktionscode),Antwort也只有 3 个Bytes。
Bitte: 01 07 [CRC]
Antwort: 01 07 6D [CRC]
→ Zustand Bytes 0x6D = 0110 1101,各厂商定义各 bit 含义
5.2 Funktionscode 0x08 — 诊断(Diagnostics)
Funktion:用于Kommunikation链路诊断,共有 16 个子Funktionscode。最Häufig的用途是「回路测试」(子Funktionscode 0x0000),用来检测Von der Station是否在线并能正常处理Meldung。
| 子Funktionscode | Name | 用途 |
|---|---|---|
| 0x0000 | 回路测试 | 回显BitteDaten,验证Kommunikation链路 |
| 0x000A | 清计数器 | 清零KommunikationEreignisse计数器 |
| 0x000B | 读总线消息计数 | LesenVon der Station检测zu的总线消息总数 |
| 0x000C | 读KommunikationFehler zählen | Lesen CRC-PrüfungFehler.次数 |
| 0x000D | 读异常Fehler zählen | LesenVon der Station返回的Ungewöhnliche Reaktion次数 |
| 0x000E | 读Von der Station消息计数 | LesenVon der Station已处理的消息数 |
| 0x000F | 读Von der Station无Antwort计数 | Lesen因Rundfunk而无需Antwort的消息数 |
回路测试Beispiel:
Bitte: 01 08 00 00 12 34 [CRC] → 子Funktionscode=0x0000, Daten=0x1234
Antwort: 01 08 00 00 12 34 [CRC] → 必须完全回显BitteDaten
5.3 Funktionscode 0x0B — 读KommunikationEreignisse计数器
返回Von der Station的KommunikationEreignisse计数器和Status字,用于监控Kommunikation质Quantität。
5.4 Funktionscode 0x16 — 掩码写Register.(Mask Write Register)
Funktion:使用 AND 掩码和 OR 掩码对单ein Register.进行位Operationen。这是 Modbus 中最巧妙的Funktionscode之一——它允许在不LesenDer aktuelle Wert的情况下,原子性地修改Register.的特定位。
BitteMeldungDas Format:
von der Station Adresse | 0x16 | Adresse高 | Adresse低 | AND掩码高 | AND掩码低 | OR掩码高 | OR掩码低 | CRC
Operationen逻辑: Result = (Current_Value AND And_Mask) OR (Or_Mask AND (NOT And_Mask))
Beispiel:将Register. 0x0004 的 bit 0~3 清零,同时设置 bit 4~7 = 0b1010
AND掩码 = 0xFFF0(Beseitigung低4位), OR掩码 = 0x00A0(设置 bit5 和 bit7)
Bitte: 01 16 00 04 FF F0 00 A0 [CRC]
六、Funktionscode对比速查表
| Funktionscode | Name | Operationen对象 | OperationenTypus | 最多Anzahl | 使用频率 |
|---|---|---|---|---|---|
| 0x01 | Read Coils | 线圈 | 读 | 2000 | ★★★★☆ |
| 0x02 | Read Discrete Inputs | 离散输入 | 读 | 2000 | ★★★☆☆ |
| 0x03 | Read Holding Registers | 保持Register. | 读 | 125 | ★★★★★ |
| 0x04 | Read Input Registers | 输入Register. | 读 | 125 | ★★★★☆ |
| 0x05 | Write Single Coil | 线圈 | 写 | 1 | ★★★☆☆ |
| 0x06 | Write Single Register | 保持Register. | 写 | 1 | ★★★★★ |
| 0x0F | Write Multiple Coils | 线圈 | 写 | 1968 | ★★★☆☆ |
| 0x10 | Write Multiple Registers | 保持Register. | 写 | 123 | ★★★★★ |
| 0x16 | Mask Write Register | 保持Register. | 读写 | 1 | ★★☆☆☆ |
| 0x17 | Read/Write Multiple Regs | 保持Register. | 读写 | 125/121 | ★★☆☆☆ |
七、FunktionscodeAuswahl决策树
在实际开发中,Auswahl合适的功码码是关键决策。以下是Auswahl决策流程:
- 需要Lesen数字Quantität输出Status? → 0x01(线圈)/ 0x02(离散输入)
- 需要Lesen模拟Quantität或Parameter? → 0x03(保持Register.)/ 0x04(输入Register.)
- 需要设置单个数字Quantität输出? → 0x05
- 需要设置单Parameter? → 0x06
- 需要批Quantität设置Parameter? → 0x10
- 需要批Quantität设置数字Quantität输出? → 0x0F
- 需要修改Parameter的某些位而不影响其他位? → 0x16
- 需要同时读写(如Lesen旧Parameter并写入新Parameter原子Operationen)? → 0x17
八、Häufig陷阱与最佳实践
8.1 Byte序陷阱
Das Modbus-Protokoll规定 16 位Register.使用大端Befehlseite(Big-Endian),但 32 位Daten(如 float32)的Befehlseite在Vereinbarung层面没有规定。Häufig的有四种排列方式:
| 排列方式 | Register. 1 | Register. 2 | Häufig厂商 |
|---|---|---|---|
| ABCD (Big-Endian) | 高16位 | 低16位 | 施耐德、ABB |
| CDAB (Little-Endian) | 低16位 | 高16位 | 西门子 S7-200 |
| BADC (Word-Swap Big) | Bytes交换 | – | 部Unterteilung国产品牌 |
| DCBA (Word-Swap Little) | 完全颠倒 | – | 少数特殊Ausrüstung |
8.2 RundfunkAdresse(Adresse 0)
在 RTU 模式下,使用von der Station Adresse 0 表示Rundfunk——所有Von der Station都执行Befehl,但都不Zurück zur Antwort。只有写OperationenFunktionscode(0x05, 0x06, 0x0F, 0x10)支持Rundfunk。
8.3 一次Bitte勿贪多
虽然规范允许 0x03 一次Lesen 125 ein Register.,但不建议一次Lesen太多。原因:
- 增大Kommunikation延迟(Porter Rate 9600 时,125 ein Register.需要约 270ms)
- 增加 CRC-Prüfung出错的概率
- 部UnterteilungVon der Station的内存限制可能导致缓冲区溢出
建议:单次Lesen控制在 20~50 ein Register.以内,Unterteilung为多个小批次Lesen。
九、实际案例:构建 Modbus DatenerfassungDas System
以下是一个典型的 Modbus Datenerfassung流程,展示了如何组合使用不同的Funktionscode:
// C 语言伪代码 - 典型 Modbus 采集流程
void modbus_acquisition_task(void) {
// 步骤 1: LesenAusrüstungStatus(离散输入)
uint8_t di_data[2];
modbus_read_inputs(0x02, &di_data, 16); // 读16个DI
// 步骤 2: Lesen模拟Quantität(输入Register.)
uint16_t ai_data[8];
modbus_read_input_regs(0x00, &ai_data, 8); // 读8个AI通道
// 步骤 3: LesenBetriebParameter(保持Register.)
uint16_t params[20];
modbus_read_holding_regs(0x00, ¶ms, 20);
// 步骤 4: 根据业务逻辑写入控制Befehl
if (need_start_motor) {
modbus_write_coil(0x0005, 1); // 启动Elektrische Motoren
}
// 步骤 5: 如果需要修改Parameter
if (need_set_temp) {
modbus_write_register(0x0010, 250); // 设定Temperatur 25.0°C
}
}
十、总结
Funktionscode是 Das Modbus-Protokoll的「动词」——它定义了Hauptstation对Von der Station做什么Operationen。掌握了Funktionscode的MeldungDas Format和适用Szene,就gleich ist掌握了 Modbus Kommunikation的核心语法。建议将本文的Funktions-Schnellüberprüfung和决策树作为日常开发的参考手册,在实际Tests中逐步加深理解。
在Nächster Artikel中,我们将深入对比 Modbus RTU 和 Modbus TCP 两种传输模式的schlecht异,从物理层zu应用层全面Analyse两者的适用Szene和性能特点。
Related阅读:Modbus Ungewöhnliche Reaktion码与故障排查完全手册 | Modbus RTU 与 TCP 深度对比 | Modbus CRC-Prüfung原理与编程实现
Antwort veröffentlichen