Részletes oktatóanyag a Modbus kommunikációs protokoll üzeneteinek elemzéséről
I. A Modbus protokoll áttekintése
Modbus egy soros kommunikációs protokoll, amelyet a Modicon (ma Schneider Electric) fejlesztett ki 1979-ben programozható logikai vezérlők (PLC-k) közötti kommunikációhoz. Több mint négy évtizedes fejlődés során az ipari automatizálás területének egyik tényleges szabványos kommunikációs protokolljává vált.
Főbb jellemzők:
- Master/Slave architektúra: Egyetlen master host több slave-vel, ahol a master kezdeményezi a kéréseket, a slave-ek pedig passzívan válaszolnak.
- Nyílt protokoll: Nincsenek licencdíjak; bármely gyártó ingyenesen megvalósíthatja.
- Több átviteli mód: RTU (bináris), ASCII (szöveges), TCP (Ethernet).
- Különböző fizikai rétegeket támogat: RS485 (leggyakoribb), RS232, TCP/IP (Ethernet).
- Átlátható adatmodell: Négy objektumtípus – tekercsek, diszkrét bemenetek, bemeneti regiszterek és tárolóregiszterek.
1.1 Három protokollváltozat összehasonlítása

1.2 Protokollspecifikációs korlátozások

II. Modbus adatmodell és címszabályok
2.1 Négyféle működési objektum

2.2 Címreprezentáció (Kritikus!)
A különböző gyártók eltérő kódolási sémákat alkalmaznak Modbus címek, ami a gyakorlati megvalósítások leggyakoribb buktatója:

Cím előtag jelentése (ipari szabvány szerinti ábrázolás):
- 0-val kezdődő: Protokoll cím (hexadecimális), pl. 0x0000
- 4 xxxx: Karbantartó regiszterek; például a 40001 a 0. karbantartási regiszter protokollcímét jelöli.
- 3xxxx: Bemeneti regiszter; pl. a 30001 a 0. bemeneti regiszter protokollcímét jelöli. ·
- 0xxxx: Tekercs; pl. a 00001 a 0. tekercs protokollcímét jelöli. ·
- 1xxxx: Diszkrét bemenet; pl. az 10001 a 0. diszkrét bemenet protokollcímét jelöli.
2.3 Big Data feldolgozási szabályok
1.1. Műveletenként olvasható regiszterek maximális száma: 125 (0x03/0x04 funkciókódok)
2.2. Műveletenként kiolvasható tekercsek/diszkrét bemenetek maximális száma: 2000 (0x01/0x02 funkciókódok)
3.3. Műveletenként írható regiszterek maximális száma: 123 (0x10 funkciókód)
4.4. Műveletenként írható tekercsek maximális száma: 1968 (0x0F funkciókód)
5.5. Ezen korlátok túllépése blokk alapú olvasást/írást igényel; a buszütközések elkerülése érdekében biztosítson eltolt lekérdezési intervallumokat.
III. A Modbus RTU üzenetek részletes elemzése
Az RTU (Remote Terminal Unit) a legszélesebb körben használt Modbus átviteli protokoll Ipari alkalmazásokban bináris kódolást alkalmaznak a nagy átviteli hatékonyság és az RS485/RS232 soros interfészekkel való kompatibilitás érdekében. A keretek közötti legalább 3,5 karakteres néma intervallumnak kell lennie a keretek határainak megkülönböztetéséhez.
3.1 Az RTU teljes keretszerkezete
Egy RTU-ban egy teljes utasításadat-keret a következő négy részből áll:

3.2 RTU üzenet példa – Holding regiszterek olvasása (0x03 funkciókód)
[Kérés üzenet] A master beolvassa az 1. slave holding regisztereit (kezdőcím: 0x0001, 3 regiszter olvasása):
01 03 00 01 00 03 54 0B
A kérésüzenet bájtonkénti elemzése:

