В этой статье вы узнаете о протоколе Modbus TCP, который является развитием протокола Modbus RTU. Англоязычная версия статьи доступна на ipc2u.com.
Оглавление:
- Куда посылать команду Modbus TCP?
- Описание протокола Modbus TCP
- Типы команд Modbus TCP
- Как послать команду на чтение дискретного вывода? Команда 0x01
- Как послать команду на чтение дискретного ввода? Команда 0x02
- Как послать команду на чтение аналогового вывода? Команда 0x03
- Как послать команду на чтение аналогового ввода? Команда 0x04
- Как послать команду на запись дискретного вывода? Команда 0x05
- Как послать команду на запись аналогового вывода? Команда 0x06
- Как послать команду на запись нескольких дискретных выводов? Команда 0x0F
- Как послать команду на запись нескольких аналоговых выводов? Команда 0x10
- Ошибки запроса Modbus TCP
- Программы для работы с протоколом Modbus TCP
Куда посылать команду Modbus TCP?
В сети Ethernet адресом устройства является его IP-адрес. Обычно устройства находятся в одной подсети, где IP адреса отличаются последними цифрами 192.168.1.20 при использовании самой распространённой маски подсети 255.255.255.0.
Интерфейсом является сеть Ethernet, протоколом передачи данных – TCP/IP.
Используемый TCP-порт: 502.
Описание протокола Modbus TCP
Команда Modbus TCP состоит из части сообщения Modbus RTU и специального заголовка.
О Modbus RTU написано в этой статье.
Из сообщения Modbus RTU удаляется SlaveID адрес в начале и CRC контрольная сумма в конце, что образует PDU, Protocol Data Unit.
Ниже приведен пример запроса Modbus RTU для получения значения AO аналогового выхода (holding registers) из регистров от #40108 до 40110 с адресом устройства 17.
11 03 006B 0003 7687
11 | Адрес устройства SlaveID (17 = 11 hex) |
03 | Функциональный код Function Code (читаем Analog Output Holding Registers) |
006B | Адрес первого регистра (40108-40001 = 107 =6B hex) |
0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) |
7687 | Контрольная сумма CRC |
Отбрасываем адрес устройства SlaveID и контрольную сумму CRC и получаем PDU:
03 006B 0003
К началу получившегося сообщения PDU добавляется новый 7-байтовый заголовок, который называется MBAP Header (Modbus Application Header). Этот заголовок имеет следующие данные:
Transaction Identifier (Идентификатор транзакции): 2 байта устанавливаются Master, чтобы однозначно идентифицировать каждый запрос. Может быть любыми. Эти байты повторятся устройством Slave в ответе, поскольку ответы устройства Slave не всегда могут быть получены в том же порядке, что и запросы.
Protocol Identifier (Идентификатор протокола): 2 байта устанавливаются Master, всегда будут = 00 00, что соответствует протоколу Modbus.
Length (Длина): 2 байта устанавливаются Master, идентифицирующие число байтов в сообщении, которые следуют далее. Считается от Unit Identifier до конца сообщения.
Unit Identifier (Идентификатор блока или адрес устройства): 1 байт устанавливается Master. Повторяется устройством Slave для однозначной идентификации устройства Slave.
Итого получаем:
Modbus RTU | Slave ID | Запрос | CRC |
---|---|---|---|
Modbus RTU | 11 | 03 006B 0003 | 7687 |
Modbus TCP | 0001 0000 0006 11 | 03 006B 0003 | |
Modbus TCP | MBAP Header | PDU | |
Modbus TCP | ADU, Application Data Unit |
Где:
0001 | Идентификатор транзакции | Transaction Identifier |
0000 | Идентификатор протокола | Protocol Identifier |
0006 | Длина (6 байтов идут следом) | Message Length |
11 | Адрес устройства (17 = 11 hex) | Unit Identifier |
03 | Функциональный код (читаем Analog Output Holding Registers) | Function Code |
006B | Адрес первого регистра (40108-40001 = 107 =6B hex) | Data Address of the first register |
0003 | Количество требуемых регистров (чтение 3-х регистров с 40108 по 40110) | The total number of registers |
В ответе от Modbus TCP Slave устройства мы получим:
0001 0000 0009 11 03 06 022B 0064 007F
Где:
0001 | Идентификатор транзакции | Transaction Identifier |
0000 | Идентификатор протокола | Protocol Identifier |
0009 | Длина (9 байтов идут следом) | Message Length |
11 | Адрес устройства (17 = 11 hex) | Unit Identifier |
03 | Функциональный код (читаем Analog Output Holding Registers) | Function Code |
06 | Количество байт далее (6 байтов идут следом) | Byte Count |
02 | Значение старшего разряда регистра (02 hex) | Register value Hi (AO0) |
2B | Значение младшего разряда регистра (2B hex) | Register value Lo (AO0) |
00 | Значение старшего разряда регистра (00 hex) | Register value Hi (AO1) |
64 | Значение младшего разряда регистра (64 hex) | Register value Lo (AO1) |
00 | Значение старшего разряда регистра (00 hex) | Register value Hi (AO2) |
7F | Значение младшего разряда регистра (7F hex) | Register value Lo (AO2) |
Регистр аналогового выхода AO0 имеет значение 02 2B HEX или 555 в десятичной системе.
Регистр аналогового выхода АО1 имеет значение 00 64 HEX или 100 в десятичной системе.
Регистр аналогового выхода АО2 имеет значение 00 7F HEX или 127 в десятичной системе.
Типы команд Modbus TCP
Приведем таблицу с кодами функций чтения и записи регистров Modbus TCP.
Код функции | Что делает функция | Тип значения | Тип доступа | |
---|---|---|---|---|
01 (0x01) | Чтение DO | Read Coil Status | Дискретное | Чтение |
02 (0x02) | Чтение DI | Read Input Status | Дискретное | Чтение |
03 (0x03) | Чтение AO | Read Holding Registers | 16 битное | Чтение |
04 (0x04) | Чтение AI | Read Input Registers | 16 битное | Чтение |
05 (0x05) | Запись одного DO | Force Single Coil | Дискретное | Запись |
06 (0x06) | Запись одного AO | Preset Single Register | 16 битное | Запись |
15 (0x0F) | Запись нескольких DO | Force Multiple Coils | Дискретное | Запись |
16 (0x10) | Запись нескольких AO | Preset Multiple Registers | 16 битное | Запись |
Как послать команду Modbus TCP на чтение дискретного вывода? Команда 0x01
Эта команда используется для чтения значений дискретных выходов DO.
В запросе PDU задается начальный адрес первого регистра DO и последующее количество необходимых значений DO. В PDU значения DO адресуются, начиная с нуля.
Значения DO в ответе находятся в одном байте и соответствуют значению битов.
Значения битов определяются как 1 = ON и 0 = OFF.
Младший бит первого байта данных содержит значение DO адрес которого указывался в запросе. Остальные значения DO следуют по нарастающей к старшему значению байта. Т.е. справа налево.
Если запрашивалось меньше восьми значений DO, то оставшиеся биты в ответе будут заполнены нулями (в направлении от младшего к старшему байту). Поле Byte Count Количество байт далее указывает количество полных байтов данных в ответе.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 04 | ||
01 | Адрес устройства | 01 | Адрес устройства |
01 | Функциональный код | 01 | Функциональный код |
00 | Адрес первого регистра Hi байт | 01 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 02 | Значение регистра DO 0-1 |
00 | Количество регистров Hi байт | ||
02 | Количество регистров Lo байт |
Состояния выходов DO0-1 показаны как значения байта 02 hex, или в двоичной системе 0000 0010.
Значение DO1 будет вторым справа, а значение DO0 будет первым справа (младший бит).
Шесть остальных битов заполнены нулями до полного байта, т.к. их не запрашивали.
Каналы | - | - | - | - | - | - | DO 1 | DO 0 |
Биты | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
Hex | 02 |
Модули с дискретным выводом: ioLogik E1211, ET-7060, ADAM-6060
Как послать команду Modbus TCP на чтение дискретного ввода? Команда 0x02
Эта команда используется для чтения значений дискретных входов DI.
Запрос и ответ для DI похож на запрос для DO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 04 | ||
01 | Адрес устройства | 01 | Адрес устройства |
02 | Функциональный код | 02 | Функциональный код |
00 | Адрес первого регистра Hi байт | 01 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 03 | Значение регистра DI 0-1 |
00 | Количество регистров Hi байт | ||
02 | Количество регистров Lo байт |
Состояния выходов DI 0-1 показаны как значения байта 03 hex, или в двоичной системе 0000 0011.
Значение DI1 будет вторым справа, а значение DI0 будет первым справа (младший бит).
Шесть остальных битов заполнены нулями.
Модули с дискретным вводом: ioLogik E1210, ET-7053, ADAM-6050
Как послать команду Modbus TCP на чтение аналогового вывода? Команда 0x03
Эта команда используется для чтения значений аналоговых выходов AO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 07 | ||
01 | Адрес устройства | 01 | Адрес устройства |
03 | Функциональный код | 03 | Функциональный код |
00 | Адрес первого регистра Hi байт | 04 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 02 | Значение регистра Hi (AO0) |
00 | Количество регистров Hi байт | 2B | Значение регистра Lo (AO0) |
02 | Количество регистров Lo байт | 00 | Значение регистра Hi (AO1) |
64 | Значение регистра Lo (AO1) |
Состояния выхода AO0 показаны как значения байта 02 2B hex, или в десятичной системе 555.
Состояния выхода AO1 показаны как значения байта 00 64 hex, или в десятичной системе 100.
Модули с дискретным вводом: ioLogik E1210, ET-7053, ADAM-6050
Как послать команду Modbus TCP на чтение аналогового ввода? Команда 0x04
Эта команда используется для чтения значений аналоговых входов AI.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 07 | ||
01 | Адрес устройства | 01 | Адрес устройства |
04 | Функциональный код | 04 | Функциональный код |
00 | Адрес первого регистра Hi байт | 04 | Количество байт далее |
00 | Адрес первого регистра Lo байт | 00 | Значение регистра Hi (AI0) |
00 | Количество регистров Hi байт | 0A | Значение регистра Lo (AI0) |
02 | Количество регистров Lo байт | 00 | Значение регистра Hi (AI1) |
64 | Значение регистра Lo (AI1) |
Состояния выхода AI0 показаны как значения байта 00 0A hex, или в десятичной системе 10.
Состояния выхода AI1 показаны как значения байта 00 64 hex, или в десятичной системе 100.
Модули с аналоговым вводом: ioLogik E1240, ET-7017-10, ADAM-6217
Как послать команду Modbus TCP на запись дискретного вывода? Команда 0x05
Эта команда используется для записи одного значения дискретного выхода DO.
Значение FF 00 hex устанавливает выход в состояние включен ON.
Значение 00 00 hex устанавливает выход в состояние выключен OFF.
Все остальные значения недопустимы и не будут влиять на состояние выхода.
Нормальный ответ на такой запрос - это эхо (повтор запроса в ответе), возвращается после того, как состояние DO было изменено.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
05 | Функциональный код | 05 | Функциональный код |
00 | Адрес регистра Hi байт | 00 | Адрес регистра Hi байт |
01 | Адрес регистра Lo байт | 01 | Адрес регистра Lo байт |
FF | Значение Hi байт | FF | Значение Hi байт |
00 | Значение Lo байт | 00 | Значение Lo байт |
Состояние выхода DO1 поменялось с выключен OFF на включен ON.
Модули с дискретным выводом: ioLogik E1211, ET-7060, ADAM-6060
Как послать команду Modbus TCP на запись аналогового вывода? Команда 0x06
Эта команда используется для записи одного значения аналогового выхода AO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
06 | Функциональный код | 06 | Функциональный код |
00 | Адрес регистра Hi байт | 00 | Адрес регистра Hi байт |
01 | Адрес регистра Lo байт | 01 | Адрес регистра Lo байт |
55 | Значение Hi байт | 55 | Значение Hi байт |
FF | Значение Lo байт | FF | Значение Lo байт |
Состояние выхода AO0 поменялось на 55 FF hex, или в десятичной системе 22015.
Модули с аналоговым выводом: ioLogik E1241, ET-7028, ADAM-6224
Как послать команду Modbus TCP на запись нескольких дискретных выводов? Команда 0x0F
Эта команда используется для записи нескольких значений дискретного выхода DO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
08 | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
0F | Функциональный код | 0F | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
00 | Адрес первого регистра Lo байт | 00 | Адрес первого регистра Lo байт |
00 | Количество регистров Hi байт | 00 | Кол-во записанных рег. Hi байт |
02 | Количество регистров Lo байт | 02 | Кол-во записанных рег. Lo байт |
01 | Количество байт далее | ||
02 | Значение байт |
Состояние выхода DO1 поменялось с выключен OFF на включен ON.
Состояние выхода DO0 осталось выключен OFF.
Модули с дискретным выводом: ioLogik E1211, ET-7060, ADAM-6060
Как послать команду Modbus TCP на запись нескольких аналоговых выводов? Команда 0x10
Эта команда используется для записи нескольких значений аналогового выхода AO.
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
0B | 06 | ||
01 | Адрес устройства | 01 | Адрес устройства |
10 | Функциональный код | 10 | Функциональный код |
00 | Адрес первого регистра Hi байт | 00 | Адрес первого регистра Hi байт |
00 | Адрес первого регистра Lo байт | 00 | Адрес первого регистра Lo байт |
00 | Количество регистров Hi байт | 00 | Кол-во записанных рег. Hi байт |
02 | Количество регистров Lo байт | 02 | Кол-во записанных рег. Lo байт |
04 | Количество байт далее | ||
00 | Значение Hi AO0 байт | ||
0A | Значение Lo AO0 байт | ||
01 | Значение Hi AO1 байт | ||
02 | Значение Lo AO1 байт |
Состояние выхода AO0 поменялось на 00 0A hex, или в десятичной системе 10.
Состояние выхода AO1 поменялось на 01 02 hex, или в десятичной системе 258.
Модули с аналоговым выводом: ioLogik E1241, ET-7028, ADAM-6224
Ошибки запроса Modbus TCP
Если после получения запроса устройство не может обработать его, то будет отослан ответ с кодом ошибки.
Ответ будет содержать измененный Функциональный код, его старший бит будет равен 1.
Пример:
Было | Стало |
---|---|
Функциональный код в запросе | Функциональный код ошибки в ответе |
01 (01 hex) 0000 0001 | 129 (81 hex) 1000 0001 |
02 (02 hex) 0000 0010 | 130 (82 hex) 1000 0010 |
03 (03 hex) 0000 0011 | 131 (83 hex) 1000 0011 |
04 (04 hex) 0000 0100 | 132 (84 hex) 1000 0100 |
05 (05 hex) 0000 0101 | 133 (85 hex) 1000 0101 |
06 (06 hex) 0000 0110 | 134 (86 hex) 1000 0110 |
15 (0F hex) 0000 1111 | 143 (8F hex) 1000 1111 |
16 (10 hex) 0001 0000 | 144 (90 hex) 1001 0000 |
Пример запроса и ответ с ошибкой:
Байт | Запрос | Байт | Ответ |
---|---|---|---|
(Hex) | Название поля | (Hex) | Название поля |
01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
02 | 02 | ||
00 | Идентификатор протокола | 00 | Идентификатор протокола |
00 | 00 | ||
00 | Длина сообщения | 00 | Длина сообщения |
06 | 03 | ||
0A | Адрес устройства | 0A | Адрес устройства |
01 | Функциональный код | 81 | Функциональный код с измененным битом |
04 | Адрес первого регистра Hi байт | 02 | Код ошибки |
A1 | Адрес первого регистра Lo байт | ||
00 | Количество регистров Hi байт | ||
01 | Количество регистров Lo байт |
Расшифровка кодов ошибок
01 | Принятый код функции не может быть обработан. |
02 | Адрес данных, указанный в запросе, недоступен. |
03 | Значение, содержащееся в поле данных запроса, является недопустимой величиной. |
04 | Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие. |
05 | Ведомое устройство приняло запрос и обрабатывает его, но это требует много времени. Этот ответ предохраняет ведущее устройство от генерации ошибки тайм-аута. |
06 | Ведомое устройство занято обработкой команды. Ведущее устройство должно повторить сообщение позже, когда ведомое освободится. |
07 | Ведомое устройство не может выполнить программную функцию, заданную в запросе. Этот код возвращается для не успешного программного запроса, использующего функции с номерами 13 или 14. Ведущее устройство должно запросить диагностическую информацию или информацию об ошибках от ведомого. |
08 | Ведомое устройство при чтении расширенной памяти обнаружило ошибку паритета. Ведущее устройство может повторить запрос, но обычно в таких случаях требуется ремонт. |
10 (0A hex) |
Шлюз неправильно настроен или перегружен запросами. |
11 (0B hex) |
Slave устройства нет в сети или от него нет ответа. |
Программы для работы с протоколом Modbus TCP
Ниже представлены программы, которые помогут легко взаимодействовать с устройствами Modbus TCP.
Modbus Master Tool с поддержкой Modbus RTU, ASCII, TCP. Скачать
Modbus TCP client с поддержкой Modbus TCP. Скачать