Детален туторијал за анализа на пораки од комуникацискиот протокол Modbus
I. Преглед на протоколот Modbus
Модбус е сериски комуникациски протокол развиен од Modicon (сега Schneider Electric) во 1979 година за комуникација помеѓу програмабилни логички контролери (PLC). Во текот на повеќе од четири децении еволуција, тој стана еден од де факто стандардните комуникациски протоколи во областа на индустриската автоматизација.
Клучни карактеристики:
- Архитектура на главен/служен хост: Еден главен хост со повеќе робови, каде што господарот иницира барања, а робовите одговараат пасивно.
- Отворен протокол: Нема такси за лиценцирање; секој производител може да го имплементира бесплатно.
- Повеќе режими на пренос: RTU (бинарен), ASCII (текст), TCP (Етернет).
- Поддржува различни физички слоеви: RS485 (најчест), RS232, TCP/IP (Ethernet).
- Јасен модел на податоци: Четири типа објекти – намотки, дискретни влезови, влезни регистри и регистри за задржување.
1.1 Споредба на три варијанти на протокол

1.2 Ограничувања на спецификацијата на протоколот

II. Модел на податоци и правила за адреса на Modbus
2.1 Четири типа на оперативни објекти

2.2 Претставување на адреса (критично!)
Различни производители користат различни шеми за кодирање за Модбус адреси, што е најчестата замка во практичните имплементации:

Значење на префиксот на адресата (претставување според индустрискиот стандард):
- Почнувајќи со0: Протоколска адреса (хексадецимална), на пр., 0x0000
- 4 xxxx: Регистри за одржување; на пример, 40001 ја означува протокол адресата на регистарот за одржување 0.
- 3xxxx: Влезен регистар; на пр., 30001 ја означува протоколната адреса на влезниот регистар 0. ·
- 0xxxx: Намотка; на пр., 00001 ја означува протоколната адреса на намотката 0. ·
- 1xxxx: Дискретен влез; на пр., 10001 ја означува протоколната адреса на дискретниот влез 0.
2.3 Правила за обработка на големи податоци
1.1. Максимален број на регистри што се читаат по операција: 125 (функционални кодови 0x03/0x04)
2.2. Максимален број на намотки/дискретни влезови што се читаат по операција: 2000 (функционални кодови 0x01/0x02)
3.3. Максимален број на регистри запишани во по операција: 123 (код на функција 0x10)
4.4. Максимален број на намотки запишани по операција: 1968 (код на функција 0x0F)
5.5. Надминувањето на овие ограничувања бара читање/пишување базирано на блокови; обезбедете распоредени интервали на анкетирање за да се избегнат конфликти меѓу магистралата.
III. Детална анализа на пораките од Modbus RTU
RTU (Remote Terminal Unit) е најшироко користената Протокол за пренос на Modbus во индустриски апликации, со примена на бинарно кодирање за висока ефикасност на пренос и компатибилност со сериските интерфејси RS485/RS232. Потребен е минимален интервал на тишина од 3,5 карактери помеѓу рамките за да се разликуваат границите на рамките.
3.1 Целосна структура на рамката на RTU
Комплетна рамка за податоци за инструкции во RTU се состои од следниве четири дела:

3.2 Пример за порака на RTU – Читање на регистри за задржување (код на функција 0x03)
[Порака за барање] Главниот уред ги чита регистрите за складирање на Slave 1 (почетна адреса 0x0001, читање 3 регистри):
01 03 00 01 00 03 54 0Б
Анализа бајт-по-бајт на пораката за барање:

[Порака за одговор] Помошната станица 1 враќа податоци од три регистри: 01,03,06,02,2B,00,00,00,64, D5, 87
Парсирање бајт-по-бајт на пораката за одговор:

3.3 Детално објаснување на стандардните функционални кодови

3.4 Детален опис на секој формат на порака за функционален код
(1) Читање на намотка / Читање на дискретен влез (Функциски кодови 0x01/0x02)
[Формат на рамка за барање] (вкупно 8 бајти)

[Формат на рамка за одговор]

[Пример за анализа на позиција] Податоците за одговор се состојат од 3 бајти (намотки 20–38):

(2)Читање на регистар за задржување/Читање на влезен регистар (код на функција 0x03/0x04)
[Формат на рамка за барање] (вкупно 8 бајти)

[Формат на рамка за одговор]

(3) Запишување на регистар со едно задржување (код на функција 0x06)
[Формат на рамка за барање] (вкупно 8 бајти)

[Рамка за одговор] Идентична со рамката за барање, таа потврдува успешно пишување.
(4)Запишување на повеќе регистри за одржување (код на функција 0x10)
[Барај формат на рамка]