[Válaszüzenet] Az 1. slave állomás három regiszterből ad vissza adatokat: 01, 03, 06, 02, 2B, 00, 00, 00, 64, D5, 87
A válaszüzenet bájtonkénti elemzése:

3.3 A standard funkciókódok részletes magyarázata

3.4 Az egyes funkciókódok üzenetformátumainak részletes leírása
(1) Tekercs olvasása / Diszkrét bemenet olvasása (0x01/0x02 funkciókódok)
[Kérés keretformátuma] (összesen 8 bájt)

[Válaszkeret formátuma]

[Pozícióanalízis példa] A válaszadatok 3 bájtból állnak (20–38 tekercsek):

(2) Holding Register olvasása/Input Register olvasása (Funkciókód: 0x03/0x04)
[Kérés keretformátuma] (összesen 8 bájt)

[Válaszkeret formátuma]

(3) Egyetlen tárolóregiszter írása (0x06 funkciókód)
[Kérés keretformátuma] (összesen 8 bájt)

[Válasz keret] A kérés keretével megegyezően visszaigazolja a sikeres írást.
(4) Több karbantartási regiszter írása (0x10 funkciókód)
[Kérés keretformátuma]

[Válaszkeret formátuma] (összesen 8 bájt): [Cím][0x10][Kezdő cím (2 bájt)][Szám (2 bájt)][CRC (2 bájt)]
(5) Írj egyetlen tekercset (Funkciókód: 0x05)
[Kérés keretformátuma] (összesen 8 bájt): Csak két érvényes érték támogatott íráshoz:
- 0xFF00 – Tekercs BE (zárt) állásban
- 0x0000 – A tekercs KI (nyitott) állásban van

[Válasz keret] A kérés keretével megegyezően visszaigazolja a sikeres írást.
IV. A Modbus TCP üzenetek részletes elemzése
A Modbus TCP az Ethernet TCP/IP protokollon keresztül működik, alapértelmezettként az 502-es portot használva. Az RTU móddal ellentétben a Modbus TCP egy MBAP (Modbus Application Protocol) fejlécet használ az üzenethatárok meghatározásához, és nem igényel CRC-ellenőrzést (ehelyett a TCP protokoll beépített hibaellenőrző mechanizmusára támaszkodik).
4.1 MBAP fejlécstruktúra (7 bájt, minden TCP csomagban benne van)

4.2 Modbus TCP üzenet példa
[Kérés üzenet] Az 1. slave eszköz tartásregiszterének olvasása (kezdőcím: 0x0000, 3 érték olvasása):
00 01 00 00 00 06 01 03 00 00 00 03
A kérésüzenet mezőnkénti elemzése:

[Válaszüzenet] A slave három regiszterből ad vissza adatokat:
00 01 00 00 00 09 01 03 06 02 2B 00 00 00 64
A válaszüzenet mezőnkénti elemzése:

4.3 Az RTU és a TCP csomagstruktúrák közötti alapvető különbségek

