Modbus-Funktionscode - vollständige Analyse: 21 Standard-Funktionscode - Handbuch von Grundlagen bis fortgeschritten
Schlüsselwörter:Modbus-Funktionscode, Modbus-Funktionscode, Modbus 01 02 03 04 05 06 15 16, Modbus-Leseregister, Modbus-Schreibspule
Der Funktionscode ist die Seele des Modbus-Protokolls. Es definiert, welche Aktionen der Master-Station an der Slave-Station ausführen soll - ob Daten gelesen oder geschrieben werden, ob die Aktionen gegen eine Spul, einen diskreten Eingang, ein Hold-Register oder ein Eingangsregister durchgeführt werden. Das Verständnis der Verwendung jedes Funktionscodes, des Nachrichtenformats und des Anwendungsszenarios ist der Grundstein für die Beherrschung der Modbus-Kommunikation.
Dieser Artikel basiert auf der Modbus-Protokollspezifikation V1.1b3 und analysiert systematisch alle 21 Standardfunktionen (einschließlich gemeinsamer, benutzerdefinierter und reservierter Funktionen) mit vollständigen Nachrichtenbeispielen und Programmierung, um Ihnen zu helfen, von einem „verständigen Ingenieur" zu einem „echten Experten zu verstehen".
1. Beziehung zwischen Modbus-Datenmodell und Funktionscode
Bevor Sie sich mit dem Funktionscode beschäftigen, müssen Sie das Modbus-Datenmodell verstehen. Modbus definiert vier Arten von Datenregionen:
| Datenbereich | Zugriffstyp | Größe | Adressbereich | Typische Verwendung |
|---|---|---|---|---|
| Spulen | Lesen und Schreiben | 1 bit | 00001-09999 | Digitale Ausgabe (DO) |
| Diskreite Eingabe | Lesenur | 1 bit | 10001-19999 | Digitale Eingabe (DI) |
| Haltenregister | Lese - und Schreiben | 16 bit | 40001-49999 | Analoge Ausgabe / Parameter |
| Eingangsregister | Lese-only | 16 - bit | 30001-39999 | Analoge Eingabe (AI) |
Wichtig:In der tatsächlichen Protokollnachricht wird eine "Protokolladresse" verwendet, die mit 0 beginnt. Zum Beispiel ist die Protokolladresse für das Haltregister 40001 0x0000. Dieses "Offset 1" - Design ist für Anfänger am leichtesten verwirrend.
II. Funktionale Klassifizierungssystem
Modbus-Funktionscode unterteilt sich in drei Hauptkategorien:
- Common Function Code (1 - 64, 73 - 99, 111 - 127):Definition von der Modbus-Organisation für Standardisierung zur Sicherstellung der Interoperabilität zwischen Geräten verschiedener Hersteller
- Benutzerdefinierter Funktionscode (65 - 72, 100 - 110):für die Anpassung von Geräteherstellern überlassen, nicht allgemein verbreitet
- Reservierung von Funktionscode:wurde von einigen Unternehmen in traditionellen Produkten (wie 8 - 11, 12 - 15 usw.)
Drei-Bit - Operations-Funktionscode (Bit-Access) Tiefe-Analyse
3.1 Funktionscode 0x01 - Lesespule (Read Coils)
Funktion:Lesen Sie den ON / OFF-Zustand der Dauerspule (DO) in der Station. Dies ist die grundlegendste Bit-Lesenoperation.
Anforderungsnachricht (RTU):
从站地址 | 0x01 | 起始地址高 | 起始地址低 | 数量高 | 数量低 | CRC
示例:读取从站 1 的线圈 0x0013~0x0037(20~56 号线圈,共 37 个)
01 01 00 13 00 25 [CRC]
→ 从站地址=1, 功能码=0x01, 起始地址=0x0013(19), 数量=0x0025(37)Response Message:
从站地址 | 0x01 | 字节数 | 数据... | CRC
01 01 05 CD 6B B2 0E 1B [CRC]
→ 5 个字节数据, CD=1100 1101 (线圈 27-20 的状态)Kritische Einschränkung:
- Bis zu 2000 Spulen gleichzeitig gelesen (0x07D0)
- Bit-Packing - Regeln in der Antwort: LSB des ersten Bytes entspricht der Startadresse-Spule
- Wenn die angeforderte Menge nicht ein Vielfaches von 8 ist, wird das höchste Bit des letzten Bytes mit 0 gefüllt
3.2 Funktionscode 0x02 - Read Discrete Inputs
Funktion:Lesen Sie den Zustand des kontinuierlichen diskreten Eingangs (DI) von der Station. Das Nachrichtenformat ist identisch mit 0x01, aber es handelt sich um einen diskreten Eingabebereich, der nur gelesen ist.
Unterschied zu 0x01:0x01 liest eine lesbare und schreibbare Spule (normalerweise entspricht dem physischen DO), während 0x02 einen diskreten Eingang liest (normalerweise entspricht dem physischen DI wie Limitschalter, Sensorstatus usw.).
示例:读取从站 1 的离散输入 0x00C4~0x00DB(197~220,共 24 个)
请求: 01 02 00 C4 00 18 [CRC]
响应: 01 02 03 AC DB 35 [CRC]
→ 3 个字节, AC=1010 1100, DB=1101 1011, 35=0011 01013.3 Funktionscode 0x05 - Single Coil schreiben
Funktion:Stellen Sie die einzelnen Spule auf ON oder OFF. Das ist der einfachste Schreibvorgang.
Nachricht angefordert:
从站地址 | 0x05 | 线圈地址高 | 线圈地址低 | 输出值高 | 输出值低 | CRC
输出值: 0xFF00 表示 ON, 0x0000 表示 OFF
示例:将从站 1 的线圈 0x00AC(173 号)置为 ON
01 05 00 AC FF 00 [CRC]Response Message:Die normale Antwort entspricht der Anforderung (Echo).
Programmierungsbeispiel (Python):
import minimalmodbus
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1)
instrument.serial.baudrate = 9600
# 写单个线圈: 地址 0x00AC = ON
instrument.write_bit(0x00AC, 1)3.4 Funktionscode 0x0F - Mehrfache Spulen schreiben
Funktion:Schreiben Sie mehrere aufeinanderfolgende Spulen auf einmal. Wenn mehrere DOs gleichzeitig gesteuert werden müssen, ist 0x0F viel effizienter als mehrere Aufrufe von 0x05.
请求报文格式:
从站地址 | 0x0F | 起始地址高 | 起始地址低 | 数量高 | 数量低 | 字节数 | 数据... | CRC
示例:将从站 1 的线圈 0x0013~0x001C(20~29,共 10 个线圈)分别置为:
20: ON, 21: OFF, 22: ON, 23: ON, 24: OFF, 25: ON, 26: ON, 27: OFF, 28: ON, 29: OFF
二进制: 01 0110 1101 → 高位补0 → 0xCD01... 等等这里需要仔细计算
实际报文: 01 0F 00 13 00 0A 02 CD 01 [CRC]16 - Bit-Access - Funktionscode (Register-Operation - Funktionscode)
4.1 Funktionscode 0x03 - Read Holding Registers
Funktion:Lesen Sie den Wert eines kontinuierlichen Registers. Dies ist einer der am häufigsten verwendeten Funktionscodes in Modbus, nicht. Fast alle Datenerfassungsszenarien verwenden 0x03.
请求报文格式:
从站地址 | 0x03 | 起始地址高 | 起始地址低 | 寄存器数量高 | 寄存器数量低 | CRC
示例:读取从站 1 的保持寄存器 0x006B~0x006D(108~110,共 3 个寄存器)
请求: 01 03 00 6B 00 03 [CRC]
响应: 01 03 06 02 2B 00 00 00 64 [CRC]
→ 6 个字节 = 3 个寄存器 × 2
→ 寄存器 108: 0x022B = 555
→ 寄存器 109: 0x0000 = 0
→ 寄存器 110: 0x0064 = 100Wichtige Einschränkungen:
- Bis zu 125 Registers pro Lese (0x007D)
- Wenn Sie 32 - Bit-Daten (float32/int32) lesen, stellen Sie sicher, dass die Anzahl der Registers gerade ist
- Byte-Sequenz - Problem: Verschiedene Geräte können das große oder kleines Ende verwenden, um mehrere Byte-Daten zu speichern
4.2 Funktionscode 0x04 - Eingaberegister lesen
Funktion:Lesen Sie den Wert eines kontinuierlichen Eingaberegisters. Das Format der Nachricht ist identisch mit 0x03, aber es arbeitet mit einem reinen Eingaberegisterbereich (z. B. ADC-Sampelwert, Sensor-Rohwert usw.).
示例:读取从站 1 的输入寄存器 0x0008(地址 9,AI 通道 1)
请求: 01 04 00 08 00 01 [CRC]
响应: 01 04 02 00 0A [CRC]
→ 输入寄存器 9 的值 = 0x000A = 104.3 Funktionscode 0x06 - Single Register schreiben
Funktion:Schreibt einen 16 - Bit-Wert in ein einzelnes Aufbewahrungsregister.
请求报文格式:
从站地址 | 0x06 | 寄存器地址高 | 寄存器地址低 | 写入值高 | 写入值低 | CRC
示例:将从站 1 的保持寄存器 0x0001 写入值 0x0003
请求: 01 06 00 01 00 03 [CRC]
响应: 01 06 00 01 00 03 [CRC](回显)Programmierungsbeispiele (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); // 从站1, 地址1, 值34.4 Funktionscode 0x10 - Schreiben mehrerer Register
Funktion:Schreiben Sie mehrere aufeinanderfolgende Register auf einmal. Es handelt sich dabei um ein effizientes Werkzeug für die Konfiguration von Parametern.
请求报文格式:
从站地址 | 0x10 | 起始地址高 | 起始地址低 | 寄存器数量高 | 寄存器数量低 | 字节数 | 数据... | CRC
示例:向从站 1 的寄存器 0x0001 和 0x0002 分别写入 0x000A 和 0x0102
请求: 01 10 00 01 00 02 04 00 0A 01 02 [CRC]
→ 字节数=4(2个寄存器×2)
响应: 01 10 00 01 00 02 [CRC]
→ 响应仅返回起始地址和寄存器数量Wichtige Einschränkungen:
- Maximal 123 Registers (0x007B) für ein einzelnes Schreiben
- Die Anzahl der Bytes muss gleich "Registerzahl x 2" sein
- Schreibfehler können zu Verwirrung der Slave-Station - Parameter führen, wird empfohlen, zuerst
zu sichern
5.1 Funktionscode 0x07 - Ausnahmezustand lesen
Funktion:Schnelle Lesung von 8 Ausnahme-Status - Bits von der Station. Dies ist ein einfacher, aber leistungsfähiger Diagnose-Funktionscode, die Nachricht nur 2 Byte (Adresse + Funktionscode) und die Antwort nur 3 Byte.
请求: 01 07 [CRC]
响应: 01 07 6D [CRC]
→ 状态字节 0x6D = 0110 1101,各厂商定义各 bit 含义5.2 Funktionscode 0x08 - Diagnose (Diagnose)
Funktion:Für die Diagnose der Kommunikationsverbindung mit insgesamt 16 Unterfunktionscodes. Die häufigste Verwendung ist der "Schleiftest" (Subfunktionscode 0x0000), um zu überprüfen, ob der Slave-Standort online ist und die Nachricht ordnungsgemäß verarbeitet.
| Subfunktionscode | Name | Verwendung |
|---|---|---|
| 0x0000 | Schleiftest | Echo-Anforderungsdaten, Überprüfung der Kommunikationsverbindung |
| 0x000A | Clear-Counter | Clear-Counter für Kommunikationsereignisse |
| 0x000B 0x000B | Lesen Busnachrichten | Lesen der Gesamtzahl der Busnachrichten, die von der Station erkannt wurden |
| 0x000C | Lesen der Anzahl der Kommunikationsfehler | Lesen der Anzahl der CRC-Verifizierungsfehler |
| 0x000D | Lesen der Anzahl der Ausnahmefehler | Lesen der Anzahl der Ausnahmeantworten, die von der Station zurückgegeben wurden |
| 0x000E | Lesen von Slave-Nachrichten | Lesen von Slave-Nachrichten, die vom Slave verarbeitet wurden |
| 0x000F | Lesen von Slave-Nachrichten, die nicht antworten | Lesen von Slave-Nachrichten, die aufgrund der Broadcast keine Antwort benötigt werden |
回路测试示例:
请求: 01 08 00 00 12 34 [CRC] → 子功能码=0x0000, 数据=0x1234
响应: 01 08 00 00 12 34 [CRC] → 必须完全回显请求数据5.3 Funktionscode 0x0B - Lesen von Kommunikationsereigniszählern
Gibt den Zähler von Kommunikationsereignissen und Statuswörtern von der Station zurück, um die Kommunikationsqualität zu überwachen.
5.4 Funktionscode 0x16 - Maske Schreibregister
Funktion:Verwenden Sie die AND-Maske und die OR-Maske für Bitoperationen in einzelnen Registeren. Dies ist einer der raffiniertesten Funktionscodes in Modbus - es ermöglicht es, bestimmte Bits eines Registers atomar zu ändern, ohne den aktuellen Wert zu lesen.
请求报文格式:
从站地址 | 0x16 | 地址高 | 地址低 | AND掩码高 | AND掩码低 | OR掩码高 | OR掩码低 | CRC
操作逻辑: Result = (Current_Value AND And_Mask) OR (Or_Mask AND (NOT And_Mask))
示例:将寄存器 0x0004 的 bit 0~3 清零,同时设置 bit 4~7 = 0b1010
AND掩码 = 0xFFF0(清除低4位), OR掩码 = 0x00A0(设置 bit5 和 bit7)
请求: 01 16 00 04 FF F0 00 A0 [CRC]6. Funktionscode im Vergleich zur Schnellüberprüfung
| Funktionscode | Name | Operationsobjekt | Typ Operationen | Die maximale Anzahl | Verwendungsfrequenz |
|---|---|---|---|---|---|
| 0x01 | Read Coils | Spule | 读 | 2000 | ★ ★ ★ ☆ |
| 0x02 | Read Discrete Inputs | Diskreter Eingang | 读 | 2000 | ★ ★ ☆ ☆ |
| 0x03 | Read Holding Registers | Haltenregister | 读 | 125 | ★ ★ ★ |
| 0x04 | Read Input Registers | Eingangsregister | 读 | 125 | ★ ★ ☆ |
| 0x05 | Write Single Coil | Spule | 写 | 1 | ★ ★ ★ ☆ ☆ |
| 0x06 | Write Single Register | Register behalten. | 写 | 1 | ★ ★ ★ ★ |
| 0x0f | Write Multiple Coils | Schleife | 写 | 1968 | ★ ★ ★ ☆ ☆ |
| 0x10 | Write Multiple Registers | Register behalten. | 写 | 123 | ★ ★ ★ ★ |
| 0x16 | Mask Write Register | Register behalten. | Lesen und schreiben | 1 | ★ ★ ☆ ☆ ☆ |
| 0x17 | Read/Write Multiple Regs | Register behalten. | Lesen und schreiben | 125/121 | ★ ★ ☆ ☆ ☆ |
7. Funktionscode Auswahl Entscheidungsbaum
In der praktischen Entwicklung ist die Auswahl des richtigen Code-Codes eine entscheidende Entscheidung. Hier ist der Auswahlentscheidungsprozess:
- Muss der Ausgabezustand der numerischen Größen ausgelesen werden?→ 0x01 (Spule) / 0x02 (diskreter Eingang)
- Benötigen Sie analoge Größe oder Parameter?→ 0x03 (Halt-Register) / 0x04 (Eingangsregister)
- Muss ein einzelner digitaler Ausgang festgelegt werden?→ 0x05
- Benötigen Sie eine einzelne Parameter?→ 0x06
- Benötigen Sie eine Massen-Einstellung von Parametern?→ 0x10
- Benötigen Sie eine Massen-Einstellung für den digitalen Ausgang?→ 0x0F
- Muss manche Bits des Parameters ändern, ohne die anderen Bits zu beeinflussen?→ 0x16
- Benötigt gleichzeitiges Lesen und Schreiben (z. B. das Lesen von alten Parametern und das Schreiben neuer Parameter)?→ 0x17
VIII. Häufige Fallen und Best Practices
8.1 Byte-Sequenz - Fallen
Das Modbus-Protokoll schreibt die Verwendung von Big-Endian für 16 - Bit-Register vor, aber die Byte-Sequenz für 32 - Bit-Daten (wie float32) ist nicht auf Protokollsebene festgelegt. Es gibt üblicherweise vier Arten von Anordnung:
| Anordnung | Register 1 | Register 2 | Häufige Hersteller |
|---|---|---|---|
| ABCD (Big-Endian) | Hohe 16 - Bit | Niedrig 16 - Bit | Schneider, ABB |
| CDAB (Little-Endian) | 16 - bit niedrig | 16 - bit hoch | Siemens S7 - 200 |
| BADC (Word-Swap Big) | Byte-Switch | - | Einige inländische Marken |
| DCBA (Word-Swap Little) | vollständig umgekehrt | - | wenige spezielle Geräte |
8.2 Broadcast-Adresse (Adresse 0)
Im RTU-Modus wird die Ausstrahlung mit der Slave-Adresse 0 angegeben - alle Slaves führen Befehle aus, aber keine Antwort zurück. Nur Schreibfunktionscodes (0x05, 0x06, 0x0F, 0x10) unterstützen Broadcasting.
8.3 Nicht zu viele Register pro Anfrage
Obwohl die Spezifikation 0x03 125 Registers auf einmal liest, wird es nicht empfohlen, zu viele auf einmal zu lesen. Ursache:
- Erhöhung der Kommunikationsverzögerung (ca. 270 ms bei 125 Registeren bei 9600 Baudrate)
- Erhöhung der Wahrscheinlichkeit von Fehlern bei der CRC-Prüfung
- Speicherbeschränkungen in teilweise Slave-Stationen können zu Pufferüberflüssen führen
Empfehlung:Einzige Lesekontrolle innerhalb von 20 bis 50 Registers, unterteilt in mehrere kleine Lese-Lösungen.
9. Praxisbeispiel: Aufbau eines Modbus-Datenerfassungssystems
Hier ist ein typischer Modbus-Datenerfassungsprozess, der zeigt, wie verschiedene Funktionscodes kombiniert werden können:
// C 语言伪代码 - 典型 Modbus 采集流程
void modbus_acquisition_task(void) {
// 步骤 1: 读取设备状态(离散输入)
uint8_t di_data[2];
modbus_read_inputs(0x02, &di_data, 16); // 读16个DI
// 步骤 2: 读取模拟量(输入寄存器)
uint16_t ai_data[8];
modbus_read_input_regs(0x00, &ai_data, 8); // 读8个AI通道
// 步骤 3: 读取运行参数(保持寄存器)
uint16_t params[20];
modbus_read_holding_regs(0x00, ¶ms, 20);
// 步骤 4: 根据业务逻辑写入控制命令
if (need_start_motor) {
modbus_write_coil(0x0005, 1); // 启动电机
}
// 步骤 5: 如果需要修改参数
if (need_set_temp) {
modbus_write_register(0x0010, 250); // 设定温度 25.0°C
}
}X. Zusammenfassung
Der Funktionscode ist das „Verb" des Modbus-Protokolls - es definiert, was der Master mit dem Slave macht. Die Beherrschung des Nachrichtenformats und des anwendbaren Szenarios des Funktionscodes bedeutet, die Kernsyntax der Modbus-Kommunikation zu meistern. Es wird empfohlen, die Funktionscode-Quickcheck - Tabelle und den Entscheidungsbaum in diesem Artikel als Referenzhandbuch für die tägliche Entwicklung zu verwenden, um das Verständnis in der tatsächlichen Debugging schrittweise zu vertiefen.
Im nächsten Artikel werden wir die Unterschiede zwischen Modbus RTU und Modbus TCP vertieft vergleichen und die anwendbaren Szenarien und Leistungsmerkmale von der physischen bis zur Anwendungsebene umfassend analysieren.
Relative Lesung:Vollständiges Handbuch zur Modbus-Ausnahme - Antwortcode - und Fehlerbehebung| Modbus RTU im Vergleich zu TCP| Modbus CRC-Prüfung und - Implementierung
Antwort veröffentlichen