[Формат на рамка за одговор] (вкупно 8 бајти): [Адреса][0x10][Почетна адреса (2 бајти)][Број (2 бајти)][CRC (2 бајти)]
(5)Запишување на една намотка (Код на функција: 0x05)
[Формат на рамка за барање] (вкупно 8 бајти): Поддржани се само две валидни вредности за запишување:
- 0xFF00 – Намотката е поставена на ВКЛУЧЕНО (затворено)
- 0x0000 – Намотката е поставена на OFF (отворена)

[Рамка за одговор] Идентична со рамката за барање, таа потврдува успешно пишување.
IV. Детална анализа на Modbus TCP пораките
Modbus TCP работи преку Ethernet TCP/IP протоколот, користејќи го портот 502 како стандарден. За разлика од RTU режимот, Modbus TCP користи MBAP (Modbus Application Protocol) заглавие за да ги дефинира границите на пораките и не бара CRC верификација (наместо тоа се потпира на вградениот механизам за проверка на грешки на TCP протоколот).
4.1 Структура на заглавието на MBAP (7 бајти, вклучени во сите TCP пакети)

4.2 Пример за TCP порака на Modbus
[Порака за барање] Читање на регистарот за задржување на Slave 1 (почетна адреса 0x0000, читање 3 вредности):
00 01 00 00 00 06 01 03 00 00 00 03
Анализа поле по поле на пораката за барање:

[Одговорна порака] Робот враќа податоци од три регистри:
00 01 00 00 00 09 01 03 06 02 2B 00 00 00 64
Парсирање поле-по-поле на пораката за одговор:

4.3 Основни разлики помеѓу структурите на пакети RTU и TCP

V. Детално објаснување на верификацијата CRC-16
Алгоритмот CRC (Cyclic Redundancy Check) е механизам за верификација на рамки на Modbus RTU-ата, дизајниран да детектира грешки за време на преносот на пораките. Полиномот што генерира CRC-16 е x¹⁶ + x¹⁵ + x² + 1 (еквивалентно на 0x8005); во пракса, се користи инвертираниот полином 0xA001.
5.1 Чекори за пресметка на CRC-16
6.1. Иницијализирајте го 16-битниот CRC регистар на 0xFFFF
7.2. Извршете XOR операција помеѓу првиот бајт и долните 8 бита од CRC регистарот; зачувајте го резултатот назад во долните 8 бита од CRC регистарот
8.3. Поместете го CRC регистарот надесно за 1 бит, пополнувајќи ги високите битови со 0; одредете го битот за поместување нанадвор (LSB):
9.4. Ако битот за поместување нанадвор е 0: Продолжете со поместување надесно само за 1 бит
10.5. Ако битот за поместување е 1: Извршете XOR операција помеѓу CRC регистарот и 0xA001
11.6. Повторете го чекор 3 додека не заврши обработката на сите 8 бита од тековниот бајт
12.7. Земете го следниот бајт и повторете ги чекорите 2–6 додека не се обработат сите бајти 13.8. Откако ќе завршите со целата обработка на бајти, заменете ги највисоките и најниските бајти на CRC регистарот за да ја добиете конечната контролна сума.
14.9. Додадете ја конечната контролна сума на крајот од пораката, со најнискиот бајт прв, а најгорниот бајт последен
5.2 Пример за пресметка на CRC-16 (Python код)
Следната Python функција може директно да се користи за пресметување на CRC-16 контролната сума за Modbus RTU:
def modbus_crc16(податоци: бајти) -> бајти:
"""бројува код за проверка на Modbus RTU CRC-16 (Вратете ги првите два бајти со најмалку значаен бит прво)"""
crc = 0xFFFF
за бајт во податоци:
crc ^= бајт
за _ во опсег(8):
ако crc & 0x0001:
crc = (crc >> 1) ^ 0xA001
друго:
crc >>= 1
# Врати го прво најнискиот бајт, а потоа највисокиот бајт
врати бајти([crc & 0xFF, (crc >> 8) & 0xFF])
# дадете типични примери: броење 01 03 00 01 00 03 CRC
рамка = бајти ([0x01, 0x03, 0x00, 0x01, 0x00, 0x03])
crc = modbus_crc16(рамка)
печатење(crc.hex()) # извоз:540b(0x54 0x0B)
5.3 Локација на CRC Проверете ја пораката
Користејќи ја пораката за барање 01 03 00 01 00 03 54 0B како пример:

