Simatic Step 7. STL. Установка/сброс бита по номеру — АСУ ТП: сообщество инженеров

Simatic Step 7. STL. Установка/сброс бита по номеру

По сути это программная реализация двоичного дешифратора (декодера). Он преобразует двоичный код номера бита в унитарный код со значащей единицей (нулем).

В стандартной библиотеке уже есть функция FC97 «DECO» для этой цели.

FUNCTION "DECO" : DWORD
TITLE = DECO (Decode Binary Position)
AUTHOR : SEA
FAMILY : CONVERT
NAME : DECO
VERSION : 2.0
VAR_INPUT
  IN : WORD;    
END_VAR
VAR_TEMP
  wrk : WORD;  
END_VAR
BEGIN
NETWORK
TITLE =
  L     1;              // set default out-value
  T     #RET_VAL;       // .
  L     #IN;            // for(wrk = in % 32; wrk > 0; wrk--)
  AD    DW#16#1F;       // {
  L     1;              // .
  +I    ;               // .
  JU    A001;           // .
A002:
  T     #wrk;           // .
  L     #RET_VAL;       //   out <<= 1
  SLD   1;              //   .
  T     #RET_VAL;       //   .
  L     #wrk;           // }
A001:
  LOOP  A002;           // .
  SET;                  // set BR
  SAVE;                 // .
 
END_FUNCTION

Алгоритм работы сдвигает единицу в регистре в цикле. В качестве счетчика цикла используется копия номера бита, т.е. цикл может выполниться до 32 раз. Это небыстрый алгоритм. Можно посчитать число команд, которые будут выполнены при входных аргументах 0 и 31.

  • аргумент 0, 7 + 6 * 1 + 2 = 15 команд;
  • аргумент 31, 7 + 6 * 32 + 2 = 201 команда;

Строго говоря две последние команды к алгоритму отношения не имеют, состояние бита ВР учитывается только в языке FBD для входа/выхода разрешения EN/ENO.
Очень быстрый алгоритм дешифратора можно получить используя STL команду распределенного перехода JL.

FUNCTION FC12: DWORD     
TITLE = Установка бита по номеру
AUTHOR:   Anakost  
FAMILY:   SOHO    
NAME:     NumSetBt      // Number + Setting + Bit  
VERSION:  1.0      
VAR_INPUT
  InCod: BYTE;          //номер бита
END_VAR
BEGIN
NETWORK
TITLE = Распределенный переход по номеру
      L #InCod;         // Загрузка номера перехода в ACCU1-L-L
      JL Exit;          // Переход выполнится при ACCU1-L-L > 32
      JU L000;          // Переход выполнится при ACCU1-L-L = 0
      JU L001;          // Переход выполнится при ACCU1-L-L = 1
      JU L002;          // Переход выполнится при ACCU1-L-L = 2
      JU L003;          // Переход выполнится при ACCU1-L-L = 3
      JU L004;          // Переход выполнится при ACCU1-L-L = 4
      JU L005;          // Переход выполнится при ACCU1-L-L = 5
      JU L006;          // Переход выполнится при ACCU1-L-L = 6
      JU L007;          // Переход выполнится при ACCU1-L-L = 7
      JU L008;          // Переход выполнится при ACCU1-L-L = 8
      JU L009;          // Переход выполнится при ACCU1-L-L = 9
      JU L010;          // Переход выполнится при ACCU1-L-L = 10
      JU L011;          // Переход выполнится при ACCU1-L-L = 11
      JU L012;          // Переход выполнится при ACCU1-L-L = 12
      JU L013;          // Переход выполнится при ACCU1-L-L = 13
      JU L014;          // Переход выполнится при ACCU1-L-L = 14
      JU L015;          // Переход выполнится при ACCU1-L-L = 15
      JU L016;          // Переход выполнится при ACCU1-L-L = 16
      JU L017;          // Переход выполнится при ACCU1-L-L = 17
      JU L018;          // Переход выполнится при ACCU1-L-L = 18
      JU L019;          // Переход выполнится при ACCU1-L-L = 19
      JU L020;          // Переход выполнится при ACCU1-L-L = 20
      JU L021;          // Переход выполнится при ACCU1-L-L = 21
      JU L022;          // Переход выполнится при ACCU1-L-L = 22
      JU L023;          // Переход выполнится при ACCU1-L-L = 23
      JU L024;          // Переход выполнится при ACCU1-L-L = 24
      JU L025;          // Переход выполнится при ACCU1-L-L = 25
      JU L026;          // Переход выполнится при ACCU1-L-L = 26
      JU L027;          // Переход выполнится при ACCU1-L-L = 27
      JU L028;          // Переход выполнится при ACCU1-L-L = 28
      JU L029;          // Переход выполнится при ACCU1-L-L = 29
      JU L030;          // Переход выполнится при ACCU1-L-L = 30
      JU L031;          // Переход выполнится при ACCU1-L-L = 31
      JU L032;          // Переход выполнится при ACCU1-L-L = 32
