In dieser Lektion

Was diese Lektion behandelt

  • Die sieben Bytes des MBAP-Headers und wer welches Feld ausfüllt
  • Das Length-Feld nachrechnen, und warum keine CRC enthalten ist
  • Welche Unit-ID zu einem nativen Gerät gehört und welche hinter einem Gateway

Vorher lesen: Exception-Codes lesen und den Funktionscode wählen, Das Modbus RTU Frame Byte für Byte, plus CRC

Der MBAP-Header ist der Umschlag, den Modbus TCP um exakt dieselbe PDU legt, die auf RS485 zwischen Adressbyte und CRC steht: sieben Bytes, vier Felder, kein Prüfsummenfeld. Wer diese sieben Bytes lesen kann, zerlegt jede TCP-Transaktion in einer Aufzeichnung. Nach dieser Lektion rechnen Sie das Length-Feld selbst nach und wissen, welcher Wert in Ihr Unit-ID-Feld gehört.

Dieselbe Anfrage, jetzt über Ethernet

Zwei Frames, dieselbe Frage: lies drei Holding-Register ab PDU-Adresse 107. Oben die serielle Variante, unten dieselbe Anfrage über Modbus TCP.

01 03 00 6B 00 03 74 17
00 01 00 00 00 06 FF 03 00 6B 00 03
MerkmalModbus RTUModbus TCP
Länge des Frames8 Bytes12 Bytes
Adressierung des GerätsServeradresse 01 im FrameIP-Adresse, Unit-ID 0xFF ohne Bedeutung
Nachrichtengrenze3,5 Zeichenzeiten Stilledas Length-Feld im Header
FehlererkennungCRC-16, Low Byte zuerstEthernet und TCP, keine Modbus-CRC

In der Mitte steht beide Male dieselbe Bytefolge: 03 00 6B 00 03. Das ist die PDU, also Funktionscode plus Daten, und sie ändert sich beim Wechsel des Transports nicht um ein Bit. Getauscht wird nur der Umschlag: RTU setzt ein Adressbyte davor und zwei CRC-Bytes dahinter, TCP setzt sieben Bytes davor und nichts dahinter. Im Datenblatt heißt das Register 40108, auf der Leitung liegt die 0-basierte PDU-Adresse 107. Den Transport im Überblick beschreibt Modbus TCP erklärt, die Wahl zwischen beiden der Vergleich Modbus RTU oder TCP, und das serielle Frame zerlegt die Lektion zum RTU-Frame und der CRC.

Die sieben Bytes des MBAP-Headers

Die ersten sieben Bytes der TCP-Variante sind der MBAP-Header. Vier Felder, alle Big-Endian, also High Byte zuerst.

BytesFeldWertWer füllt es aus
00 01Transaction Identifier1Client wählt, Server kopiert zurück
00 00Protocol Identifier0Client setzt 0, Server kopiert zurück
00 06Length6Client rechnet, Server rechnet neu
FFUnit Identifier255Client setzt, Server kopiert zurück

Sechs dieser sieben Bytes übernimmt der Server unverändert in die Antwort. Nur das Length-Feld berechnet er selbst, denn seine Antwort ist meist länger als Ihre Anfrage. Das Protocol-Feld hat genau einen erlaubten Wert, 0x0000. Steht dort etwas anderes, verwirft der Server die Nachricht stillschweigend: keine Antwort, keine Exception, nur ein Timeout auf Ihrer Seite.

MBAP-Header, 7 BytesPDU, Funktionscode und DatenTID2 BPID2 BLEN2 BUID1 BFC1 BDATAN BCRC-16
TIDTransaction-ID, 2 Bytes
PIDProtocol-ID, 2 Bytes, immer 0
LENLength, 2 Bytes
UIDUnit-ID, 1 Byte
FCFunktionscode
DATADaten

Keine CRC: Ethernet und TCP prüfen die Integrität bereits.

Sieben Bytes Header, danach exakt dieselbe PDU wie auf RS485.

Warum es eine Transaction-ID gibt

