Leave Your Message

Részletes oktatóanyag a Modbus kommunikációs protokoll üzeneteinek elemzéséről

2026-06-24

    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-1.jpg

    1.2 Protokollspecifikációs korlátozások

    1-2.jpg

    II. Modbus adatmodell és címszabályok

    2.1 Négyféle működési objektum

    2-1.jpg

    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:

    2-2.jpg

    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-1.jpg

    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:

    3-2.jpg

    [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-2-1.jpg

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

    3-3.jpg

    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)

    3-4-1.jpg

    [Válaszkeret formátuma]

    3-4-2.jpg

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

    3-4-3.jpg

    (2) Holding Register olvasása/Input Register olvasása (Funkciókód: 0x03/0x04)

    [Kérés keretformátuma] (összesen 8 bájt)

    3-4-4.jpg

    [Válaszkeret formátuma]

    3-4-5.jpg

    (3) Egyetlen tárolóregiszter írása (0x06 funkciókód)

    [Kérés keretformátuma] (összesen 8 bájt)

    3-4-6.jpg

    [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]

    3-4-7.jpg

    [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

    3-4-8.jpg

    [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-1.jpg

    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:

    4-2.jpg

    [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.jpg

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

    4-3-0.jpg

    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:

    5-3.jpg

    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-1.jpg

    6.2 A standard kivételkódok jelentése

    6-2.jpg

    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:

    6-3.jpg

    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:

    CR LF

    7-1.jpg

    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-1.jpg

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

    8-2.jpg

    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)