Modbus Funktionscodes erklärt: vollständige Referenz für Installateure 2026
Modbus Funktionscodes erklärt für Installateure. Read Holding Registers (0x03), Write Multiple (0x10), Exception Codes und die 40001 vs 0x0000 Falle.

Modbus Funktionscodes sagen jedem Slave auf dem Bus, was der Master will: lesen oder schreiben, ein Bit oder ein 16-Bit-Register, eine Adresse oder einen Block. Wer die Codes auswendig kennt, liest einen Wireshark-Trace direkt und erkennt bei einer Exception Response in fünf Sekunden, woran es liegt. Wer das nicht kennt, verliert bei jeder Störung eine Stunde.
Dieser Artikel gibt Ihnen die vollständige Funktionscode-Liste, die Byte-Beispiele, die Sie an einem Eastron SDM630 oder einer Wago 750-Steuerung tatsächlich sehen, und den Unterschied zwischen Funktionscode 0x03 und der Legacy-Adresse "40001" aus alten PLC-Handbüchern. Gedacht für Installateure, nicht für Protokoll-Entwickler.
Key Takeaways
- Modbus hat vier Registertypen (Coils, Discrete Inputs, Holding Registers, Input Registers) und neun verbreitete Funktionscodes, die eins zu eins darauf mappen.
- Funktionscode 0x03 (Read Holding Registers) und 0x10 (Write Multiple Registers) decken zusammen rund 80 Prozent des Verkehrs in HLK und Kältetechnik ab.
- Eine Exception Response hat denselben Funktionscode wie der Request, aber mit Bit 7 auf 1 gesetzt: aus 0x03 wird 0x83.
Was ist ein Modbus Funktionscode genau?
Ein Modbus Funktionscode ist ein 1-Byte-Feld in jedem Modbus-Frame, das angibt, welche Operation der Master verlangt und welche Registerklasse er anspricht. Der Code steht immer direkt nach der Slave-Adresse (RTU) oder nach dem MBAP-Header (TCP), wie in der Modbus Application Protocol Specification V1.1b3 der Modbus Organization beschrieben.
Funktionscodes sind nicht dasselbe wie Registeradressen. Der Funktionscode sagt, WAS Sie tun (lesen oder schreiben, einzeln oder mehrere, Bit oder Wort), die Registeradresse sagt, WO. Diese Unterscheidung wird von Einsteigern in die Modbus-Welt am häufigsten übersehen. Für den breiteren Kontext des Protokolls siehe unseren kompletten Modbus-Leitfaden und die Modbus RTU Erklärung für den Frame-Aufbau.
In der Praxis gibt es zwei Gruppen von Funktionscodes: die öffentlichen Codes (zugewiesen von Modbus.org, in der Spezifikation dokumentiert), und die User-Defined Codes im Bereich 0x41 bis 0x48 und 0x64 bis 0x6E, die Hersteller selbst belegen dürfen. Für 99 Prozent der Arbeit in HLK, Energiemessung und Kältetechnik brauchen Sie nur die erste Gruppe.
Die vier Registertypen und ihre Funktionscodes
Modbus organisiert Speicher in vier Registertypen. Jeder Typ hat einen Lesecode und, sofern beschreibbar, zwei Schreibcodes (einen für einzelne, einen für mehrere). Neun Funktionscodes mappen auf dieses Raster:
Coils sind 1-Bit-Werte, die Sie lesen und schreiben können. Beispiel: der Zustand eines Relais oder eines digitalen Ausgangs. Read Coils nutzt 0x01, Write Single Coil 0x05, Write Multiple Coils 0x0F.
Discrete Inputs sind 1-Bit-Werte, die nur lesbar sind. Eingänge eines Druckschalters oder eines Endschalters fallen darunter. Read Discrete Inputs nutzt 0x02. Einen Schreibcode dafür gibt es nicht, denn es ist per Definition ein Input.
Holding Register sind 16-Bit-Werte, die Sie lesen und schreiben können. Hier steckt die meiste Arbeit in HLK und Kältetechnik: Sollwerte, Konfigurationswerte, Modus-Auswahl. Read Holding Registers nutzt 0x03, Write Single Holding Register 0x06, Write Multiple 0x10.
Input Register sind 16-Bit-Werte, die nur lesbar sind. Messwerte wie Temperaturen, Drücke, Leistungen und Energiezähler. Read Input Registers nutzt 0x04. Wie bei Discrete Inputs gibt es keinen Schreibcode.
In der Praxis nutzen viele Hersteller nur Holding Register, auch für Messwerte, weil das die Toolchain vereinfacht. Ein Eastron SDM630 legt sowohl Konfiguration als auch Messwerte in Holding Register (0x03), während ein Carel pCO Kälteregler die volle Unterscheidung zwischen Holding und Input Register respektiert.
Die neun Funktionscodes, die Sie wirklich brauchen
Unter den 19 öffentlichen Funktionscodes der Modbus-Spezifikation gibt es neun, die Sie täglich sehen. Die anderen zehn sind vor allem RTU-Bus-Diagnose (0x07, 0x08, 0x0B, 0x0C, 0x11) oder File-Record-Operationen (0x14, 0x15), die in modernen Installationen selten vorkommen.
| Funktionscode | Name | Anwendung | Häufigkeit |
|---|---|---|---|
| 0x01 | Read Coils | Status digitaler Ausgänge lesen | mittel |
| 0x02 | Read Discrete Inputs | Status digitaler Eingänge lesen | mittel |
| 0x03 | Read Holding Registers | Sollwerte, Konfiguration, Messwerte | sehr hoch |
| 0x04 | Read Input Registers | Read-only Messwerte | hoch |
| 0x05 | Write Single Coil | Ein Relais an oder aus | mittel |
| 0x06 | Write Single Holding Register | Ein Sollwert oder Konfigurationswert | hoch |
| 0x0F | Write Multiple Coils | Mehrere Relais in einem Frame | niedrig |
| 0x10 | Write Multiple Holding Registers | Sollwert-Blöcke atomar schreiben | hoch |
| 0x17 | Read/Write Multiple Registers | Lesen und Schreiben in einer Transaktion | niedrig |
Funktionscodes 0x03 und 0x10 sehen Sie am häufigsten. 0x03, weil es der generische "lies Daten von diesem Gerät" Aufruf ist; 0x10, weil alle modernen Integrationstools (Home Assistant, Node-RED, PLCs) FC 16 bevorzugen, auch für ein einzelnes Register, da das Programmiermodell einfacher ist.
Funktionscode 0x03 im Detail: Holding Register lesen
Funktionscode 0x03 ist mit Abstand der meistgenutzte Code in einer Installation. Ein Leserequest auf Holding Register besteht aus sechs Bytes Daten (nach der Slave-Adresse):
| Byte-Position | Feld | Beispielwert |
|---|---|---|
| 1 | Slave-Adresse | 0x01 |
| 2 | Funktionscode | 0x03 |
| 3 bis 4 | Start-Registeradresse | 0x0000 (= Register 0) |
| 5 bis 6 | Anzahl Register | 0x000A (= 10 Register) |
| 7 bis 8 | CRC-16 | (berechnet über Bytes 1 bis 6) |
Ein konkretes Beispiel: Master fragt Slave 1 nach den ersten 10 Holding Registern (0 bis 9):
01 03 00 00 00 0A C5 CD
Der Slave antwortet mit der Slave-Adresse, demselben Funktionscode, einem Byte Byte-Count (Anzahl Datenbytes, 2x Anzahl Register), den Registerwerten und der CRC:
01 03 14 00 64 00 C8 01 2C ... C5 7B
Bytes 1 bis 3 sind Header: Slave-Adresse 0x01, Funktionscode 0x03, Byte-Count 0x14 (= 20 Datenbytes, 10 Register x 2). Danach folgen 20 Datenbytes mit den Werten und 2 Bytes CRC.
Exception Responses: was ein 0x83 im Log bedeutet
Wenn ein Slave einen Request nicht ausführen kann, antwortet er nicht mit einem neuen Funktionscode, sondern mit demselben Funktionscode, bei dem Bit 7 (MSB) auf 1 gesetzt ist. Aus Funktionscode 0x03 (Read Holding Registers) wird in der Exception Response 0x83. Aus 0x10 (Write Multiple) wird 0x90. Bit 7 zu setzen entspricht einer OR-Verknüpfung mit 0x80 (binär 1000 0000).
Nach dem Exception-Funktionscode folgt ein Byte Exception Code, der sagt, WARUM der Request fehlgeschlagen ist. Die vollständige Exception Response umfasst also immer fünf Bytes (RTU): Slave-Adresse, Exception-Funktionscode, Exception Code und 2 Bytes CRC. Bei Modbus TCP sind es nach dem MBAP-Header sieben Bytes.
Die Modbus Application Protocol Specification V1.1b3, Abschnitt 7, definiert neun Standard-Exception-Codes:
| Exception Code | Name | Bedeutung in der Praxis |
|---|---|---|
| 0x01 | Illegal Function | Slave unterstützt diesen FC nicht (versuchen Sie 0x10 statt 0x06) |
| 0x02 | Illegal Data Address | Adresse existiert auf diesem Slave nicht (Off-by-one HMI vs Wire) |
| 0x03 | Illegal Data Value | Wert oder Registeranzahl außerhalb des erlaubten Bereichs |
| 0x04 | Slave Device Failure | Hardware-Problem im Slave (Sensor defekt, Speicher korrupt) |
| 0x05 | Acknowledge | Slave verarbeitet, später erneut mit Poll-Status anfragen |
| 0x06 | Slave Device Busy | Slave in Selbsttest oder Firmware-Update, warten und erneut versuchen |
| 0x08 | Memory Parity Error | File-Record Speicherfehler (in HLK selten) |
| 0x0A | Gateway Path Unavailable | Modbus-Gateway erreicht Target-Slave nicht (Kabel ab, Slave aus) |
| 0x0B | Gateway Target Failed to Respond | Target-Slave antwortet nicht im Timeout (falsche Slave-ID) |
Ein konkretes Exception-Beispiel: Master fragt Slave 1 nach Holding Register 0x0064 (= 100), aber der Slave hat nur 64 Register. Der Slave antwortet:
01 83 02 C0 F1
Slave-Adresse 0x01, Funktionscode 0x83 (= 0x03 + Bit 7), Exception Code 0x02 (Illegal Data Address), CRC 0xC0F1. Ein Logger, der "Funktionscode 131" anzeigt, hat technisch Recht, aber es ist klarer, dies als "FC 0x03, Exception Code 0x02" zu lesen.
Die 40001-Falle: 1-basierte versus 0-basierte Adressierung
Eines der hartnäckigsten Probleme bei Modbus ist der Unterschied zwischen dem, was ein HMI- oder PLC-Handbuch sagt, und dem, was auf dem Bus passiert. Viele alte Dokumentationen nutzen 5-stellige Adressen mit Präfix:
- 0xxxx für Coils (zum Beispiel 00001 für die erste Coil)
- 1xxxx für Discrete Inputs (10001 für die erste)
- 3xxxx für Input Register (30001 für das erste)
- 4xxxx für Holding Register (40001 für das erste)
Diese Notation kommt aus dem originalen Modicon Modbus Protocol Reference Guide PI-MBUS-300 von 1996 und ist 1-basiert: 40001 verweist auf das ERSTE Holding Register. Das Modbus-Protokoll selbst nutzt jedoch 0-basierte Adressierung auf dem Bus: das erste Holding Register sitzt auf Adresse 0x0000.
Wenn der Hersteller 40001 nennt, senden Sie auf dem Bus 0x0000. Ziehen Sie immer 1 vom 4xxxx-Wert ab, bevor Sie ihn in den Request packen.
Die praktische Regel: steht im Datenblatt "40001 = Netzspannung", setzen Sie in Ihrem Polling-Tool Registeradresse 0 (nicht 1, nicht 40001) mit Funktionscode 0x03. Ein Eastron SDM630 Datenblatt nennt zum Beispiel Voltage L1 auf "30001" (Input-Register-Notation), was auf dem Bus Adresse 0x0000 mit Funktionscode 0x04 wird.
FC 06 gegen FC 16: wann welcher?
Beim Schreiben auf Holding Register haben Sie zwei Optionen: FC 06 (Write Single) oder FC 16 (Write Multiple). Eine berechtigte Frage ist, wann welcher genutzt wird:
FC 06 nutzen, wenn:
- Sie genau einen Wert schreiben und der Slave es unterstützt
- Sie einen minimalen Frame wollen (8 Bytes total bei RTU)
- Sie mit einem Legacy-Slave arbeiten, der nur FC 06 kennt (zum Beispiel ältere Carel pCO Regler)
FC 16 nutzen, wenn:
- Sie mehrere benachbarte Register atomar schreiben wollen (zum Beispiel Sollwert plus Modus gleichzeitig)
- Ihr Slave nur FC 16 unterstützt (zum Beispiel Daikin Altherma)
- Sie konsistent in Ihrem Code bleiben wollen (immer FC 16, auch für ein Register)
Der Unterschied liegt nicht nur in der Registeranzahl. FC 06 antwortet mit einem Echo des Requests (dieselben 8 Bytes zurück). FC 16 antwortet mit einem kürzeren Frame: Slave-Adresse, FC, Start-Adresse, Anzahl Register, CRC. Für einen Logger macht das das Response-Muster leichter erkennbar.
- 1
Klären Sie, welchen FC der Slave unterstützt
Lesen Sie das Datenblatt oder fragen Sie den Hersteller, welche Schreibcodes das Gerät akzeptiert. Ein Gerät muss nicht ALLE Schreibcodes implementieren. Viele HLK-Geräte unterstützen nur 0x10.
- 2
Stellen Sie Ihr Polling-Tool auf den passenden FC
In modpoll:
-m rtu -f 16für Write Multiple. In Home Assistant Modbus:write_type: holdingsmitcount: 1löst FC 16 für ein Register aus. In einem Python-Script: nutzen Sieclient.write_registers(address, values)aus pymodbus, nichtwrite_register(address, value). - 3
Verifizieren Sie mit einem Leserequest nach dem Schreiben
Senden Sie direkt nach dem Write ein FC 03 Read auf dieselbe Adresse und vergleichen Sie den gelesenen Wert mit dem geschriebenen. Geht der Write ohne Exception durch, liest aber anders zurück, sitzt im Slave eine interne Skalierung (zum Beispiel Faktor 10, sodass Sie 250 schreiben, aber 25,0 gespeichert wird).
Häufige Installationsszenarien
Für alle, die regelmäßig Störungen analysieren, hier die drei häufigsten Funktionscode-Situationen:
Szenario 1: ein Modbus-Poller zeigt "FC 131" oder "FC 0x83". Das ist kein unbekannter Funktionscode, sondern eine Exception Response auf FC 0x03. Lesen Sie Byte 5 (den Exception Code) und schauen Sie in der Tabelle oben nach. Meist ist es 0x02 (Illegal Data Address: Adresse existiert nicht) oder 0x03 (Illegal Data Value: zu viele Register angefragt).
Szenario 2: Schreiben auf Holding Register funktioniert nicht. Erste Prüfung: ist es wirklich ein Holding Register und kein Input Register? Input Register sind read only, Schreibversuche geben Exception 0x01 (Illegal Function). Zweite Prüfung: unterstützt der Slave FC 06 oder nur FC 16? Bei Bedarf umschalten.
Szenario 3: Lesen liefert "immer Null". Häufig ein Adress-Offset-Problem (siehe 40001-Abschnitt oben). Senden Sie auch mal mit Funktionscode 0x04 (Input Register) statt 0x03. Manche Hersteller legen Messwerte in Input Register und nur Konfiguration in Holding Register.
Für den breiteren Kontext von Modbus RTU gegen TCP und welcher Transportlayer wann passt, siehe unseren Vergleich RTU vs TCP. Für spezifische Wärmepumpen-Szenarien mit Funktionscodes im Installationskontext siehe Wärmepumpe Modbus Monitoring.
Häufig gestellte Fragen
Was ist der Unterschied zwischen Modbus Funktionscode 0x03 und 0x04?
Funktionscode 0x03 liest Holding Register (read/write, 16-bit), Funktionscode 0x04 liest Input Register (read only, 16-bit). Beide liefern 16-Bit-Werte zurück, aber Holding Register sind auch über 0x06 und 0x10 beschreibbar. Viele Hersteller entscheiden sich dafür, nur Holding Register zu nutzen, auch für Messwerte.
Wie viele Modbus Funktionscodes gibt es?
Die Modbus Application Protocol Spezifikation definiert 19 öffentliche Funktionscodes. Daneben gibt es zwei User-Defined-Bereiche (0x41 bis 0x48 und 0x64 bis 0x6E) für herstellerspezifische Funktionen. In der Praxis decken neun Codes (0x01 bis 0x06, 0x0F, 0x10 und 0x17) etwa 99 Prozent des Verkehrs ab.
Wie lese ich einen Modbus Exception Code?
Eine Exception Response besteht aus der Slave-Adresse, dem ursprünglichen Funktionscode mit Bit 7 auf 1 (zum Beispiel 0x83 für eine FC 0x03 Exception) und einem Byte Exception Code. Die neun Standard-Exception-Codes reichen von 0x01 (Illegal Function) bis 0x0B (Gateway Target Failed to Respond). Lesen Sie Byte 3 (nach Slave-Adresse und Exception FC) und schlagen Sie die Bedeutung nach.
Warum funktioniert mein Schreibvorgang auf Register 40001 nicht?
Die 4xxxx-Notation ist 1-basiert, die Protokoll-Adressierung auf dem Bus ist 0-basiert. Schreiben Sie auf dem Bus an 40001, senden Sie an Holding Register 40000, das meist nicht existiert. Das richtige Mapping ist 40001 in der HMI gleich 0x0000 auf dem Bus. Ziehen Sie immer 1 ab, bevor Sie den Wert ins Tool setzen, oder lassen Sie das Tool die Konvertierung vornehmen.
Was ist die maximale Anzahl Register pro Modbus Request?
Für Funktionscode 0x03 (Read Holding Registers) liegt das Maximum bei 125 Registern pro Request. Für 0x10 (Write Multiple Registers) sind es 123 Register. Für 0x01 und 0x02 (Read Coils und Discrete Inputs) gelten 2000 Bits pro Request. Fordern Sie mehr an, kommt Exception Code 0x03 (Illegal Data Value) zurück.
Nächste Schritte
Funktionscodes sind die Arbeitssprache von Modbus: wer sie liest, liest das Protokoll. Kombinieren Sie dieses Wissen mit der Modbus RTU Framestruktur, um Byte für Byte einen Trace zu analysieren, und mit der Modbus TCP Framestruktur für die moderne IP-Transportvariante.
Wollen Sie diese Funktionscodes nicht selbst in einem Script schreiben, sondern die Daten direkt in der Cloud sehen? Das ModbusCloud Gateway übernimmt das Polling und stellt die Register über ein Dashboard plus Alerts bereit. Buchen Sie eine kurze Demo, um zu sehen, wie das in Ihrer Flotte funktioniert.
Bereit loszulegen?
Bestellen Sie das ModbusCloud Gateway und ueberwachen Sie Ihre Anlagen in 5 Minuten.
Gateway ansehenBereit loszulegen?
Bestellen Sie das ModbusCloud Gateway und ueberwachen Sie Ihre Anlagen in 5 Minuten.
Gateway ansehen