Auf RS485 stellt der Client eine Frage und wartet auf die Antwort. Erst danach darf das nächste Frame auf den Bus, sonst senden zwei Teilnehmer gleichzeitig. Über TCP gilt diese Regel nicht: Ein Client darf mehrere Anfragen offen haben, und die Antworten müssen nicht in derselben Reihenfolge zurückkommen.

Dafür ist die Transaction-ID da. Der Client vergibt pro offener Anfrage eine Nummer, die auf dieser Verbindung eindeutig ist, der Server kopiert sie unverändert in die Antwort, und der Client ordnet damit beides einander zu. Ein Zähler, der bei jeder Anfrage um eins hochgeht, reicht dafür völlig. Sobald eine SPS oder ein Gebäudeautomationsserver mehrere Geräte parallel abfragt, hängt die Zuordnung allein an diesem Feld.

Das Length-Feld nachrechnen

Length zählt nicht das ganze Frame, sondern nur das, was nach dem Feld noch kommt: 1 Byte Unit Identifier plus die PDU. In der Anfrage sind das FF und 03 00 6B 00 03, also 1 plus 5 gleich 6, und im Header steht 00 06. Daraus folgt die Prüfregel: Das komplette Frame ist immer sechs Bytes länger als der Length-Wert.

Die Antwort auf dieselbe Anfrage:

00 01 00 00 00 09 FF 03 06 02 2B 00 00 00 64
BytesFeldBedeutung
00 01Transaction Identifieraus der Anfrage kopiert
00 00Protocol Identifieraus der Anfrage kopiert
00 09Length1 Byte Unit-ID plus 8 Bytes PDU, vom Server berechnet
FFUnit Identifieraus der Anfrage kopiert
03Funktionscodeunverändert, also keine Exception
06Byte Count3 Register mal 2 Bytes
02 2B 00 00 00 64Registerwerte555, 0 und 100

Zusammen 15 Bytes: 7 Header plus 8 PDU. Nach oben ist das begrenzt: Die PDU bleibt auch über Ethernet bei höchstens 253 Bytes, das ADU bei 260. Deshalb lesen Sie auch im Netzwerk nie mehr als 125 Register pro Anfrage.

Ein zweites Beispiel, das an einer Stelle abweicht. Fehlt eines der drei Register, antwortet das Gerät so:

00 01 00 00 00 03 FF 83 02

Length ist jetzt 00 03, also 1 plus 2. Der Funktionscode lautet 0x83, das ist 0x03 mit gesetztem höchstem Bit, und 02 ist der Exception-Code Illegal Data Address. Eine Exception erkennen Sie über TCP also an zwei Dingen: Length 3 und ein Funktionscode über 0x80.

Vollständiges Frame (ADU)

MBAP-Header (7 Bytes)

00010000000601

PDU (Funktionscode und Daten)

030000000A

Length zählt 1 Byte Unit-ID plus 5 Bytes PDU, zusammen 6. Genau dieser Wert steht im Header.

Transaction-ID00 011Frei gewählte laufende Nummer. Die Antwort wiederholt sie, damit Sie Anfrage und Antwort zuordnen können.
Protocol-ID00 000Für Modbus immer 0.
Length00 066Anzahl der Bytes, die nach diesem Feld noch folgen, die Unit-ID eingeschlossen.
Unit-ID011Adresse des Geräts hinter dem Gateway. Bei einem nativen TCP-Gerät 255 oder 0.
Funktionscode033 (Read Holding Registers)Welche Operation Sie anfordern.
Startadresse00 000Erstes Register, auf der Leitung 0-basiert.
Anzahl00 0A10Anzahl der Register oder Coils in einer Anfrage.
Ändern Sie Funktionscode und Anzahl und beobachten Sie, was mit dem Length-Feld passiert.

Warum keine CRC enthalten ist

