Structured Text (ST) в IEC 61131-3 - это текстовый язык для ПЛК, близкий по духу к Pascal/Ada: строгие типы, блоки объявлений, управляющие конструкции и вызовы FB/FC. На практике половина времени уходит не на «алгоритм», а на сообщения компилятора про несовместимость типов и область видимости.
Ниже - сжатый справочник синтаксиса (без претензии заменить стандарт), плюс мини-таблица: типичная формулировка ошибки - что обычно не так. Конкретные номера и тексты сообщений у Siemens, CODESYS, Rockwell различаются, но смысл у ошибок один.
Короткий ответ
•Объявления живут в секциях VAR / VAR_INPUT / VAR_OUTPUT / VAR_IN_OUT / VAR_TEMP / VAR_GLOBAL (и др. в зависимости от среды).
•Базовые типы: BOOL, целые SINT/INT/DINT/LINT и беззнаковые USINT/UINT/UDINT/ULINT, REAL/LREAL, STRING[(n)], WSTRING, TIME, DATE, TOD, DT.
•ENUM и STRUCT задают именованные типы; доступ к полю - точка.
•REFERENCE TO (ссылка на переменную типа T) есть в стандарте и ряде сред; «сырые указатели» в стиле C в ПЛК обычно запрещены или вендор-специфичны - не смешивайте с REFERENCE.
•Большинство «непонятных» ошибок компилятора - это типы, направление параметров (IN_OUT), экземпляры FB и синтаксис вызова.
Дальше - по пунктам.
Программа, функция, функциональный блок
Типовые оболочки (ключевые слова стандарта, порядок секций может требоваться строго в вашей IDE):
•PROGRAM … END_PROGRAM - организационная единица верхнего уровня (в зависимости от рантайма).
•FUNCTION_BLOCK … END_FUNCTION_BLOCK - блок с сохраняемыми внутренними переменными, вызывается через экземпляр.
•FUNCTION … END_FUNCTION - без внутреннего сохраняемого состояния между вызовами (кроме статики, если среда позволяет - осторожно), обычно возвращает значение.
Вызов FB: указывают имя экземпляра, затем параметры в скобках или через присваивание входам - синтаксис зависит от среды. Забытый экземпляр или неверное имя - частая причина «identifier not found».
Объявления переменных
Пример каркаса (иллюстративно по IEC, без привязки к одному редактору):
VAR_INPUT - только читает блок снаружи. VAR_OUTPUT - наружу. VAR_IN_OUT - ссылочная семантика (передаётся «как адрес»), запрет на привязку к выражению вместо переменной - частый источник ошибок.
Элементарные типы и литералы
•BOOL: TRUE, FALSE.
•Целые литералы: 10, 16#FF (шестнадцатеричный вид по среде).
•REAL/LREAL: 1.0, научная запись в зависимости от среды (1.0E-3).
•TIME: T#500ms, TIME#1s_200ms - синтаксис литералов зависит от реализации; при ошибке смотрите справку среды.
•STRING: одинарные кавычки в IEC; длина задаётся типом STRING[80].
ENUM
TYPE E_Mode : (Stop, Run, Fault) := Stop; END_TYPE
Использование: сравнения, CASE E_Mode OF .... Ошибки: смешение INT и ENUM без ENUM_TO_* или без явного приведения, разные типы ENUM в одном выражении.
STRUCT и ARRAY
Доступ: p.x, a[i]. Индекс за границей - часто рантайм или проверка диапазона по настройке компилятора, не всегда ошибка на этапе компиляции.
Операторы (кратко)
Присваивание :=, сравнения =, <>, <, >, <=, >=, логика AND/OR/XOR/NOT, битовые AND для целых, скобки для приоритета. Конкатенация строк + или функция в зависимости от среды.
Управляющие конструкции
•IF … ELSIF … ELSE … END_IF
•CASE выражение OF 1: … 2..5: … ELSE … END_CASE
•FOR i := a TO b BY step DO … END_FOR
•WHILE условие DO … END_WHILE
•REPEAT … UNTIL условие END_REPEAT
•EXIT (выход из цикла), RETURN (в FUNCTION/FB - по правилам среды)
Забытый END_IF или ; после присваивания - классика «unexpected token».
REFERENCE TO и «указатели»
В IEC 61131-3 третьего издания есть REFERENCE TO - ссылка на другую переменную совместимого типа, с операциями REF() / разыменование в синтаксисе среды (например ^ в части реализаций).
Это не указатель на произвольную память C. Если ваша среда не поддерживает REFERENCE - компилятор скажет «unknown type» или аналог.
Стиль кода (минимум правил для команды)
•Один стиль имён: CamelCase или snake_case, но не вперемешку.
•Не экономить на скобках в сложных булевых выражениях.
•Не раздувать один IF на экран - вынести в FB или CASE.
•Критичные участки снабжать коротким комментарием «зачем», не «что делает строка».
Мини-таблица: формулировка ошибки - что обычно не так
Где уместен СТАБУР
В проектах на базе СТАБУР имеет смысл единый гайдлайн ST: именование, работа с ENUM/STRUCT, правила VAR_IN_OUT, шаблоны FB и список запрещённых приёмов (магические числа, неявные приведения). Это уменьшает шум в компиляторе и ускоряет ревью.
Заключение
ST по IEC 61131-3 - строгий язык: чем раньше вы привыкаете читать ошибки как «диагностику типов и области видимости», тем меньше времени тратится на отладку «на железе». Держите под рукой карту типов и правила передачи по ссылке - и компилятор станет союзником, а не шумом.
FAQ
Где взять полный синтаксис?
В официальном стандарте IEC 61131-3 и в документации вашей среды - реализации отличаются.
Почему один и тот же код компилируется в одной IDE и нет в другой?
Разные подмножества стандарта, расширения, строгость проверок.
Нужны ли указатели в ST?
В большинстве прикладных задач АСУ ТП - нет; REFERENCE - отдельный инструмент под конкретные паттерны.
Как уменьшить поток ложных «type mismatch»?
Явные приведения и отдельные типы для физических величин (давление, мм) вместо «везде REAL».
ST лучше LD для алгоритмов?
Часто да для ветвлений, циклов, структур данных - см. матрицу языков в отдельной статье.
Обсуждение