Exit: JU Err;                   // Ошибочный ввод
L000: JU Err;                   // Ветвь кода при ACCU1-L-L = 0
L001: L DW#16#00000001; JU Out; // Ветвь кода при ACCU1-L-L = 1
L002: L DW#16#00000002; JU Out; // Ветвь кода при ACCU1-L-L = 2
L003: L DW#16#00000004; JU Out; // Ветвь кода при ACCU1-L-L = 3
L004: L DW#16#00000008; JU Out; // Ветвь кода при ACCU1-L-L = 4
L005: L DW#16#00000010; JU Out; // Ветвь кода при ACCU1-L-L = 5
L006: L DW#16#00000020; JU Out; // Ветвь кода при ACCU1-L-L = 6
L007: L DW#16#00000040; JU Out; // Ветвь кода при ACCU1-L-L = 7
L008: L DW#16#00000080; JU Out; // Ветвь кода при ACCU1-L-L = 8
L009: L DW#16#00000100; JU Out; // Ветвь кода при ACCU1-L-L = 9
L010: L DW#16#00000200; JU Out; // Ветвь кода при ACCU1-L-L = 10
L011: L DW#16#00000400; JU Out; // Ветвь кода при ACCU1-L-L = 11
L012: L DW#16#00000800; JU Out; // Ветвь кода при ACCU1-L-L = 12
L013: L DW#16#00001000; JU Out; // Ветвь кода при ACCU1-L-L = 13
L014: L DW#16#00002000; JU Out; // Ветвь кода при ACCU1-L-L = 14
L015: L DW#16#00004000; JU Out; // Ветвь кода при ACCU1-L-L = 15
L016: L DW#16#00008000; JU Out; // Ветвь кода при ACCU1-L-L = 16
L017: L DW#16#00010000; JU Out; // Ветвь кода при ACCU1-L-L = 17
L018: L DW#16#00020000; JU Out; // Ветвь кода при ACCU1-L-L = 18
L019: L DW#16#00040000; JU Out; // Ветвь кода при ACCU1-L-L = 19
L020: L DW#16#00080000; JU Out; // Ветвь кода при ACCU1-L-L = 20
L021: L DW#16#00100000; JU Out; // Ветвь кода при ACCU1-L-L = 21
L022: L DW#16#00200000; JU Out; // Ветвь кода при ACCU1-L-L = 22
L023: L DW#16#00400000; JU Out; // Ветвь кода при ACCU1-L-L = 23
L024: L DW#16#00800000; JU Out; // Ветвь кода при ACCU1-L-L = 24
L025: L DW#16#01000000; JU Out; // Ветвь кода при ACCU1-L-L = 25
L026: L DW#16#02000000; JU Out; // Ветвь кода при ACCU1-L-L = 26
L027: L DW#16#04000000; JU Out; // Ветвь кода при ACCU1-L-L = 27
L028: L DW#16#08000000; JU Out; // Ветвь кода при ACCU1-L-L = 28
L029: L DW#16#10000000; JU Out; // Ветвь кода при ACCU1-L-L = 29
L030: L DW#16#20000000; JU Out; // Ветвь кода при ACCU1-L-L = 30
L031: L DW#16#40000000; JU Out; // Ветвь кода при ACCU1-L-L = 31
L032: L DW#16#80000000; JU Out; // Ветвь кода при ACCU1-L-L = 32
Err:  L DW#16#00000000;         // Ошибочный ввод
Out:  T #RET_VAL;               // Результат
 
END_FUNCTION

В этом алгоритме кол-во выполняемых команд не превышает пяти для любого аргумента.
Есть не принципиальное отличие в логике работы. Библиотечная функция принимает в качестве аргумента слово WORD и при необходимости обрезает его по модулю 32 (5 значащих бит). 0 используется как значащий аргумент и устанавливает младший бит в слове.
Я написал функцию под свой алгоритм, а мне было нужно чтобы 0 и числа более 32 использовались как запрещающий сигнал на выходе.
Функция с распределенным переходом получилась настолько гибкая, что реакцию выхода на входной аргумент можно настроить как угодно. Двоичный код 0..255 можно преобразовать в унитарный, семисегментный, ASCII, Грея и т.д.
Не обошлось и без ложки дегтя, платой за универсальность и быстродействие стал гораздо больший размер функции (516 слов вместо 92).

Источник: http://we.easyelectronics.ru/plc/simatic-step-7-stl-ustanovka-sbros-bita-po-nomeru.html

🔗 Simatic Step 7. STL. Установка/сброс бита по номеру

Оставьте комментарий

Войти

Зарегистрироваться

Сбросить пароль

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

Прокрутить вверх