Modbus TCP hat kein Prüfsummenfeld, und das ist kein Versehen. Unter Modbus liegen zwei Schichten, die diese Arbeit bereits erledigen: Ethernet hängt an jedes Frame eine CRC-32 an, und TCP hat eine eigene Prüfsumme samt erneuter Übertragung verlorener Segmente. Eine dritte Kontrolle in der Modbus-Schicht würde nur Bandbreite und Rechenzeit kosten.

Dazu kommt das zweite Problem, das der Header löst. TCP ist ein Bytestrom ohne Nachrichtengrenzen: Eine Modbus-Nachricht kann auf mehrere Segmente verteilt ankommen oder zusammen mit der folgenden in einem Segment liegen. Das Length-Feld sagt dem Empfänger, wo sie endet, und ist damit das direkte Gegenstück zur 3,5-Zeichen-Stille auf der seriellen Leitung.

Was Sie in das Unit-ID-Feld eintragen

Bei einem nativen TCP-Gerät ist die Unit-ID bedeutungslos, denn adressiert wird über die IP-Adresse. Die Spezifikation empfiehlt dort 0xFF, also 255, und lässt 0x00 ebenfalls zu. Hinter einem Gateway ist es umgekehrt: Dann trägt das Feld die echte Serveradresse des Geräts auf der RS485-Seite, einen Wert von 1 bis 247, wobei 0 als Broadcast reserviert ist. Die IP-Adresse zeigt dann auf das Gateway, und die Unit-ID entscheidet, an welches Gerät dahinter die Anfrage geht.

Warum ausgerechnet 0xFF? Das ist kein Ritual, sondern Schutz. Bekommt später ein Gateway die IP-Adresse Ihres TCP-Geräts, dann leitet es eine Anfrage mit einem bedeutungsvollen Wert im Feld an irgendein serielles Gerät weiter. Bei 0xFF verwirft es die PDU einfach.

Viele Hersteller halten sich nicht an die Empfehlung: SMA erwartet im SunSpec-Profil die 126, Fronius beim GEN24 die 1 für den Wechselrichter und die 200 für den Zähler, SolarEdge über Ethernet die 1. Die Unit-ID gehört deshalb in dieselbe Notiz wie IP-Adresse und Port. Wie Sie ein Gateway aufsetzen, zeigt die Anleitung zum Einrichten eines Modbus TCP Gateways.

Warum Port 502 feststeht

Alle Modbus TCP ADUs gehen an den registrierten Port 502. Modbus/TCP wurde 1996 bei der IANA eingetragen, der Servicename zu Port 502 lautet dort mbap und ist auf modbus.org registriert. Die Spezifikation erlaubt einem Gerät ausdrücklich einen zusätzlichen Port, verlangt aber, dass 502 daneben erreichbar bleibt. Deshalb ist 502 der erste Port, den Sie in einer Firewall freigeben.

Verlassen Sie sich trotzdem nicht blind darauf. SolarEdge-Wechselrichter mit SetApp hören standardmäßig auf Port 1502, die älteren Geräte mit LCD-Display auf 502. Bevor Sie die Firewall verdächtigen, lesen Sie die Portangabe im Datenblatt.

Häufige Fehler

  1. Die Unit-ID mit der RS485-Serveradresse verwechseln. Bei einem nativen TCP-Gerät gehört dort 255 oder 0 hinein, hinter einem Gateway dagegen die echte Serveradresse zwischen 1 und 247. Wer hinter einem Gateway 255 einträgt, bekommt Exception 0B und sucht anschließend an der falschen Stelle.
  2. Length für die Gesamtlänge des Frames halten. Das Feld zählt nur die Unit-ID und die PDU. Bei 00 06 ist das Frame nicht sechs, sondern zwölf Bytes lang. Wer den Puffer nach dem Length-Wert bemisst, schneidet jede Nachricht sechs Bytes zu früh ab.
  3. Eine CRC erwarten. Ein TCP-Frame endet mit Nutzdaten. Ein Werkzeug, das RTU dekodiert, liest die letzten zwei Bytes als Prüfsumme und meldet einen Fehler, der in Wirklichkeit ein Registerwert ist.
  4. Port 502 als gesetzt annehmen. Ein Gerät darf einen zusätzlichen Port anbieten, und manche Hersteller nutzen das. Prüfen Sie die Portangabe, bevor Sie eine Firewallregel schreiben.

