Структура 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
        

Сравнение групп переменных

Группа

Где используется

Сохраняет значение

Направление

Принимает

VAR

PROGRAM, FB, FUNC

Да (кроме FUNC)

Внутренняя

VAR_TEMP

PROGRAM, FB, FUNC

Нет

Внутренняя

VAR_INPUT

PROGRAM, FB, FUNC

Зависит от типа

Вход

Константы, выражения, переменные

VAR_OUTPUT

PROGRAM, FB, FUNC

Да (для PROGRAM и FB)

Выход

Только переменные

VAR_IN_OUT

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 требуют передачи переменных с совпадающим типом данных.

См. также