Реализация сервера Modbus TCP на S7‑1200: полное руководство
Применяемое ПО: TIA Portal V19 (подойдут V13–V20)
Оборудование: S7‑1200 (прошивка ≥4.2), S7‑1500 (прошивка ≥2.5)
Содержание
- Введение: что такое сервер Modbus TCP и зачем он нужен
- Отличие сервера (Slave) от клиента (Master)
- Преимущества использования встроенных библиотек Siemens
- Терминология и структура данных Modbus
- Объекты данных: катушки, дискретные входы, входные регистры, регистры хранения
- Как эти объекты отображаются в S7‑1200/1500
- Подготовка проекта в TIA Portal
- Требования к версиям ПО и прошивкам
- Создание блока данных с неоптимизированным доступом для регистров хранения
- Пошаговая настройка блока MB_SERVER
- 4.1. Добавление блока и настройка интерфейса
- 4.2. Создание структуры TCON_IP_v4 для соединения
- 4.3. Присвоение идентификатора интерфейса (InterfaceId)
- 4.4. Подача области регистров хранения на MB_HOLD_REG
- Ограничение доступа к катушкам и дискретным входам
- Зачем это нужно
- Установка QB_Count, QB_Read_Count, IB_Count = 0
- Проверка работоспособности
- Использование стороннего Modbus-клиента
- Контроль порядка байт (Endianness)
- Чтение и запись регистров хранения
- Особенности работы с разными типами данных
- Использование массивов WORD в оптимизированных DB
- Эксперименты: что работает, а что нет
- Рекомендации по выбору области памяти
- Типичные ошибки и способы их устранения
- Ошибка 8187 (некорректный указатель на MB_HOLD_REG)
- Неправильный идентификатор интерфейса
- Соединение не устанавливается (STATUS 7002)
- Путаница с порядком байт
- Неверный порт (502 vs 503)
- Заключение и дальнейшие шаги
- Когда использовать сервер, а когда клиент
- Переход к реализации клиента Modbus TCP
1. Введение: что такое сервер Modbus TCP и зачем он нужен
Протокол Modbus TCP — это промышленный стандарт обмена данными, работающий поверх TCP/IP. В паре «клиент-сервер» сервер (ранее называвшийся slave) ожидает входящих запросов и отвечает на них. Сервер никогда сам не инициирует передачу.
В контроллерах Siemens S7‑1200 поддержка сервера Modbus TCP реализована через встроенный функциональный блок MB_SERVER (находится в библиотеке Communication → Others → MODBUS TCP). Это бесплатное решение, не требующее дополнительных лицензий, в отличие от S7‑300/400.

Типичные задачи для сервера Modbus TCP:
- Предоставление данных из ПЛК системам верхнего уровня (SCADA, BMS, диспетчерские).
- Интеграция с устройствами, которые могут работать только как клиенты (например, некоторые HMI или контроллеры сторонних производителей).
- Организация точки доступа для диагностики и мониторинга.
2. Терминология и структура данных Modbus
Modbus оперирует четырьмя основными типами объектов. В традиционной реализации они привязаны к определённым областям памяти контроллера.
| Объект Modbus | Тип доступа | Традиционное отображение в Siemens | Назначение |
|---|---|---|---|
| Катушки (Coils) | Чтение / Запись | %Q (выходные биты) | Дискретные управляющие сигналы |
| Дискретные входы (Discrete Inputs) | Только чтение | %I (входные биты) | Дискретные сигналы от датчиков |
| Входные регистры (Input Registers) | Только чтение | %IW (входные слова) | Аналоговые значения (16 бит) |
| Регистры хранения (Holding Registers) | Чтение / Запись | Произвольная область (DB, M) | Числовые параметры, уставки, результаты |
В версиях библиотеки Modbus TCP до V5.0 доступ к катушкам, дискретным входам и входным регистрам был жёстко привязан к процессным образам I и Q. Начиная с V5.0 (S7‑1200 прошивка ≥4.2, S7‑1500 ≥2.5) появилась возможность переназначать эти объекты на любые битовые или словные области (например, в DB). Это даёт большую гибкость и безопасность.
3. Подготовка проекта в TIA Portal
3.1. Требования к версиям
| Контроллер | Минимальная прошивка | Версия библиотеки Modbus TCP |
|---|---|---|
| S7‑1200 | 4.2 | V5.0 (встроена в TIA Portal) |
| S7‑1500 | 2.5 | V5.0 (встроена в TIA Portal) |
Если у вас более старые версии, функциональность может быть ограничена (например, отсутствие возможности переназначать объекты). Рекомендуется обновить проект до актуальных версий.
3.2. Создание блока данных для регистров хранения
Регистры хранения – это самый важный объект, так как через них обычно передаются все числовые данные (REAL, INT, WORD и т.д.). Для их хранения создадим глобальный блок данных с неоптимизированным доступом.