Приемникот ја пресметува повторно CRC вредноста на првите 6 бајти и ја споредува со последните 2 бајти од пакетот. Ако тие се разликуваат, се детектира грешка во преносот и не се враќа одговор.
Ⅵ.Работење со исклучоци и детали за кодот за грешка
Кога помошната станица не може да изврши барање од главната станица (на пр., поради неподдржани функционални кодови или адреса надвор од опсегот), таа враќа рамка за одговор на исклучок. Кодот на функцијата за одговор на исклучок е = оригинален функционален код + 0x80 (т.е. највисокиот бит е поставен на 1).
6.1 Формат на абнормален одговор (RTU)
[Адреса на роб [Функциски код | 0x80] [Абнормален код] [CRC-16]

6.2 Значење на стандардните кодови за исклучоци

6.3 Пример за абнормален одговор
[Сценарио] Главната станица бара да прочита регистар на невалидна адреса од помошната станица 1, а помошната станица враќа исклучок:
Барање: 01 03 00 20 00 01 XX XX (читачки регистар на адреса 0x0020);
Одговор на исклучок: 01 83 02 C0 F1;
Бајт по бајт анализа на одговорот на исклучокот:

VI. Вовед во Modbus ASCII пораките
Режимот Modbus ASCII ги кодира сите бајти од податоци како два ASCII знаци (на пр., 0x0F е кодиран како „0F“). Иако е лесно читлив, нуди ниска ефикасност на пренос и првенствено се користи за цели на дебагирање.
7.1ASCII структура на рамка
Целосен ASCII формат на рамка:

7.2 Алгоритам за верификација на LRC
Чекори за пресметување на LRC (Проверка на лонгитудинална редундантност):
15.1. Извршете бинарно собирање на сите бајти од полето за адреса, функционалниот код и полето за податоци (со исклучок на маркерите за почеток и крај).
16.2. Игнорирај ги битовите за носење (ако резултатот надмине 255, автоматски ќе се заокружи и ќе се задржат само долните 8 бита).
17.3. Пресметајте го комплементот на резултатот од сумирањето модул 1 (т.е. 0xFF − сума).
18.4. Зголемете го комплементот за 1 за да го добиете конечниот LRC контролен код (1 бајт).
19.5. Кодирајте го LRC контролниот код како два ASCII знаци и додадете ги на крајот од пораката.
VIII. Практични совети и вообичаени проблеми
8.1 Проблеми со редоследот на бајтите (голем-ендијан/микро-ендијан)
На Модбус стандард користи голем крај (со бајтот од повисок ред прво) за пренос на 16-битни или подолги податоци. Некои уреди (на пр., одредени уреди базирани на ARM) користат микро крај; конверзијата на редоследот на бајтите е потребна за да се избегнат грешки во нумеричкото парсирање.

8.2 Ограничување на големината на единицата за регистрација (PDU ≤ 253 бајти)

8.3 Препораки за конфигурација на истекување на времето за комуникација и повторен обид
Препорачани конфигурации:
- Интервал на анкетирање: Поставено на 2–3 пати од максималното време на одговор на помошната единица (обично 100–500 ms) • Времетраење на истекот на времето: Препорачан опсег од 1000–3000 ms, може да се прилагоди врз основа на брзината на одговор на помошната единица
- Обиди за повторен обид: Препорачана граница од 3; активирајте аларм ако не успеете
- Анкетирање од повеќе страни: Закажување на променливи интервали на анкетирање меѓу страните за да се спречат конфликти со магистралата • Истекување на време од бајти: Во RTU режим, интервалот на знаци што надминува 1,5 знаци се смета за грешка во рамката
8.4 Препорачани алатки за отстранување грешки
Додаток: Табела со брзи референци за заеднички пораки
Читање на намотка (код на функција 0x01)
[Барање]: Читање од помошната станица 1 на почетната адреса 0 (намотка 1), добивање 8 пораки за статус на намотката: 01 01 00 00 00 08 3D CC
[Одговор]: Осум статуси на намотки: 0x55 (01010101B);
Порака: 01 01 01 55 94 36
Запишување на една намотка (код на функција 0x05)
[Барање] Поставете ја намотката на адреса 0 на ВКЛУЧЕНО (вредност за запишување 0xFF00):
Порака: 01 05 00 00 FF 00 8C 3A
[Барање] Поставете ја намотката на адреса 0 на OFF (вредност за запишување 0x0000):
Порака: 01 05 00 00 00 00 CD CA
[Одговор] Идентично со рамката на барањето
Запишување во еден регистар (код на функција 0x06):
[Барање] Напишете ја вредноста 0x1234 за да се регистрира на адреса 0.
Порака: 01 06 00 00 12 34 XX XX (XX е CRC, треба да се пресмета).
[Одговор] Идентично со рамката на барањето.
Запишување во повеќе регистри (код на функција 0x10)
[Барање]: Запишување во два регистра почнувајќи од адреса 0 со вредности 0x1234 и 0xABCD соодветно.
Порака: 01 10 00 00 00 02 04 12 34 AB CD XX XX
[Одговор]: Врати ја почетната адреса и бројот на запишани регистри.
Порака: 01 10 00 00 00 02 41 C8
Читање на влезни регистри (код на функција 0x04)
[Барање]: Читање од роб 1 на почетна адреса 0, читање на два влезни регистри
пораки: 01 04 00 00 00 02 71 CB
[Одговор]: Врати две вредности на влезниот регистар
пораки: 01 04 04 00 64 01 90 XX XX (Вратени вредности: 100 и 400)










