Ключевые слова
Ключевые слова — это уникальные комбинации символов, используемых как отдельные синтаксические элементы. Ключевые слова не должны содержать внутренних пробелов и могут быть введены в символах верхнего и нижнего регистра, регистр символов не учитывается (Например, ключевые слова FUNCTION и function синтаксически эквивалентны).
Ключевые слова не должны использоваться в любых других целях, например, как имена переменных.
Зарезервированные ключевые слова
Встроенные функции/типы/определения
Правила именования
Имена переменных, функций и функциональных блоков подчиняются следующим правилам:
Имя не должно содержать пробелов и спецсимволов (!, @ и т.д.). Исключение – символ нижнего подчеркивания (_);
Нижнее подчёркивание _ допускается и считается отдельным символом. (A_BCD и AB_CD - это разные идентификаторы);
Имя должно начинаться с буквы;
Имя переменной может содержать только буквы латинского алфавита;
Имя не должно содержать несколько символов нижнего подчеркивания (_), размещенных подряд (т.е. имя i__Test недопустимо, а имя i_Te_st - допустимо);
Регистр имен объектов не учитывается (VAR1, VaR1 и var1 относятся к одной и той же переменной);
На длину имени не накладывается никаких ограничений;
Имя не должно совпадать с одним из зарезервированных ключевых слов (например, VAR, INT, и т.д.);
Рекомендации
Рекомендуется использовать венгерскую нотацию для именования переменных: имена переменных предваряются заранее оговоренными префиксами, состоящими из одного или нескольких символов. Краткие значащие имена являются предпочтительными. Каждое слово в идентификаторе следует записывать с заглавной буквы. Перед именем переменной указывается строчный префикс, обозначающий её тип.
| Тип данных | Префикс |
|---|---|
BOOL | x |
DWORD | dw |
Пример:
![]() |
Выражения
Выражение – это конструкция, возвращающая определенное значение после его вычисления.
Выражение состоит из операторов и операндов. Операндом может быть константа, переменная, функциональный блок или другое выражение.
Вычисление выражений выполняется согласно правилам приоритета. Оператор с самым высоким приоритетом выполняется первым, оператор с более низким приоритетом – вторым и т.д., пока не будут выполнены все операторы.
Операторы с одинаковым приоритетом выполняются слева направо.
В языке поддерживаются следующие виды выражений:
Примеры:
Литералы
Порядок вычисления литералов не специфицирован.
Числовые литералы могут записываться в десятичном (0, 1, 100), двоичном (2#0011_0011), восьмеричном (8#127), шестнадцатеричном (16#ABCD) видах.
Числовой литерал может быть типизированным (DWORD#123). Числовой литерал может быть записан в научной нотации с указанием множителя и показателя степени числа 10 (2.5E+1 = 25). В случае положительного показателя степени знак "+" можно опустить.
Литерал вычисляется в соответствующее значение наименьшего подходящего по размеру типа (если тип литерала не указан явно).
Литералы массивов
Литералы массивов записываются в квадратных скобках. При этом элементы массива указываются по порядку объявления через запятую.
Пример:
![]() |
В литералах массивов допускается указывать несколько первых элементов подряд. Неуказанные элементы принимаются равными нулевому значению соответствующего типа. Пропуски элементов ([1,,3]) не допускаются (ошибка компиляции E007).
Пример:
![]() |
Литералы структур
Литералы структур записываются в круглых скобках с явным указанием идентификаторов полей и их значений в виде <идентификатор_поля>:=<значение> через запятую. Если имя поля не указано явно, возникнет ошибка компиляции [E071].
Пропущенные значения принимаются равными нулевому значению соответствующего типа.
Пример:
![]() |
Литералы вложенных структур требуют указания типов для каждого уровня вложенности, кроме самого нижнего. В противном случае возникнет ошибка компиляции [E071].
Пример вложенных структур:
![]() |
Литерал массива структур в текущей реализации работает некорректно.
Пример структуры с массивами:
![]() |
Чтение переменных
![]() |
Для чтения из переменной достаточно указать её идентификатор (a, dwVar, DWVAR).
Чтение из переменной записывается в текущее значение переменной и имеет тип, совпадающий с типом этой переменной.
Индексный доступ
Доступ к элементу массива по индексу вычисляется соответствующее значение этого элемента.
<Выражение> должно вычисляться в массив. В противном случае возникнет ошибка компиляции [E059]. Порядок вычисления <выражения> и <индекса> не специфицирован.
Попытка доступа к элементу за границами массива (индекс вычисляется на этапе компиляции) приведёт к ошибке компиляции [E058].
Попытка доступа к элементу за границами массива (индекс вычисляется на этапе исполнения) не приводит к ошибке исполнения. Поведение в этом случае не специфицировано.
Индекс может быть представлен целочисленным (в том числе булевым) литералом, целочисленной (в том числе булевой) переменной.
Чтение полей структур
Чтение поля структуры аналогично чтению переменной. Для доступа к полям структуры после идентификатора структуры используется оператор "точка".
Чтение из поля структуры вычисляется в текущее значение поля указанного экземпляра структуры и имеет тип, совпадающий с типом этого поля.
Вложенный доступ поддерживается. Уровень вложенности неограничен.
Если функция возвращает структуру, недопустимо при вызове функции обращаться к отдельным полям возвращаемого значения. В противном случае произойдёт ошибка компиляции [E002]. Имеется в виду конструкция вида b := f().a;
Унарные выражения
Поддерживаются следующие унарные операторы: +.
Все математические операторы возвращают целочисленный тип. Данное выражение сначала вычисляет свое внутреннее выражение, а потом к его результату применяет соответствующее действие.
Бинарные выражения
Поддерживаются следующие бинарные операторы: +.
Все математические операторы возвращают целочисленный тип. Данное выражение сначала вычисляет свои внутренние выражения (слева направо), а потом применяет к ним соответствующее действие.
Переполнение ведёт себя по принципу арифметики с дополнением до 2.
Пример переполнения:
Вызовы функций
Аргументы функции могут передаваться как позиционно, так и именованно, через запятую.
Аргумент может быть структурой, передаётся в функцию аналогично аргументам простого типа.
Аргумент может быть массивом. Такой аргумент не может передаваться в виде литерала (ошибка компиляции [E071]).
Пример для функции fct(in1,in2,in3):
Вызов fct(in2 := 2, in1 := 1, 3) в CODESYS приведёт к ошибке компиляции.
МЭК 61131-3 описывает только формальный (именованный) и неформальный (позиционный) варианты передачи, но допускает передачу неполного перечня аргументов. Каждая переменная, которой в перечне не задано значение, имеет начальное значение, присвоенное в объявлении вызванного объекта, или неявное значение соответствующего типа данных.
При вызове функции аргументы вычисляются в порядке указания слева направо, затем происходит их передача по значению в функцию.
Пример:
Возвращаемый слот функции имеет значение по умолчанию - нулевое значение соответствующего типа.
Функция с результатом может вызываться в выражении или как оператор. Такое выражение вычисляется в возвращаемое значение соответствующего типа.
Функция может возвращать структуру. Начальным значением для возвращаемого слота-структуры будет структура с полями, имеющими соответствующие их типам нулевые значения.
Функция без результата не должна вызываться внутри выражения. В противном случае произойдёт ошибка компиляции [E037].
Пример:
Функция может возвращать структуру (в том числе вложенную). Начальным значением для возвращаемого слота-структуры будет структура с полями, имеющими соответствующие их типам нулевые значения.
Допускается как полная перезапись возвращаемого слота, так и перезапись отдельных полей.
Запрещено обращаться к отдельным полям возвращаемого значения извне функции. В противном случае произойдёт ошибка компиляции [E007].
Пример возврата структуры:
![]() |
Функция может возвращать массив (в том числе многомерный). Начальным значением для возвращаемого слота-массива будет массив с элементами, имеющими соответствующие типу нулевые значения.
Допускается как полная перезапись возвращаемого слота, так и перезапись отдельных элементов.
Возвращаемое значение-массив может быть проигнорировано.
Пример возврата массива:
![]() |
Всё описанное выше справедливо и для массивов структур.
Составные выражения
Составные выражения содержат в качестве элементов другие выражения (необязательно простые). Количество подвыражений и количество уровней вложенности не ограничены.
Вложенные подвыражения вычисляются перед содержащими их выражениями.
Пример:
Приоритеты операций
Операции в таблице расположены от высшего приоритета к низшему. Чем выше приоритет операции, тем раньше она выполняется. Операции одного приоритета выполняются слева направо.
| Операция | Обозначение |
|---|---|
Взятие в скобки | ( <Выражение> ) |
Оператор с передачей операндов в скобках | <Оператор>(<операнды>) |
Сложение | + |
Сравнение | <, >, <=, >= |
Проверка на равенство | = |
Операторы
Оператор ADD
Оператор для сложения переменных.
Разрешённые типы данных: WORD, DWORD, DINT.
Пример:
a := 1+3; // результат 4 |
Оператор EQ
Оператор для проверки операндов на равенство.
Разрешённые типы данных: все элементарные типы.
Возвращает TRUE, если операнды равны, и FALSE в противном случае.
Пример:
x1 := 1=1; // результат TRUE
x2 := TRUE=FALSE; // результат FALSE |
Оператор GT
Оператор для проверки утверждения "больше" относительно операндов.
Разрешённые типы данных: WORD, DWORD, DINT.
Возвращает TRUE, если первый операнд больше второго, и FALSE в противном случае.
Пример:
Оператор REF (ADR)
Оператор для возврата указателя на объект.
Взятие указателя реализуется оператором REF() или ADR(). Оператор ADR добавлен для совместимости с CODESYS V3.5. ADR() и REF() семантически эквивалентны.
Пример:
Оператор разыменования ^
Разыменование (взятие значения по указателю) реализуется оператором ^.
Указатели типизированные. Разыменование вычисляется в значение соответствующего типа по указателю.
При несовпадении типов, где это возможно, выполняется неявное преобразование типа (между целочисленными типами и BOOL). Если тип данных слева меньше, неявное преобразование выполняется с предупреждением компилятора [E067].
Несовпадение типов с невозможностью неявного преобразования приведёт к ошибке компиляции [E037].
Разыменование нулевого указателя приводит к ошибке исполнения (Segmentation fault).
Пример:
Оператор SIZEOF
Возвращает размер объекта в байтах (значение типа ULINT).
Пример:
Утверждения (инструкции)
| Утверждение | Синтаксис |
|---|---|
| Присвоение переменной | <идентификатор> := <выражение> |
| Условие | IF <условие1> THEN <блок кода1> ELSIF <условие2> THEN … ELSE <блок кодаN> END_IF |
| Цикл с предусловием | WHILE <условие> DO … END_WHILE |
| Цикл FOR | FOR <выражение-счётчик> := <начальное значение> TO <конечное значение> DO … END_FOR |
| EXIT | WHILE <условие> DO … EXIT; … END_WHILE |
| CONTINUE | FOR <счётчик> := <начальное значение> TO <конечное значение> BY <шаг> DO <блок кода 1> CONTINUE; <блок кода 2> END_FOR |
| RETURN | PROGRAM <…> … RETURN; … END_PROGRAM |
| Комментарии | // Однострочный комментарий (* многострочный комментарий *) |
Присвоение
<Выражение места> (L-Value expression) может быть представлено: именем переменной (в том числе структурой), именем поля переменной-структуры, именем функции (внутри этой функции), указателем.
<Выражение> может быть любым. Порядок вычисления <выражения> и <выражения-места> не определён.
Доступ к элементу массива осуществляется по индексу. Доступ к полям структуры осуществляется через точку. Вложенный доступ поддерживается.
Разрешены присвоения выражений типа BOOL и числовых типов (см. примечание ниже), присвоения структур одного и того же типа. Присвоение переменной простого типа значения структуры (и наоборот), а также структур несовпадающих типов приведёт к ошибке компиляции [E037].
Пример:
![]() |
Пример доступа к полям структур:
![]() |
При присвоении массивов (в том числе многомерных) элементы массива указываются по порядку объявления.
Пример:
![]() |
В литералах массивов допускается указывать несколько первых элементов подряд. При этом оставшиеся элементы сохранят свои прежние (начальные) значения. Пропуски элементов (например, [1,,3]) не допускаются (ошибка компиляции E007).
IF
Инструкция ветвления в зависимости от условия(-ий).
Здесь блоки кода 1, 2 - представляют собой произвольное количество инструкций (от нуля до бесконечности). Блоки кода внутри могут содержать вложенные конструкции IF/FOR/WHILE.
Условия являются выражениями и должны возвращать результат типа BOOL. В противном случае произойдёт неявное преобразование в BOOL, компилятор выдаст предупреждение [E096].
При выполнении сначала вычисляется условие. Если оно вычисляется в значение TRUE, то исполняется блок кода 1, иначе - блок кода 2. После этого выполнение завершается. Блок ELSE может отсутствовать.
Пример:
Также, в данной конструкции может быть использован вариант с ELSIF.
Количество блоков ELSIF не ограничено.
Расширенная конструкция вычисляется следующим образом:
Вычисляется условие 1.
Если условие1 истинно, выполняется блок кода 1. Далее выполнение конструкции завершается. Если условие 1 ложно, вычисляется условие 2.
Если условие 2 истинно, выполняется блок кода 2. Если ложно - вычисляется условие 3.
Расширенная конструкция может быть преобразована к обычной конструкции IF:
Здесь первый блок ELSIF преобразован в блок ELSE с вложенным IF с конструкциями ELSIF/ELSE. Операционная семантика расширенной конструкции исходит из операционной семантики базового IF THEN ELSE END_IF.
Пример
WHILE
Инструкция для цикла с предусловием.
Условие должно возвращать результат типа BOOL. В противном случае произойдёт неявное преобразование в BOOL, компилятор выдаст предупреждение [E096].
Блок кода представляет собой произвольное количество инструкций (от нуля до бесконечности). Блок кода внутри может содержать вложенные конструкции IF/FOR/WHILE.
Блок кода выполняется повторно, пока условие истинно, и не выполняется в противном случае. То есть может выполниться от нуля до бесконечности раз в зависимости от условия.
Пример:
FOR
Оператор FOR указывает, что последовательность операторов выполняется повторно, в то время как переменная управления (счётчик) инкрементируется.
Счётчик, начальное значение и конечное значение должны быть выражениями целого типа (например, DINT). Они не должны изменяться внутри цикла. В противном случае не будет обеспечено заданное количество итераций, но выполнение завершится корректно. Переменная-счётчик должна быть объявлена. При несоответствии типов произойдёт ошибка компиляции [E094].
Блок кода представляет собой произвольное количество инструкций (от нуля до бесконечности). Блок кода внутри может содержать вложенные конструкции IF/FOR/WHILE. По окончании выполнения блока кода счётчик изменяется на заданный шаг.
Блок кода выполняется столько раз, сколько задано начальным и конечным значениями для счётчика.
Конструкция BY может быть опущена. В этом случае изменение счётчика происходит на 1 от начального значения к конечному.
Пример:
![]() |
EXIT
Утверждение EXIT используется внутри конструкций FOR и WHILE для безусловного выхода из цикла. Блок кода, расположенный после EXIT, выполняться не будет.
Счётчик FOR при выходе из цикла сохраняет своё значение.
При использовании EXIT во вложенном цикле выход происходит только из него. Внешний цикл продолжит выполняться.
Пример:
![]() |
CONTINUE
Утверждение CONTINUE используется внутри конструкций FOR и WHILE для безусловного перехода на следующую итерацию цикла. Блок кода, расположенный после CONTINUE, выполняться не будет.
Счётчик FOR при выполнении CONTINUE сохраняет своё значение в текущей итерации и изменяется на заданный шаг в следующей итерации. Если CONTINUE вызван на последней итерации, счётчик по окончании цикла примет <конечное значение> + <шаг> (как и без использования CONTINUE).
Пример:
RETURN
Утверждение RETURN используется внутри программ и функций, выполняет безусловный выход из POU и передачу потока управления вызвавшему POU.
Пример:
Комментарии
Тип данных переменных
Программа представляет собой набор операций, выполняемых над данными, размещенными в памяти устройства. Для упрощения работы с памятью данные представляются в виде переменных – именованных объектов с определенными характеристиками (в частности – типом). Перед работой с переменными необходимо их объявить.
Сначала указывается имя переменной, затем ее тип и опционально – начальное значение. Имя переменной и тип разделяются символом двоеточия. Тип и начальное значение разделяются оператором присваивания :=. Заканчивается объявление символом «точка с запятой».
Вместе с объявлением переменной можно указать пояснительный комментарий.
ALTA IDE поддерживает однострочные комментарии, начинающиеся с символа //, и многострочные – размещенные между символами (* и *).
Тип данных переменной определяет род информации, диапазон представлений и множество допустимых операций.
В ALTA IDE используются следующие типы переменных:
булевский (двоичный);
Значения от одной переменной к другой могут передаваться только при совпадающих типах переменных.
BOOL
| Значения | Размер |
|---|---|
| TRUE (1), FALSE (0) | 1 байт |
Целочисленные типы
| Тип данных | Нижняя граница | Верхняя граница | Размер |
|---|---|---|---|
| WORD/UINT | 0 | 65535 | 16 бит |
| INT | -32768 | 32767 | 16 бит |
| DWORD/UDINT | 0 | 4294967295 | 32 бит |
| DINT | -2147483648 | 2147483647 | 32 бит |
Типы с плавающей точкой (IEEE 754)
| Тип данных | Нижняя граница | Верхняя граница | Размер |
|---|---|---|---|
| REAL | 1.0E-44 | 3.402823E+38 | 32 бит |
| LREAL | 4.94065645841247E-324 | 1.7976931348623157E+308 | 64 бит |
Строковые типы
Строки являются нуль-терминированными
| Тип данных | Кодировка | Размер |
|---|---|---|
| STRING | UTF-8 | 1 байт |
| WSTRING | USC-2 | 2 байта |
Временные типы
Тип данных | Описание | Формат, разрешение наносекунды (ns) | Нижняя граница | Верхняя граница | Память |
|---|---|---|---|---|---|
TIME (T), LTIME (LT) | длительность интервалов времени | T#хDxHxMxSxMSxUSxNS | 0 | 213503d23h34m33s709ms551us615ns | 64 бит |
TIME_OF_DAY (TOD), LTOD | значение местного времени, начиная с 0 часов текущих суток | TOD#hh:mm:ss:ms | 00:00:00 | 23:59:59.999_999_999 | 64 бит |
DATE (D), LDATE (LD) | значение календарной даты, вычисляется относительно UNIX эпохи | D#yyyy-mm-dd | 1677-09-21 | 2262-04-11 | 64 бит |
DATE_AND_TIME (DT), LDT | значение календарной даты и местного времени, вычисляется относительно UNIX эпохи | DT#yyyy-mm-dd-hh:mm:ss.ms | 1677-09-21 00:12:43.145224192 | 2262-04-11 23:47:16.854775807 | 64 бит |
Объявление типа
Объявление типа может быть синонимом любому типу, в том числе встроенному.
Здесь конструкция ()+ означает одно или более повторений.
Объявление типа может быть представлено:
Именем другого типа.
Ограничением числового типа по диапазону.
Объявлением структуры.
Имя другого типа
Представляет собой псевдоним другого типа (в том числе встроенного) и может использоваться взаимозаменяемо с именем этого типа.
Ограничение диапазона
Представляет собой псевдоним другого целочисленного типа (в том числе встроенного) с ограниченным диапазоном значений.
Попытка присвоить литерал, выходящий за указанный диапазон, должна приводить к ошибке компиляции. Во всех остальных случаях (вычисление на этапе исполнения) ограничение не учитывается.
Примеры:
Структуры
Структура - пользовательский тип данных, содержащий набор именованных полей любых типов данных.
Количество полей от 1 до бесконечности. Попытка объявить структуру без полей приведёт к ошибке компиляции [E028].
Структуры могут быть вложенными. Уровень вложенности неограничен.
Объявление рекурсивной структуры приведёт к ошибке компиляции [E029].
Синтаксис:
Пример объявления:
Доступ к полям структуры осуществляется через точку. Вложенный доступ поддерживается.
Пример доступа к полям:
Массивы
Массив - совокупность элементов данных одного типа.
Синтаксис:
В случае многомерного массива его размерности указываются через запятую. Число размерностей не ограничено. <Тип_данных> может быть простым типом, объявлением типа, структурой, массивом (в том числе многомерным). Массив массивов не является синтаксически и семантически эквивалентным многомерному массиву.
Пример объявления:
Доступ к элементам массива осуществляется по индексу. Доступ по индексу вычисляется в соответствующее значение элемента массива. Попытка доступа к элементу за границами массива (индекс вычисляется на этапе компиляции) приведёт к ошибке компиляции [E058]. Попытка доступа к элементу за границами массива (индекс вычисляется на этапе исполнения) не приводит к ошибке исполнения.
Синтаксис:
Примеры доступа по индексу:
Доступ по индексу к массиву структур выполняется аналогично.
Пример доступа по индексу к массиву структур:
Указатели (REF_TO / POINTER TO)
Указатель - переменная, хранящая адрес некоторого объекта в памяти.
Указатель является 64-битным целым числом (ULINT).
Объявление:
Использование ключевого слова POINTER вызывает предупреждение компилятора (E015), как несоответствие стандарту МЭК61131-3.
Взятие указателя реализуется оператором REF(). Оператор ADR() возвращает числовое значение указателя. В компиляторе реализовано неявное преобразование в обе стороны. Разыменование (взятие значения по указателю) реализуется оператором ^.
Синтаксис:
Пример:
Указатель на массив | Содержит адрес первого элемента массива. |
Указатель на структуру | Содержит адрес первого поля по порядку указания в объявлении типа структуры. |
Указатель на указатель | Допускается использовать указатель на указатель. Глубина "вложенности" неограничена. |
Пример:
Операция разыменования выглядит следующим образом:
Арифметика указателей
Прибавление/вычитание целочисленного выражения N из указателя вычисляется в прибавление/вычитание N*<размер типа указателя>. Прибавление/вычитание нецелочисленного выражения (REAL, STRING, REF_TO и т.п.) из указателя приведёт к ошибке компиляции [E071].
Пример:
Неявные преобразования чисел/массивов/указателей
Ниже рассматриваются ситуации, когда выражение типа X оказывается в позиции, где ожидается выражение типа Y (или неявное преобразование X ⇒ Y).
Преобразование ARRAY […] OF T ⇒ REF_TO(T) выполняется.
Преобразование REF_TO ARRAY […] OF T ⇒ REF_TO(T) выполняется c предупреждением компилятора [E090].
Преобразование REF_TO T ⇒ SIZEOF(T) выполняется только если T имеет размер не меньше, чем REF_TO, т.е. LWORD. В противном случае произойдёт ошибка компиляции [E065].
Преобразование SIZEOF(T) ⇒ REF_TO T выполняется только если T имеет размер не меньше, чем REF_TO, т.е. LWORD. В противном случае произойдёт ошибка компиляции [E065].
POU
POU (Programming Organization Unit) - программный компонент, структурная единица проекта, описывающая алгоритм на языке ST.
Функция
Функция - POU, возвращающий одно значение.
В CODESYS V3.5 допускается использовать VAR_OUTPUT в функциях.
Функция не сохраняет значения переменных между вызовами. Вызов функции с одинаковыми параметрами (VAR_INPUT) приводит к одинаковому результату.
Объявление функции
![]() |
Здесь <имя_функции> - произвольный идентификатор. Возвращаемый тип может не указываться, в этом случае опускается двоеточие.
Объявления переменных и параметров могут содержать любое количество блоков объявлений (в том числе отсутствовать).
Тело реализации содержит любое (в том числе нулевое) количество утверждений.
Пример описания функции:
![]() |
Функция с результатом может вызываться в выражении или как оператор.
Функция без результата не должна вызываться внутри выражения.
Пример вызова функции:
![]() |
Программа
Программа - POU, возвращающий одно или несколько значений. Программа сохраняет значения локальных переменных между вызовами.
Объявление программы:
![]() |
Здесь <имя_программы> - произвольный идентификатор.
Объявления переменных и параметров могут содержать любое количество блоков объявлений (в том числе отсутствовать).
Тело реализации содержит любое (в том числе нулевое) количество утверждений.
Программа может вызываться из других программ и функций. Рекурсивный вызов допускается. Глубина рекурсии не определена.
Вызов программы:
![]() |
Передача параметров VAR_INPUT в программу может осуществляться как позиционно (при отсутствии VAR_OUTPUT), так и именованно. Запрещено совмещать варианты передачи аргументов, в этом случае возникнет ошибка компиляции [E031]. VAR_OUTPUT могут передаваться только именованно. При наличии в программе блока VAR_OUTPUT все аргументы должны передаваться именованно.
Извне доступны только переменные VAR_INPUT и VAR_OUTPUT программы. Локальные переменные VAR извне недоступны (ошибка компиляции [E049]).
Пример доступа к входным/выходным параметрам программы:
![]() |
По окончании выполнения программы выходные параметры VAR_OUTPUT по программы передаются по значению в указанные переменные. Поток выполнения передаётся вызвавшему POU. Для принудительного завершения программы используется утверждение RETURN.
Пример вызова программы:
![]() |
Переменные
В языке имеются следующие виды переменных:
VAR;
VAR_INPUT;
VAR_OUTPUT;
VAR_GLOBAL.
VAR
Локальные переменные объявляются между ключевыми словами VAR и END_VAR в области объявления POU.
Пример:
![]() |
VAR_INPUT
Переменные VAR_INPUT являются аргументами для функции/программы. Переменные VAR_INPUT объявляются между ключевыми словами VAR_INPUT и END_VAR в области объявления POU.
Порядок указания переменных в блоке(-ах) VAR_INPUT определяет позиции аргументов POU.
При вызове POU происходит передача по значению.
Пример:
![]() |
VAR_OUTPUT
Переменные VAR_OUTPUT являются выходными параметрами программы. Переменные VAR_OUTPUT объявляются между ключевыми словами VAR_OUTPUT и END_VAR в области объявления POU. Порядок указания переменных в блоке(-ах) VAR_OUTPUT определяет позиции параметров при вызове POU.
По окончании выполнения POU происходит передача параметров VAR_OUTPUT по значению.
Пример:
![]() |
VAR_GLOBAL
Глобальные переменные видны из всех POU проекта (и доступны для чтения и записи). Глобальные переменные объявляются между ключевыми словами VAR_GLOBAL и END_VAR вне POU в отдельном списке внутри проекта. Количество списков неограничено.
Для объявления глобальной переменной необходимо создать программный объект (программу, функцию или функциональный блок), и объявить список глобальных переменных после завершающей части конструкции объявления компонента (END_PROGRAM END_FUNCTION или END_FUNCTION_BLOCK):
Пример:
![]() |
Глобальную переменную нельзя напрямую привязать к параметрам устройства. Глобальная переменная должна быть присвоена переменной программы, которую, в свою очередь, можно привязать к параметрам устройства.
Пример:
![]() |
VAR RETAIN
Retain переменные объявляются между ключевыми словами VAR RETAIN и END_VAR в области объявления переменных программы и в списках глобальных переменных. Объявление retain переменных в функции или функциональном блоке не приведет к созданию энергонезависимой переменной.
Если в программе используется экземпляр функционального блока со свойством Retain, то все переменные внутри этого ФБ сохраняются в энергонезависимой памяти.
Для переменных типа структуры и массивы со свойством retain в энергонезависимую память:
сохраняется значение каждого поля экземпляра структуры;
сохраняется значение каждого элемента массива.
Пример объявления в программе:
VAR RETAIN
iCycles: UDINT := 0;
fbTON: TON; // таймер задержки включения
END_VAR |
Пример объявления в списке GVL:
VAR_GLOBAL RETAIN
gCounter: DINT := 0;
gMode: INT := 1;
END_VAR |
При перезаписи проекта на ПЛК значения retain переменных не сохраняются.
Примеры объявления
Переменные одного типа могут быть объявлены группами через запятую. Размер группы неограничен.
Пример 1:
![]() |
Блоки объявления не могут быть вложены друг в друга.
Пример 2:
FUNCTION fct
VAR_INPUT
in1, in2: DWORD;
END_VAR
VAR_OUTPUT
in3: DWORD;
END_VAR
VAR
local1, local2: DWORD;
END_VAR
END_FUNCTION |
Разрешение имен
Области видимости
Каждый POU имеет локальную область видимости (переменные в разделах VAR, VAR_INPUT). Локальные переменные видны только внутри родительского POU.
В глобальной области видимости могут быть объявлены функции (глобальные), программы и глобальные переменные. Видны из любого POU проекта.
Конфликты
Дублирование имен
Дублирование имён в области видимости - объявление переменных и/или функций с одинаковыми именами приведёт к ошибке компиляции [E004].
Затенение имен
Если из POU видимы одноимённые локальная переменная и глобальная переменная/функция, то компиляция и выполнение произойдут корректно.
Выражение f() будет относиться к функции, а f - к локальной переменной.
В CODESYS V3.5 произойдёт ошибка компиляции.
Вызов функции/возвращаемый слот функции
Внутри функции не может быть одноименной локальной переменной (см. выше дублирование имен). Выражение f() будет относиться к функции, а f - к возвращаемому слоту.
Рекурсивный вызов функции допускается, глубина рекурсии не определена.
Имя типа/Имя функции/переменной
Допускается объявление переменных/функций одноимённых с типами данных.
В CODESYS V3.5 произойдёт ошибка компиляции.
Размещение данных в памяти
Данные POU размещаются в памяти последовательно в порядке объявления. Для элементарных типов данных занимаемый размер в памяти, выравнивание (кратность адреса) и сдвиг (занимаемый размер в массиве) совпадают. Для массивов выравнивание определяется выравниванием элемента массива.
| Тип данных | Размер (size) | Выравнивание (alignment) | Сдвиг (offset) |
|---|---|---|---|
| BOOL | 1 | ||
| WORD/UINT/INT | 2 | ||
| DWORD/DINT/UDINT | 4 | ||
| REAL | 4 | ||
| LREAL | 8 | ||
| STRING(len) | len+1 | 1 | len+1 |
| WSTRING(len) | 2*len+2 | 2 | 2*len+2 |
Размещение структур
Элементы структуры размещаются в памяти последовательно - по порядку указания в описании типа. Выравнивание элементов выполняется по элементу (простого типа) с максимальным выравниванием.
Аналогичное правило действует для вложенных структур: выравнивание в памяти для надструктуры определяется наибольшим выравниванием элементов подструктуры.
Порядок байт/слов самих элементов структуры при этом не изменяется.
Примеры:
![]() |
Размещение массивов
Элементы массива размещаются в памяти последовательно - по порядку от элемента с начальным индексом до элемента с конечным индексом. Выравнивание определяется выравниванием элемента массива. Сдвиг равен размеру в байтах.
Многомерные массивы (в том числе массивы массивов) располагаются в памяти по порядку указания осей. Элементы каждой оси располагаются по порядку от элемента с начальным индексом до элемента с конечным индексом. Пример: [a11, a12, a21, a22].
Порядок байт/слов самих элементов массива при этом не изменяется.
Примеры:
![]() |

















































