Почему неоптимизированный?
Блоки с оптимизированным доступом хранят переменные не по фиксированным адресам, а в произвольном порядке. Блок MB_SERVER ожидает, что область памяти будет непрерывной и с известными смещениями. При использовании оптимизированного DB возможна ошибка 8187 (см. раздел «Типичные ошибки»).
Шаги:
- Добавить новый блок данных (Add new block → Data block). Назвать, например,
DB_Modbus_Holding. - Отключить оптимизированный доступ:
- Открыть свойства DB (правой кнопкой → Properties).
- На вкладке Attributes снять флажок Optimized block access.
- Подтвердить (система предупредит о возможной несовместимости, нажмите OK).
- Создать структуру внутри DB. Например, структуру
HoldingRegs, содержащую нужные переменные:textHoldingRegs : STRUCT Speed : REAL; // 2 регистра (4 байта) Current : REAL; // ещё 2 регистра StatusWord : WORD; // 1 регистр (2 байта) Setpoint : REAL; // 2 регистра // … и т.д. END_STRUCT;Или массивARRAY[0..99] OF WORD, если удобнее работать со словами. - Откомпилировать DB.
Важно: Порядок переменных в структуре определяет соответствие регистрам Modbus. Первая переменная будет занимать регистры с адреса 1 (если начинать с 1). Для REAL понадобится два регистра.
4. Пошаговая настройка блока MB_SERVER
4.1. Добавление блока и настройка интерфейса
- В OB1 (или другом циклическом блоке) добавьте вызов MB_SERVER из библиотеки.
- Создайте экземпляр (Instance DB) – можно оставить имя по умолчанию.
- Настройте входные параметры:
- CONNECT: ссылка на структуру соединения (создадим позже).
- MB_HOLD_REG: указатель на область регистров хранения (нашу структуру).
4.2. Создание структуры TCON_IP_v4
Для конфигурации TCP-соединения используем системный тип TCON_IP_v4. Объявим его в статической области экземпляра или в отдельном DB.
Поля структуры:
| Поле | Значение | Пояснение |
|---|---|---|
| InterfaceId | HW_ANY | Идентификатор сетевого интерфейса (будет присвоен позже) |
| ID | WORD | Уникальный идентификатор соединения (1…4096) |
| ConnectionType | BYTE | 11 (B#16#0B) – TCP |
| ActiveEstablished | BOOL | FALSE – сервер, не инициирует соединение |
| RemoteAddress | ARRAY[1..4] of BYTE | IP-адрес клиента (если нужно ограничить). Оставить 0 – любой |
| RemotePort | UINT | 0 – любой порт клиента |
| LocalPort | UINT | 502 – стандартный порт Modbus TCP |
Создание в коде (например, в статическом DB):
scl
CONNECT_Struct : TCON_IP_v4 := (
InterfaceId := 0, // временно
ID := 1,
ConnectionType := B#16#0B,
ActiveEstablished := FALSE,
RemoteAddress := [0,0,0,0],
RemotePort := 0,
LocalPort := 502
);
4.3. Присвоение идентификатора интерфейса (InterfaceId)
Перед вызовом MB_SERVER необходимо записать в CONNECT_Struct.InterfaceId правильный идентификатор сетевого интерфейса, через который будет работать сервер. Это может быть:
- встроенный PROFINET-порт (X1, X2),
- или CM/CP.
Способ 1: через системные константы (рекомендуется):
- Откройте аппаратную конфигурацию.
- Выделите нужный порт (например, PROFINET-интерфейс X1).
- Во вкладке System constants найдите переменную, начинающуюся с
Local~PROFINET_interfaceилиLocal~PN/IE. Скопируйте её имя. - В коде используйте эту константу.
Способ 2: прямая константа (для X1 у многих CPU это 64, но лучше не полагаться на это).
Пример присвоения в SCL:
scl
#CONNECT_Struct.InterfaceId := "Local~PROFINET_interface_1"; // имя из системных констант
4.4. Подача области регистров хранения
На вход MB_HOLD_REG подаём указатель на созданную структуру. Если в DB_Modbus_Holding есть структура HoldingRegs, то в SCL:
scl
MB_SERVER_DB(
CONNECT := #CONNECT_Struct,
MB_HOLD_REG := "DB_Modbus_Holding".HoldingRegs
);
В LAD/FBD можно просто перетащить переменную.
5. Ограничение доступа к катушкам и дискретным входам
По умолчанию MB_SERVER позволяет клиенту:
- читать и записывать катушки (биты %Q),
- читать дискретные входы (биты %I),
- читать входные регистры (слова %IW).
Это может быть нежелательно, так как сторонняя система получит прямой доступ к управлению выходами. Чтобы запретить доступ к этим объектам, установите соответствующие параметры экземпляра MB_SERVER в 0.
Где задавать:
Откройте экземпляр DB блока MB_SERVER (например, MB_SERVER_DB). В статических переменных найдите:
QB_Count– количество байт выходной области (катушек), доступных для записи.QB_Read_Count– количество байт выходной области, доступных для чтения.IB_Count– количество байт входной области (дискретных входов и входных регистров).
Установите их в 0. Можно сделать это прямо в коде перед вызовом:
scl
#MB_SERVER_DB.QB_Count := 0; #MB_SERVER_DB.QB_Read_Count := 0; #MB_SERVER_DB.IB_Count := 0;
После этого клиент при попытке обратиться к катушкам или входам получит ответ Illegal Data Address (код ошибки 0x02). Регистры хранения продолжат работать.
6. Проверка работоспособности
6.1. Загрузка и онлайн-мониторинг
Загрузите проект в контроллер. В онлайн-режиме откройте экземпляр MB_SERVER. Поле STATUS должно показывать 7002 – это не ошибка, а индикация того, что соединение установлено (ожидается подключение). Как только подключится клиент, статус изменится на 0 (без ошибок) или другой код.
6.2. Использование стороннего Modbus-клиента
Возьмите любой Modbus TCP клиент (например, ModScan, Simple Modbus TCP Client, или даже утилиту командной строки). Настройте:
- IP-адрес контроллера,
- порт 502,
- функцию: Read Holding Registers (чтение регистров хранения).
Если вы создали структуру из 5 регистров (как в примере), запросите 5 регистров, начиная с адреса 1. Проверьте, что значения соответствуют тем, которые вы записали в контроллере.
6.3. Порядок байт (Endianness)
Важный момент: в контроллерах Siemens используется little-endian (младший байт слова хранится по младшему адресу). Многие Modbus-клиенты по умолчанию ожидают big-endian. Поэтому при отображении значений может получиться «перевёрнутая» картина. Например, если в регистре хранения записано 16#1234, клиент может показать 16#3412.
Решения:
- Настроить клиент на «swap words» или «little-endian» режим.
- В самом контроллере поменять порядок байт перед записью в регистры (например, использовать функцию
SWAP).
В примере на скриншоте из оригинальной статьи клиент настроен на Float (Word Swap), что позволяет корректно отображать REAL.
7. Особенности работы с разными типами данных
7.1. Использование массивов WORD в оптимизированных DB
Интересный эксперимент: если в качестве MB_HOLD_REG подать массив ARRAY[0..9] OF WORD, объявленный в оптимизированном блоке данных, то это работает. Почему?
Потому что массив слов в оптимизированном DB всё равно располагается в непрерывной области памяти (оптимизация касается расположения отдельных элементов, но не внутренней структуры массива). Блок MB_SERVER, ожидая непрерывную область, может корректно с ней работать.
Однако для структур (особенно содержащих разнородные типы) оптимизированный доступ приводит к нарушению непрерывности и ошибке 8187.
Рекомендация: для надёжности используйте неоптимизированный DB со структурой. Так вы точно знаете, какому регистру соответствует каждая переменная.
7.2. Доступ к регистрам хранения в формате REAL
Для работы с REAL (32-битное число с плавающей точкой) выделите два последовательных регистра. При чтении/записи клиент должен интерпретировать пару регистров как одно число с плавающей точкой (32‑bit float). В структуре DB это будет выглядеть как одна переменная типа REAL.
7.3. Меркерная область (M-память)
В качестве MB_HOLD_REG можно использовать меркерные слова, например MW0. Это тоже непрерывная область, и она работает. Но для больших объёмов данных удобнее DB.
8. Типичные ошибки и способы их устранения
8.1. Ошибка 8187: «Invalid pointer. Data area is too small»
Симптом: В поле STATUS блока MB_SERVER появляется код 8187.
Причина: Указатель на MB_HOLD_REG указывает на область, которая не является непрерывной (например, структура в оптимизированном DB).
Решение: Используйте неоптимизированный DB или массив слов в оптимизированном DB. Убедитесь, что размер области достаточен для запросов клиента.
8.2. Неправильный идентификатор интерфейса
Симптом: STATUS = 7002 (соединение не устанавливается) или 7004.
Причина: InterfaceId не соответствует действительности или не назначен.
Решение: Проверьте, что в CONNECT_Struct.InterfaceId записана корректная константа из системных констант. Для X1 большинства CPU это Local~PROFINET_interface_1. Можно также временно задать значение 64 (но это менее надёжно).
8.3. Соединение не устанавливается (STATUS 7002 бесконечно)
Причина: Клиент не может подключиться к порту 502. Возможно, брандмауэр блокирует порт, или контроллер не имеет IP-адреса.
Решение: Проверьте сетевые настройки. Пропингуйте контроллер. Убедитесь, что в проекте задан IP-адрес для интерфейса.
8.4. Путаница с порядком байт
Симптом: Данные читаются, но значения не соответствуют ожидаемым (например, число 1.0 читается как 1.0E-38).
Причина: Клиент и сервер используют разный порядок байт.
Решение: В клиенте включите опцию «Word Swap» или «Byte Swap». Если такой опции нет, придётся поменять порядок байт в программе контроллера с помощью инструкции SWAP для каждого слова.
8.5. Неверный порт (502 vs 503)
В некоторых реализациях (например, LOGO! как сервер Modbus) используется порт 503. Для S7‑1200/1500 порт по умолчанию 502. Убедитесь, что клиент подключается именно на порт 502. Если нужно изменить, укажите другой LocalPort в структуре TCON_IP_v4.
9. Заключение и дальнейшие шаги
Мы детально разобрали создание сервера Modbus TCP на контроллерах S7‑1200/1500. Такой сервер позволяет интегрировать Siemens PLC в разнородные системы автоматизации, предоставляя доступ к регистрам хранения, катушкам и входам с возможностью гибкого ограничения прав.
Ключевые выводы:
- Используйте неоптимизированные DB для регистров хранения, чтобы избежать ошибок.
- Ограничивайте доступ к катушкам и входам, если это не требуется для сторонней системы.
- Контролируйте порядок байт при работе с REAL и многобайтовыми значениями.
- Всегда проверяйте идентификатор интерфейса и корректность IP-настроек.
Следующий шаг:
Если вам нужно, чтобы S7‑1200/1500 сам опрашивал другие устройства по Modbus TCP (выступал клиентом), изучите блок MB_CLIENT. В TIA Portal он работает аналогично, но требует настройки активного соединения (ActiveEstablished := TRUE) и указания удалённого сервера.