Selbst ausprobieren

Ziel: Sie bauen ein Frame selbst und kontrollieren, ob die Länge stimmt. Die ganze Übung läuft in der Seite, Hardware brauchen Sie dafür nicht.

  1. 1

    Den Builder auf das Beispiel einstellen

    Setzen Sie im Builder oben den Funktionscode auf FC03, die Unit-ID auf 255, die Startadresse auf 107 und die Anzahl auf 3.

  2. 2

    Mit dem Musterframe vergleichen

    Halten Sie das Ergebnis neben 00 01 00 00 00 06 FF 03 00 6B 00 03. Abweichen darf nur die Transaction-ID, denn die wählt der Client frei.

  3. 3

    Die Anzahl auf 10 erhöhen

    Beobachten Sie, was mit dem Length-Feld passiert und was nicht passiert. Length beschreibt die Anfrage, nicht die Antwort, und die Anfrage bleibt gleich lang.

  4. 4

    Auf FC16 umschalten

    Wechseln Sie den Funktionscode auf FC16 und zählen Sie, um wie viele Bytes die PDU wächst. Der Byte Count und die Registerwerte kommen jetzt mit in die Anfrage.

  5. 5

    Die Antwortlänge auf Papier vorhersagen

    Rechnen Sie für Schritt 2 vor: 7 Bytes MBAP plus 1 Byte Funktionscode plus 1 Byte Byte Count plus 6 Datenbytes ergibt 15 Bytes.

  6. 6

    Gegenprobe mit echten Daten

    Wenn Sie ein Gerät im Netz haben: Lesen Sie ein bekanntes Register aus. Dasselbe Frame taucht in der Lektion zur Analyse mit Wireshark wieder auf, dort dann als Aufzeichnung.

Erwartetes Ergebnis: ein Frame, das bis auf die Transaction-ID mit dem Beispiel übereinstimmt, und eine selbst ausgerechnete Antwortlänge von 15 Bytes.

Zusammenfassung

  • Der MBAP-Header ist sieben Bytes lang: Transaction-ID, Protocol-ID, Length und Unit-ID; die PDU dahinter ist identisch mit der eines RTU-Frames.
  • Von den sieben Header-Bytes berechnet der Server nur Length neu, die übrigen sechs kopiert er aus der Anfrage.
  • Length ist 1 Byte Unit-ID plus die Länge der PDU, das komplette Frame also immer sechs Bytes länger als dieser Wert.
  • Bei einem nativen TCP-Gerät gehört 0xFF oder 0x00 in das Unit-ID-Feld, hinter einem Gateway die echte Serveradresse von 1 bis 247.
  • Port 502 muss laut Spezifikation immer erreichbar bleiben, auch wenn ein Gerät zusätzlich einen anderen Port anbietet.

Überprüfen Sie sich selbst

Vier Fragen zu dieser Lektion. Zu jeder Antwort gibt es eine Erläuterung.

Frage 1 von 4
Im Frame 00 01 00 00 00 06 FF 03 00 6B 00 03: was bedeutet das Feld 00 06?
Sie lesen einen Energiezähler aus, der hinter einem RS485-auf-Ethernet-Gateway hängt. Sie tragen Unit-ID 255 ein und bekommen Exception 0B zurück. Was bedeutet das?
Warum enthält Modbus TCP keine CRC, Modbus RTU aber schon?
Zwei Anfragen desselben Clients sind gleichzeitig unterwegs. Woran erkennt der Client, welche Antwort zu welcher Anfrage gehört?

Kommen Sie bei einem Projekt nicht weiter?

Beschreiben Sie, was Sie sehen und wo es hakt. Wir schauen es uns an und sagen Ihnen, was wir tun würden.

Weiterlesen in der Wissensdatenbank