V. A CRC-16 ellenőrzésének részletes magyarázata
A CRC algoritmus (Cyclic Redundancy Check) a Modbus RTU-k keretellenőrzési mechanizmusa, amelynek célja az üzenetátvitel során fellépő hibák észlelése. A CRC-16 generáló polinom x¹⁶ + x¹⁵ + x² + 1 (egyenértékű a 0x8005-tel); a gyakorlatban az invertált 0xA001 polinomot használják.
5.1 CRC-16 számítási lépések
6.1. Inicializálja a 16 bites CRC regisztert 0xFFFF értékre
7.2. Végezzen XOR műveletet az első bájt és a CRC regiszter alsó 8 bitje között; az eredményt tárolja vissza a CRC regiszter alsó 8 bitjébe.
8.3. Tolja el a CRC regisztert 1 bittel jobbra, a magasabb biteket 0-val töltve fel; határozza meg a kifelé tolódott bitet (LSB):
9.4. Ha a kifelé mozdított bit 0: Folytassa a jobbra mozdítást csak 1 bittel
10.5. Ha a kifelé mozdított bit 1: XOR művelet végrehajtása a CRC regiszter és a 0xA001 között.
11.6. Ismételje meg a 3. lépést, amíg az aktuális bájt mind a 8 bitjének feldolgozása be nem fejeződik.
12.7. Vegye a következő bájtot, és ismételje meg a 2–6. lépéseket, amíg az összes bájt feldolgozásra nem került. 13.8. Az összes bájt feldolgozásának befejezése után cserélje fel a CRC regiszter magas és alacsony bájtjait a végső ellenőrzőösszeg megkapásához.
14.9. Az utolsó ellenőrzőösszeget az üzenet végéhez fűzzük, az alsó bájtot elöl, a felső bájtot pedig utoljára.
5.2 CRC-16 számítási példa (Python kód)
A következő Python függvény közvetlenül használható a Modbus RTU CRC-16 ellenőrzőösszegének kiszámításához:
def modbus_crc16(adatok: bájtok) -> bájtok:
"""számláló Modbus RTU CRC-16 ellenőrző kód(Adja vissza az első két bájtot, a legkisebb helyiértékű bittel kezdve)"""
crc = 0xFFFF
bájt az adatokban:
crc ^= bájt
_ esetén a(z)(8) tartományban:
ha crc és 0x0001:
crc = (crc >> 1) ^ 0xA001
más:
crc >>= 1
# Először az alsó bájtot adja vissza, majd a felső bájtot
visszatérési bájtok([crc & 0xFF, (crc >> 8) & 0xFF])
# Adjon meg tipikus példákat:count 01 03 00 01 00 03 CRC
keret = bájtok([0x01, 0x03, 0x00, 0x01, 0x00, 0x03])
crc = modbus_crc16(keret)
print(crc.hex()) # export:540b(0x54 0x0B)
5.3 A CRC ellenőrzés helye az üzenetben
A 01 03 00 01 00 03 54 0B kérésüzenet példáján keresztül:

A vevő újraszámolja az első 6 bájt CRC-értékét, és összehasonlítja azt a csomag utolsó 2 bájtjával. Ha ezek eltérnek, átviteli hibát észlel, és nem küld vissza választ.
Ⅵ.Kivételkezelés és hibakód részletei
Amikor egy slave állomás nem tudja végrehajtani a master állomástól érkező kérést (például nem támogatott funkciókódok vagy tartományon kívüli cím miatt), akkor egy kivételre adott válaszkeretet ad vissza. A kivételre adott válasz funkciókódja = eredeti funkciókód + 0x80 (azaz a legmagasabb bit 1-re van állítva).
6.1 Rendellenes válaszformátum (RTU)
[Szolga cím][Funkciókód | 0x80][Rendellenes kód][CRC-16]

6.2 A standard kivételkódok jelentése

6.3 Példa a rendellenes válaszra
[Forgatókönyv] A fő állomás érvénytelen címen lévő regiszter beolvasását kéri az 1. slave állomástól, és a slave állomás kivételt ad vissza:
Kérés: 01 03 00 20 00 01 XX XX (olvasási regiszter a 0x0020 címen);
Kivételre adott válasz: 01 83 02 C0 F1;
A kivételre adott válasz bájtról bájtra történő lebontása:

VI. Bevezetés a Modbus ASCII üzenetekbe
A Modbus ASCII mód az összes adatbájtot két ASCII karakterként kódolja (pl. a 0x0F "0F"-ként van kódolva). Bár könnyen olvasható, alacsony átviteli hatékonyságot kínál, és elsősorban hibakeresési célokra használják.
7.1 ASCII keretszerkezet
Teljes ASCII keretformátum:

