Куда посылать команду Modbus TCP?
В сети Ethernet адресом устройства является его IP-адрес. Обычно устройства находятся в одной подсети, где IP-адреса отличаются последними цифрами (например, 192.168.1.20) при использовании маски подсети 255.255.255.0. Интерфейсом служит сеть Ethernet, а протоколом передачи данных — TCP/IP.
Для передачи команд используется TCP-порт 502.
Описание протокола Modbus TCP
Команда Modbus TCP состоит из части сообщения Modbus RTU и специального заголовка MBAP (Modbus Application Header).
Из сообщения Modbus RTU удаляются:
- SlaveID (адрес устройства) в начале сообщения;
- CRC (контрольная сумма) в конце сообщения.
Получившаяся часть называется PDU (Protocol Data Unit).
Пример запроса Modbus RTU для чтения значений аналогового выхода (holding registers) из регистров #40108–40110 с адресом устройства 17
11 03 006B 0003 7687
- 11 — Адрес устройства (SlaveID, 17 в десятичной системе = 11 в шестнадцатеричной системе);
- 03 — Функциональный код (Function Code, чтение Analog Output Holding Registers);
- 006B — Адрес первого регистра (40108 − 40001 = 107 = 6B hex);
- 0003 — Количество регистров для чтения (3 регистра: 40108, 40109, 40110);
- 7687 — Контрольная сумма (CRC).
Удалив адрес устройства (SlaveID) и контрольную сумму (CRC), получаем PDU:
03 006B 0003
К началу PDU добавляется новый 7-байтовый заголовок MBAP Header, который содержит:
- Transaction Identifier (2 байта): идентификатор транзакции, устанавливаемый Master для уникальной идентификации каждого запроса. Повторяется устройством Slave в ответе.
- Protocol Identifier (2 байта): идентификатор протокола, всегда равен 00 00 для Modbus.
- Length (2 байта): длина сообщения в байтах от Unit Identifier до конца сообщения.
- Unit Identifier (1 байт): адрес устройства, устанавливаемый Master. Повторяется Slave для идентификации устройства.
Итоговая структура сообщений
| Протокол | Slave ID / MBAP Header | Запрос / PDU | 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 |
Расшифровка Modbus TCP:
- 0001 — Идентификатор транзакции (Transaction Identifier);
- 0000 — Идентификатор протокола (Protocol Identifier);
- 0006 — Длина сообщения (6 байтов после заголовка);
- 11 — Адрес устройства (Unit Identifier, 17 в десятичной системе = 11 в шестнадцатеричной системе);
- 03 — Функциональный код (Function Code, чтение Analog Output Holding Registers);
- 006B — Адрес первого регистра (40108 − 40001 = 107 = 6B hex);
- 0003 — Количество регистров для чтения (3 регистра: 40108, 40109, 40110).
Пример ответа от устройства Modbus TCP Slave
0001 0000 0009 11 03 06 022B 0064 007F
Расшифровка ответа:
- 0001 — Идентификатор транзакции (Transaction Identifier);
- 0000 — Идентификатор протокола (Protocol Identifier);
- 0009 — Длина сообщения (9 байтов после заголовка);
- 11 — Адрес устройства (Unit Identifier, 17 в десятичной системе = 11 в шестнадцатеричной системе);
- 03 — Функциональный код (Function Code, чтение Analog Output Holding Registers);
- 06 — Количество байтов в данных (6 байтов);
- 022B — Значение регистра AO0 (старший разряд: 02 hex, младший разряд: 2B hex, итог: 555 в десятичной системе);
- 0064 — Значение регистра AO1 (старший разряд: 00 hex, младший разряд: 64 hex, итог: 100 в десятичной системе);
- 007F — Значение регистра AO2 (старший разряд: 00 hex, младший разряд: 7F hex, итог: 127 в десятичной системе).
Итоги
- AO0: 02 2B hex = 555 (десятичная система);
- AO1: 00 64 hex = 100 (десятичная система);
- AO2: 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).
В запросе указывается начальный адрес первого регистра DO и количество необходимых значений. Адресация DO начинается с нуля.
Значения DO возвращаются в ответе в одном или нескольких байтах, где:
- 1 означает включенное состояние (ON),
- 0 — выключенное состояние (OFF).
Младший бит первого байта данных соответствует первому запрашиваемому адресу DO, остальные биты — последующим адресам. Если запрашивается менее 8 значений, неиспользованные биты заполняются нулями.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 00 | Длина сообщения | 00 | Длина сообщения |
| 06 | 04 | ||
| 01 | Адрес устройства | 01 | Адрес устройства |
| 01 | Функциональный код | 01 | Функциональный код |
| 00 | Адрес первого регистра (Hi) | 01 | Количество байт далее |
| 00 | Адрес первого регистра (Lo) | 02 | Значение регистра DO 0-1 |
| 00 | Количество регистров (Hi) | ||
| 02 | Количество регистров (Lo) |
Пример результата: Состояния DO0-1 представлены значением 0x02 (в двоичном виде: 0000 0010).
- DO1 (второй справа бит) = 1 (ON).
- DO0 (первый справа бит) = 0 (OFF).
Остальные 6 бит заполнены нулями.
Отправка команды Modbus TCP для чтения дискретного ввода (0x02)
Эта команда используется для чтения значений дискретных входов (DI).
Структура запроса и ответа аналогична команде 0x01, но функциональный код заменяется на 0x02.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 00 | Длина сообщения | 00 | Длина сообщения |
| 06 | 04 | ||
| 01 | Адрес устройства | 01 | Адрес устройства |
| 02 | Функциональный код | 02 | Функциональный код |
| 00 | Адрес первого регистра (Hi) | 01 | Количество байт далее |
| 00 | Адрес первого регистра (Lo) | 03 | Значение регистра DI 0-1 |
| 00 | Количество регистров (Hi) | ||
| 02 | Количество регистров (Lo) |
Пример результата: Состояния DI0-1 представлены значением 0x03 (в двоичном виде: 0000 0011).
- DI1 (второй справа бит) = 1 (ON).
- DI0 (первый справа бит) = 1 (ON).
Остальные 6 бит заполнены нулями.
Отправка команды Modbus TCP для чтения аналогового вывода (0x03)
Команда 0x03 используется для чтения значений аналоговых выходов (AO).
В запросе указывается начальный адрес первого регистра AO и количество регистров, которые необходимо прочитать. Каждый регистр содержит 16-битное значение.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 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 (в шестнадцатеричной системе), что соответствует значению 555 в десятичной системе.
- Значение AO1 представлено байтами 00 64 (в шестнадцатеричной системе), что соответствует значению 100 в десятичной системе.
Каждое значение регистра занимает 2 байта, где:
- Старший байт (Hi) передает старшие 8 бит значения,
- Младший байт (Lo) передает младшие 8 бит значения.
Отправка команды Modbus TCP для чтения аналогового ввода (0x04)
Команда 0x04 используется для чтения значений аналоговых входов (AI).
В запросе указывается начальный адрес первого регистра AI и количество регистров, которые необходимо прочитать. Каждый регистр содержит 16-битное значение.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 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 (в шестнадцатеричной системе), что соответствует значению 10 в десятичной системе.
- Значение AI1 представлено байтами 00 64 (в шестнадцатеричной системе), что соответствует значению 100 в десятичной системе.
Каждое значение регистра занимает 2 байта, где:
- Старший байт (Hi) передает старшие 8 бит значения,
- Младший байт (Lo) передает младшие 8 бит значения.
Отправка команды Modbus TCP для записи дискретного вывода (0x05)
Команда 0x05 используется для записи значения одного дискретного выхода (DO).
- Значение FF 00 (в шестнадцатеричной системе) устанавливает выход в состояние включен (ON).
- Значение 00 00 устанавливает выход в состояние выключен (OFF).
- Любые другие значения недопустимы и не изменят состояние выхода.
Ответ на запрос представляет собой эхо-запрос (повтор запроса), который подтверждает изменение состояния выхода.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 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 в положение включен (ON), используя значение FF 00.
- Ответ: подтверждает выполнение команды, повторяя запрос.
Состояние DO1 изменилось с выключен (OFF) на включен (ON).
Отправка команды Modbus TCP для записи аналогового вывода (0x06)
Команда 0x06 используется для записи одного значения аналогового выхода (AO).
Ответ на запрос представляет собой эхо-запрос (повтор запроса), который подтверждает успешное выполнение команды.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 00 | Длина сообщения | 00 | Длина сообщения |
| 06 | 06 | ||
| 01 | Адрес устройства | 01 | Адрес устройства |
| 06 | Функциональный код | 06 | Функциональный код |
| 00 | Адрес регистра (Hi) | 00 | Адрес регистра (Hi) |
| 01 | Адрес регистра (Lo) | 01 | Адрес регистра (Lo) |
| 55 | Значение (Hi) | 55 | Значение (Hi) |
| FF | Значение (Lo) | FF | Значение (Lo) |
Пример результата
В данном случае:
- Запрос: записывает значение 55 FF (в шестнадцатеричной системе) в регистр AO0.
- Ответ: подтверждает выполнение команды, повторяя запрос.
Результат:
- Состояние выхода AO0 изменилось на значение 55 FF (в шестнадцатеричной системе), что соответствует значению 22015 в десятичной системе.
Каждое значение состоит из 2 байт:
- Старший байт (Hi) содержит старшие 8 бит значения,
- Младший байт (Lo) содержит младшие 8 бит значения.
Отправка команды Modbus TCP для записи нескольких дискретных выводов (0x0F)
Команда 0x0F используется для записи нескольких значений дискретных выходов (DO).
В запросе указывается начальный адрес первого регистра, количество регистров, которые нужно записать, и их значения. Значения передаются в виде битов, где:
- 1 — выход включен (ON),
- 0 — выход выключен (OFF).
Ответ на запрос подтверждает успешную запись, возвращая количество записанных регистров.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 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 | Значение байт |
Пример результата:
- Запрос:
Указывает начальный адрес регистра DO0.
Записывает значения двух регистров:
- DO1 изменяется на включен (ON),
- DO0 остается выключен (OFF).
Значения передаются как 02 (в шестнадцатеричной системе), что соответствует 0000 0010 в двоичном виде.
- Ответ: подтверждает, что два регистра успешно записаны.
Результат:
Состояние выходов:
- DO1: включен (ON),
- DO0: выключен (OFF).
Остальные биты в байте значения остаются заполненными нулями, так как они не используются.
Отправка команды Modbus TCP для записи нескольких аналоговых выводов (0x10)
Команда 0x10 используется для записи нескольких значений аналоговых выходов (AO).
В запросе указываются начальный адрес первого регистра, количество регистров для записи и их значения. Значения передаются в виде 16-битных слов (2 байта на каждое значение).
Ответ на запрос подтверждает успешную запись, возвращая количество записанных регистров.
Пример структуры запроса и ответа
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 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.
Записывает значения двух регистров:
- AO0 изменяется на 00 0A (в шестнадцатеричной системе), что соответствует 10 в десятичной системе.
- AO1 изменяется на 01 02 (в шестнадцатеричной системе), что соответствует 258 в десятичной системе.
- Ответ: подтверждает, что два регистра успешно записаны.
Результат:
Состояния выходов:
- AO0: 10 (десятичное значение),
- AO1: 258 (десятичное значение).
Каждое значение занимает 2 байта:
- Старший байт (Hi) содержит старшие 8 бит значения,
- Младший байт (Lo) содержит младшие 8 бит значения.
Ошибки запроса Modbus TCP
Если устройство не может обработать полученный запрос, оно отправляет ответ с кодом ошибки. В ответе функциональный код изменяется: его старший бит устанавливается в 1, чтобы указать на ошибку.
Пример изменения функционального кода в случае ошибки:
| Функциональный код в запросе | Функциональный код ошибки в ответе | Бинарное представление |
|---|---|---|
| 01 (01 hex) | 129 (81 hex) | 0000 0001 → 1000 0001 |
| 02 (02 hex) | 130 (82 hex) | 0000 0010 → 1000 0010 |
| 03 (03 hex) | 131 (83 hex) | 0000 0011 → 1000 0011 |
| 04 (04 hex) | 132 (84 hex) | 0000 0100 → 1000 0100 |
| 05 (05 hex) | 133 (85 hex) | 0000 0101 → 1000 0101 |
| 06 (06 hex) | 134 (86 hex) | 0000 0110 → 1000 0110 |
| 15 (0F hex) | 143 (8F hex) | 0000 1111 → 1000 1111 |
| 16 (10 hex) | 144 (90 hex) | 0001 0000 → 1001 0000 |
Пример запроса и ответа с ошибкой
| Байт | Запрос | Байт | Ответ |
|---|---|---|---|
| 01 | Идентификатор транзакции | 01 | Идентификатор транзакции |
| 02 | Идентификатор протокола | 02 | Идентификатор протокола |
| 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) | Устройство отсутствует в сети или не отвечает. |
Итог:
Если запрос обработан с ошибкой, ведущее устройство получает модифицированный функциональный код и код ошибки, указывающий на причину проблемы. Это позволяет эффективно диагностировать и устранять неполадки.
Программы для работы с протоколом Modbus TCP
Ниже представлены программы, которые помогут легко взаимодействовать с устройствами Modbus TCP.
Modbus TCP client с поддержкой Modbus TCP. Скачать
Modbus TCP client с поддержкой Modbus TCP. Скачать