Структура ST-программы
Этот раздел описывает базовую структуру программы на языке Structured Text (ST) и принципы модульности.
Модульность в ST
В языке ST программа строится из программных модулей (POU - Program Organization Unit). Каждый модуль представляет собой отдельный программный блок, который может использоваться как самостоятельный элемент или вызываться из других модулей.
Типы программных модулей
В ST существует три типа программных модулей:
PROGRAM — программный модуль, который используется исключительно как функциональный блок в FBD-программах. Он не может быть вызван из ST-кода. Сохраняет состояние между вызовами.
FUNCTION_BLOCK — функциональный блок, используемый только внутри ST-модулей. Сохраняет состояние между вызовами. Требует создания экземпляра.
FUNCTION — функция, используемая только внутри ST-модулей. Не сохраняет состояние. Может возвращать одно значение (через имя функции) или несколько значений (через VAR_OUTPUT).
PROGRAM — Программный модуль
Модуль PROGRAM предназначен для использования в качестве функционального блока в FBD-программах. Он не может быть вызван из ST-кода.
Особенности:
Используется только как функциональный блок в FBD-программах
Сохраняет состояние между вызовами
Переменные
VARсохраняют свои значенияМожет содержать
VAR_INPUT,VAR_OUTPUT,VAR_IN_OUT,VAR,VAR_TEMPНе требует создания экземпляра
Не может быть вызван из ST-кода
Пример PROGRAM для использования в FBD:
PROGRAM MotorControl
VAR_INPUT
enable : BOOL; // Входной пин в FBD
speed_setpoint : INT; // Входной пин в FBD
END_VAR
VAR_OUTPUT
motor_running : BOOL; // Выходной пин в FBD
current_speed : INT; // Выходной пин в FBD
END_VAR
VAR_IN_OUT
error_counter : INT; // Параметр по ссылке
END_VAR
VAR
internal_counter : INT := 0; // Внутренняя переменная (не видна в FBD)
END_VAR
VAR_TEMP
temp_value : INT; // Временная переменная
END_VAR
// Логика управления
temp_value := speed_setpoint * 2;
IF enable THEN
motor_running := TRUE;
current_speed := temp_value;
internal_counter := internal_counter + 1;
ELSE
motor_running := FALSE;
current_speed := 0;
END_IF;
END_PROGRAM
|
FUNCTION_BLOCK — Функциональный блок
Модуль FUNCTION_BLOCK предназначен для создания переиспользуемых программных компонентов. Он используется только внутри ST-модулей и не отображается в FBD-редакторе.
Особенности:
Используется только внутри ST-модулей
Сохраняет состояние между вызовами
Переменные
VARсохраняют свои значенияТребует создания экземпляра перед использованием
Может содержать
VAR_INPUT,VAR_OUTPUT,VAR_IN_OUT,VAR,VAR_TEMPНе может быть использован в FBD
Пример FUNCTION_BLOCK:
FUNCTION_BLOCK PIDController
VAR_INPUT
setpoint : REAL; // Уставка
process_value : REAL; // Текущее значение
kp : REAL := 1.0; // Коэффициент P
ki : REAL := 0.1; // Коэффициент I
kd : REAL := 0.05; // Коэффициент D
END_VAR
VAR_OUTPUT
output : REAL; // Выходное значение
integral_part : REAL; // Интегральная составляющая
END_VAR
VAR
previous_error : REAL := 0.0; // Предыдущая ошибка (сохраняется)
integral : REAL := 0.0; // Интеграл (сохраняется)
END_VAR
VAR_TEMP
temp_error : REAL; // Временная переменная
END_VAR
// PID-алгоритм
temp_error := setpoint - process_value;
// ...
END_FUNCTION_BLOCK
|
Использование FUNCTION_BLOCK:
Для использования FUNCTION_BLOCK необходимо создать его экземпляр в разделе переменных:
PROGRAM MainProgram
VAR
pid1 : PIDController; // Создание экземпляра
output_value : REAL;
END_VAR
// Вызов функционального блока
pid1(setpoint := 100.0, process_value := 95.0);
output_value := pid1.output;
END_PROGRAM
|
FUNCTION — Функция
Модуль FUNCTION предназначен для выполнения вычислений. В отличие от PROGRAM и FUNCTION_BLOCK, функция не сохраняет состояние между вызовами.
Особенности:
Используется только внутри ST-модулей
Не сохраняет состояние между вызовами
Все переменные являются временными
Может возвращать значение через имя функции
Может возвращать несколько значений через VAR_OUTPUT
Может содержать
VAR_INPUT,VAR_OUTPUT,VAR_IN_OUT,VAR,VAR_TEMPПеременные в группе
VARне сохраняют состояние (аналогичныVAR_TEMP)
Пример FUNCTION с возвратом через имя функции:
FUNCTION CalculateAverage : REAL
VAR_INPUT
value1 : REAL;
value2 : REAL;
value3 : REAL;
END_VAR
VAR_TEMP
sum : REAL;
END_VAR
sum := value1 + value2 + value3;
CalculateAverage := sum / 3.0;
END_FUNCTION
|
Пример FUNCTION с VAR_OUTPUT:
FUNCTION ProcessData : BOOL
VAR_INPUT
input_value : INT;
multiplier : INT;
END_VAR
VAR_OUTPUT
result : INT; // Дополнительный выходной параметр
error_code : INT; // Дополнительный выходной параметр
END_VAR
VAR_TEMP
temp_value : INT;
END_VAR
temp_value := input_value * multiplier;
IF temp_value > 1000 THEN
result := 0;
error_code := 1;
ProcessData := FALSE; // Возврат через имя функции
ELSE
result := temp_value;
error_code := 0;
ProcessData := TRUE; // Возврат через имя функции
END_IF;
END_FUNCTION
|
Использование FUNCTION с VAR_OUTPUT:
PROGRAM MainProgram
VAR
success : BOOL;
result_value : INT;
error_code : INT;
END_VAR
// Вызов функции с VAR_OUTPUT
success := ProcessData(input_value := 50,
multiplier := 10,
result := result_value,
error_code := error_code);
END_PROGRAM
|
Группы переменных
В языке ST переменные объединяются в группы в зависимости от их назначения и области видимости.
VAR — Внутренние переменные
Переменные, объявленные в блоке VAR, являются локальными для данного модуля.
В PROGRAM и FUNCTION_BLOCK сохраняют значение между вызовами
В FUNCTION не сохраняют значение (аналогичны VAR_TEMP)
Могут быть инициализированы при объявлении
Могут иметь прямой доступ к аппаратным портам (с использованием
AT), за исключением универсальных входов/выходов
Пример:
VAR
counter : INT := 0; // Инициализированная переменная
temp_value : REAL; // Неинициализированная переменная
port_input AT %DIN1 : BOOL; // Прямой доступ к порту ввода
port_output AT %DOUT1 : BOOL; // Прямой доступ к порту вывода
array_data : ARRAY[0..9] OF INT; // Массив
END_VAR
|
VAR_TEMP — Временные переменные
Переменные, объявленные в блоке VAR_TEMP, являются временными и могут использоваться в любых типах модулей.
Создаются при каждом вызове
Не сохраняют значение между вызовами
Не могут быть инициализированы
Пример:
PROGRAM ExampleProgram
VAR_TEMP
temp_counter : INT; // Временная переменная
temp_index : INT; // Временная переменная для цикла
END_VAR
FOR temp_index := 1 TO 10 DO
temp_counter := temp_counter + temp_index;
END_FOR;
END_PROGRAM
|
VAR_INPUT — Входные параметры
Переменные, объявленные в блоке VAR_INPUT, используются для передачи данных в модуль извне.
Доступны только для чтения (нельзя изменять внутри модуля)
Могут иметь значения по умолчанию
Для PROGRAM — отображаются как входы в FBD
Для FUNCTION_BLOCK и FUNCTION — входные параметры при вызове
Могут принимать константы, выражения и переменные
Пример:
VAR_INPUT
enable : BOOL := TRUE; // Вход с значением по умолчанию
setpoint : INT; // Вход без значения по умолчанию
reset : BOOL; // Сигнал сброса
END_VAR
|
Передача значений в VAR_INPUT:
PROGRAM Example
VAR
pid : PIDController;
speed : INT := 100;
END_VAR
// Передача константы
pid(setpoint := 50.0);
// Передача выражения
pid(setpoint := speed * 2 + 10);
// Передача переменной
pid(setpoint := speed);
END_PROGRAM
|
VAR_OUTPUT — Выходные параметры
Переменные, объявленные в блоке VAR_OUTPUT, используются для возврата данных из модуля.
Доступны только для записи (нельзя читать до присваивания)
Сохраняют значение между вызовами (для PROGRAM и FUNCTION_BLOCK)
Для PROGRAM — отображаются как выходы в FBD
Для FUNCTION_BLOCK и FUNCTION — выходные параметры
Могут принимать только переменные с совпадающим типом данных
Пример:
VAR_OUTPUT
result : INT; // Выходной результат
is_ready : BOOL; // Флаг готовности
error_code : DINT; // Код ошибки
END_VAR
|
Правильная передача в VAR_OUTPUT:
PROGRAM Example
VAR
pid : PIDController;
output_value : REAL; // Переменная для подключения к выходу
END_VAR
// Правильно: передача переменной
pid(setpoint := 100.0, process_value := 95.0);
output_value := pid.output; // Чтение из VAR_OUTPUT
// Ошибка: нельзя передать константу в VAR_OUTPUT
// pid(output := 50.0); // НЕПРАВИЛЬНО!
END_PROGRAM
|
VAR_IN_OUT — Параметры по ссылке
Переменные, объявленные в блоке VAR_IN_OUT, передаются по ссылке. Это позволяет изменять исходные переменные, переданные в модуль.
Изменения внутри модуля влияют на исходную переменную
Не могут иметь значения по умолчанию
Используются для больших структур данных (массивы, строки)
Для PROGRAM — отображаются как входы/выходы в FBD
Для FUNCTION_BLOCK и FUNCTION — параметры по ссылке
Могут принимать только переменные с совпадающим типом данных
Пример:
VAR_IN_OUT
inout_data : ARRAY[0..99] OF INT; // Массив по ссылке
inout_string : STRING; // Строка по ссылке
inout_value : INT; // Целочисленное значение по ссылке
END_VAR
|
Правильная передача в VAR_IN_OUT:
PROGRAM Example
VAR
my_data : ARRAY[0..9] OF INT;
my_value : INT := 10;
END_VAR
// Правильно: передача переменной
ProcessData(inout_data := my_data, inout_value := my_value);
// Ошибка: нельзя передать константу в VAR_IN_OUT
// ProcessData(inout_value := 5); // НЕПРАВИЛЬНО!
END_PROGRAM
|
Сравнение групп переменных
Группа |
Где используется |
Сохраняет значение |
Направление |
Принимает |
|---|---|---|---|---|
|
PROGRAM, FB, FUNC |
Да (кроме FUNC) |
Внутренняя |
— |
|
PROGRAM, FB, FUNC |
Нет |
Внутренняя |
— |
|
PROGRAM, FB, FUNC |
Зависит от типа |
Вход |
Константы, выражения, переменные |
|
PROGRAM, FB, FUNC |
Да (для PROGRAM и FB) |
Выход |
Только переменные |
|
PROGRAM, FB, FUNC |
Нет (ссылка) |
Вход/Выход |
Только переменные |
Примеры использования
Пример PROGRAM с использованием FUNCTION_BLOCK:
PROGRAM MainProgram
VAR
pid1 : PIDController; // Экземпляр FUNCTION_BLOCK
setpoint : REAL := 100.0;
actual : REAL := 95.0;
control_output : REAL;
error_count : INT := 0;
END_VAR
VAR_IN_OUT
error_counter : INT; // Параметр по ссылке
END_VAR
VAR_TEMP
temp_value : REAL; // Временная переменная
END_VAR
// Вызов FUNCTION_BLOCK
pid1(setpoint := setpoint,
process_value := actual,
kp := 1.5, // Константа в VAR_INPUT
ki := actual * 0.01); // Выражение в VAR_INPUT
// Чтение VAR_OUTPUT
control_output := pid1.output;
// Передача в VAR_IN_OUT
error_counter := error_count;
END_PROGRAM
|
Пример FUNCTION с VAR_OUTPUT:
FUNCTION CalculateStatistics : BOOL
VAR_INPUT
value1 : REAL;
value2 : REAL;
value3 : REAL;
END_VAR
VAR_OUTPUT
average : REAL; // Выходной параметр
max_value : REAL; // Выходной параметр
min_value : REAL; // Выходной параметр
END_VAR
VAR_TEMP
sum : REAL;
END_VAR
sum := value1 + value2 + value3;
average := sum / 3.0;
max_value := value1;
IF value2 > max_value THEN max_value := value2; END_IF;
IF value3 > max_value THEN max_value := value3; END_IF;
min_value := value1;
IF value2 < min_value THEN min_value := value2; END_IF;
IF value3 < min_value THEN min_value := value3; END_IF;
CalculateStatistics := TRUE;
END_FUNCTION
|
Использование FUNCTION с VAR_OUTPUT:
PROGRAM MainProgram
VAR
success : BOOL;
avg : REAL;
max : REAL;
min : REAL;
END_VAR
success := CalculateStatistics(value1 := 10.0,
value2 := 20.0,
value3 := 15.0,
average := avg,
max_value := max,
min_value := min);
END_PROGRAM
|
Примечание
Точность именования переменных и соблюдение синтаксиса имеют важное значение.
Объявление переменных обязательно должно происходить перед их использованием в теле программы.
PROGRAM используется только как функциональный блок в FBD и не может быть вызван из ST-кода.
FUNCTION_BLOCK требует создания экземпляра перед использованием.
VAR_TEMP могут использоваться в любых типах модулей.
При передаче в VAR_INPUT тип данных приводится к типу VAR_INPUT.
VAR_OUTPUT и VAR_IN_OUT требуют передачи переменных с совпадающим типом данных.
См. также
Встроенные типы данных - для информации о типах данных.
Операторы языка ST - для изучения операторов.
Создание ST-модуля в zWorkbench - для информации о создании ST-модуля и его использовании в FBD.