7.2LRC-ellenőrzési algoritmus
Az LRC (longitudinális redundancia-ellenőrzés) kiszámításának lépései:
15.1. Végezzen bináris összegzést a címmező, a függvénykód és az adatmező összes bájtján (a kezdő- és végmarkerek kivételével).
16.2. Az átviteli biteket figyelmen kívül hagyja (ha az eredmény meghaladja a 255-öt, automatikusan körbefutja és csak az alsó 8 bitet tartja meg).
17.3. Számítsd ki az összegzési eredmény komplementerét 1 modulo-val (azaz 0xFF − sum).
18.4. Növeld a komplementert 1-gyel, hogy megkapd a végső LRC ellenőrző kódot (1 bájt).
19.5. Kódold az LRC ellenőrzőkódot két ASCII karakterként, és fűzd hozzá őket az üzenet végéhez.
VIII. Gyakorlati tippek és gyakori problémák
8.1 Bájtsorrenddel (Big-Endian/Micro-Endian) kapcsolatos problémák
A Modbus szabvány big-endian sorrendet használ (a magasabb helyiértékű bájttal előre) 16 bites vagy hosszabb adatok átviteléhez. Egyes eszközök (pl. bizonyos ARM-alapú eszközök) mikro-endian sorrendet használnak; a bájtsorrend konverziója szükséges a numerikus elemzési hibák elkerülése érdekében.

8.2 Regisztrációs egység méretkorlátja (PDU ≤ 253 bájt)

8.3 Kommunikációs időtúllépés és újrapróbálkozás konfigurációs javaslatai
Ajánlott konfigurációk:
- Lekérdezési intervallum: A slave maximális válaszidejének 2-3-szorosára állítható (jellemzően 100–500 ms) • Időtúllépés időtartama: Ajánlott tartomány 1000–3000 ms, a slave válaszsebessége alapján állítható
- Újrapróbálkozások: Ajánlott maximum 3 próbálkozás; sikertelen kísérlet esetén riasztást indít
- Többszolga lekérdezés: A szolgák között eltolt lekérdezési intervallumok ütemezése a buszütközések elkerülése érdekében • Bájt időtúllépés: RTU módban az 1,5 karakternél hosszabb karakterintervallum kerethibának minősül.
8.4 Ajánlott hibakereső eszközök
Függelék: Gyakori üzenetek gyorsreferencia-táblázata
Tekercs olvasása (Funkciókód: 0x01)
[Kérés]: Olvasás az 1. slave állomásról a 0 kezdőcímen (1. tekercs), 8 tekercs állapotüzenet lekérése: 01 01 00 00 00 08 3D CC
[Válasz]: Nyolc tekercsállapot: 0x55 (01010101B);
Üzenet: 01 01 01 55 94 36
Írás egyetlen tekercsre (Function Code 0x05)
[Kérés] A 0. címen található tekercs BE állásba állítása (írási érték: 0xFF00):
Üzenet: 01 05 00 00 FF 00 8C 3A
[Kérés] A 0. címen található tekercs KI állapotba állítása (írási érték: 0x0000):
Üzenet: 01 05 00 00 00 00 CD CA
[Válasz] Megegyezik a kérés keretével
Egyetlen regiszterbe írás (0x06 funkciókód):
[Kérés] Írja be a 0x1234 értéket a 0. címen történő regiszterbe.
Üzenet: 01 06 00 00 12 34 XX XX (XX CRC, kiszámítandó).
[Válasz] Megegyezik a kérés keretével.
Több regiszterbe írás (Function Code 0x10)
[Kérés]: Írjon két regiszterbe a 0 címtől kezdve, 0x1234 és 0xABCD értékekkel.
Üzenet: 01 10 00 00 00 02 04 12 34 AB CD XX XX
[Válasz]: Visszaadja a kezdőcímet és a kiírt regiszterek számát.
Üzenet: 01 10 00 00 00 02 41 C8
Bemeneti regiszterek olvasása (0x04 funkciókód)
[Kérés]: Olvasás a slave 1-ről a 0 kezdőcímen, két bemeneti regiszter olvasása
üzenetek: 01 04 00 00 00 02 71 CB
[Válasz]: Két bemeneti regiszterértéket ad vissza
üzenetek: 01 04 04 00 64 01 90 XX XX (Visszatérési értékek: 100 és 400)










