TGViewer
Codesys 3.5 Обучение программированию. Codesys 3.5 Обучение программированию. @codesys4 · 269 subscribers
Post #164 72
⚙️ FUNCTION_BLOCK в CODESYS: почему повторный вызов может изменить результат?

📘 Часть 1/2. Внутренняя память и повторные вызовы

Функциональные блоки — основа многих программ ПЛК.

Таймеры, счётчики, триггеры, управление оборудованием, обмен по Modbus — всё это часто реализуется через FUNCTION_BLOCK.

Но есть важная особенность:

Функциональный блок сохраняет своё внутреннее состояние между вызовами.

Если один экземпляр вызвать несколько раз за цикл программы, его код выполнится несколько раз.

Разберём, почему это важно.

━━━━━━━━━━━━━━━━━━

🔹 FUNCTION и FUNCTION_BLOCK — в чём разница?

В Structured Text используются разные типы программных единиц.

FUNCTION — функция.

Обычно применяется для вычислений и преобразований данных.

Например:

rResult := ABS(rValue);


FUNCTION_BLOCK — функциональный блок.

В отличие от обычной функции, экземпляр ФБ может сохранять значения внутренних переменных между вызовами.

Например:

fbTimer : TON;
fbTrig : R_TRIG;


Каждый экземпляр имеет собственную память.

Именно поэтому TON отсчитывает время, а R_TRIG способен обнаруживать фронт сигнала.

━━━━━━━━━━━━━━━━━━

🔄 Что происходит при вызове ФБ?

Создадим простой функциональный блок:

FUNCTION_BLOCK FB_Counter
VAR_INPUT
xEnable : BOOL;
END_VAR

VAR_OUTPUT
iCount : INT;
END_VAR

IF xEnable THEN
iCount := iCount + 1;
END_IF;


В программе объявим экземпляр:

VAR
fbCounter : FB_Counter;
END_VAR


И вызовем:

fbCounter(xEnable := TRUE);


При каждом вызове выполняется тело функционального блока.

Значение iCount при этом сохраняется внутри экземпляра.

Если вызывать блок один раз за цикл, счётчик будет увеличиваться на единицу за цикл.

━━━━━━━━━━━━━━━━━━

⚠️ Что произойдёт при двух вызовах?

Теперь напишем:

fbCounter(xEnable := TRUE);

fbCounter(xEnable := TRUE);


Оба вызова обращаются к одному и тому же экземпляру.

Предположим, начальное значение:

iCount = 0


После первого вызова:

iCount = 1


После второго:

iCount = 2


Получается, что за один цикл ПЛК счётчик увеличился сразу на две единицы.

Если продолжить выполнение:

Цикл 1 → 2
Цикл 2 → 4
Цикл 3 → 6
Цикл 4 → 8


Причина проста: каждый вызов повторно выполняет код ФБ.

━━━━━━━━━━━━━━━━━━

🧠 Почему это важно?

Функциональный блок — не просто набор инструкций.

Его экземпляр хранит собственные данные.

При повторном вызове используется та же память, а не создаётся новый независимый объект.

Это особенно важно для блоков, работа которых зависит от предыдущих состояний.

Например:

• R_TRIG запоминает предыдущее состояние сигнала.
• TON хранит состояние таймера.
• CTU хранит значение счётчика.
• Собственные ФБ могут хранить этапы алгоритма.

Повторный вызов может изменить результат работы всей программы.

━━━━━━━━━━━━━━━━━━

📌 Вывод первой части

Два вызова одного экземпляра ФБ — это не два независимых функциональных блока.

Это повторное выполнение одного объекта с общей внутренней памятью.

➡️ В части 2 рассмотрим более интересную ситуацию: как два вызова одного R_TRIG могут создавать ложные импульсы даже при неизменном входном сигнале.

#CODESYS #ПЛК #StructuredText #FUNCTION_BLOCK
More from @codesys4
  1. Oct 15, 2026document post
  2. Oct 15, 2026🎛 Интерактивный симулятор ПИД-регулятора! Хотите наглядно увидеть, как работают P, I и D…
  3. Oct 15, 2026🧠 РАЗБОР КОДА: R_TRIG ⚠️ Найдите подвох в программе! В CODESYS объявлены переменные: VAR…
  4. Oct 15, 2026🧠 РАЗБОР КОДА: R_TRIG Один экземпляр — два вызова за цикл ПЛК. Сигналы не изменяются: xA…
  5. Oct 15, 2026⚙️ FUNCTION_BLOCK в CODESYS 📘 Часть 3/3. Как избежать ошибок повторного вызова ФБ? В пред…
  6. Oct 15, 2026⚙️ FUNCTION_BLOCK в CODESYS 📘 Часть 2/3. Почему R_TRIG может выдавать ложные импульсы? В…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →