Simatic Step 7. STL. Бит четности (паритета). — АСУ ТП: сообщество инженеров

Simatic Step 7. STL. Бит четности (паритета).

Под четностью битовой строки понимается, какое кол-во единичных бит — четное или нечетное — содержит эта строка. Правильнее было бы назвать его битом нечетности, т.к. нечетному кол-ву бит соответствует единичный бит четности, четному кол-ву — нулевой. Математически результат представляет собой сумму всех бит слова по модулю 2, т.е. над всеми битами выполняется операция

исключающее ИЛИ

. В стандартной библиотеке такой функции нет.

Я уже приводил один из способов проверки слова на четность (

подсчет установленных бит

). Там четность получается как побочный эффект вычислений и представляет собой младший бит значения возвращаемого функцией. Но если кол-во установленных бит вас не интересует, вычислять четность слова лучше с помощью более эффективных специализированных методов.

Классический метод вычисления для DWORD взят из книги Генри Уорена «Алгоритмические трюки для программистов», 2014 г.

  x = x ^ (x >> 1);
  x = x ^ (x >> 2);
  x = x ^ (x >> 4);
  x = x ^ (x >> 8);
  x = x ^ (x >> 16);
  x = x & 1;

Бит четности окажется в младшем разряде

х

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

STL

использует для расчетов только внутренние регистры:

FUNCTION FC10: VOID     
TITLE = "Определение четности числа"
AUTHOR:   Anakost       // 
FAMILY:   SOHO          //
NAME:     BtParity      // Bit + Parity
VERSION:  1.0           //
VAR_INPUT            
  Input: DWORD;    
END_VAR
VAR_OUTPUT            
  Parity: DWORD;
END_VAR
BEGIN
NETWORK
TITLE = Вычисление четности числа DWORD
  L #Input;             //
// x = x ^ (x >> 1);
  PUSH;                 //
  SRD 1;                //
  XOD;                  //
// x = x ^ (x >> 2);
  PUSH;                 //
  SRD 2;                //
  XOD;                  //
// x = x ^ (x >> 4);
  PUSH;                 //
  SRD 4;                //
  XOD;                  //
// x = x ^ (x >> 8);
  PUSH;                 //
  SRD 8;                //
  XOD;                  //
// x = x ^ (x >> 16);
  PUSH;                 //
  SRD 16;               //
  XOD;                  //
// x = x & 1;
  AD DW#16#1;           //
  T #Parity;            //
 
END_FUNCTION

Функция работает правильно, но получение выходного результата в младшем бите слова

DWORD

мне показалось неудобным. Сначала нужно результат присвоить меркеру, а затем уже проверять младший бит в нем. С локальной переменной еще сложнее. Поэтому я немного изменил функцию, чтобы сразу получить битовый результат:

VAR_OUTPUT            
  Parity: BOOL;
END_VAR
...
  SLD 1;        // 1,2mkc    // second bit <- bit parity
  T STW;        // 0,6mkc    // RLO <- bit parity
  = #Parity;    // 0,4mkc    // Parity <- RLO

Я изменил обьявление выхода на

BOOL

, и две последние строчки заменил на три новые. Дело в том, что бит

RLO

в статусном регистре

Simatic

находится во втором справа бите. Поэтому бит паритета сначала сдвигается на вторую позицию, а затем напрямую заносится в статусный регистр на место бита

RLO

. Следующая операция присваивает бит

RLO

выходу. Применять операцию

AD DW#16#1

здесь без надобности, т.к. изменение других битов статусного регистра нас не волнует (и не для всех возможно).

Можно и по другому, более традиционно и наглядно (как выяснилось, этот вариант еще и быстрее, увидел проставив типовое время выполнения):

...
  AD DW#16#1;   // 0,3mkc    // ACCU1 and 1
  A <>0;        // 0,2mkc    // RLO <- ACCU1 <> 0
  = #Parity;    // 0,4mkc    // Parity <- RLO

Функция работает очень быстро, но в той же книге есть более оптимальный для

Simatic

алгоритм:

  x = x ^ (x >> 1);
  x = (x ^ (x >> 2)) & 0x11111111;
  x = x mod 15;
  x = x & 1;

Ее код на

STL

:

NETWORK
TITLE = Вычисление четности числа DWORD
  L #Input;             //
// x = x ^ (x >> 1);
  PUSH;                 //
  SRD 1;                //
  XOD;                  //
// x = (x ^ (x >> 2)) & 0x11111111;
  PUSH;                 //
  SRD 2;                //
  XOD;                  //
  AD DW#16#11111111;    //
// x = x mod 15;
  L 15;                 //
  MOD;                  //
// x = x & 1;
  AD DW#16#1;           //
  T #Parity;            //

Все вышесказанное о получении результата функции в булевом виде применимо и здесь..

Источник: http://we.easyelectronics.ru/plc/simatic-step-7-stl-bit-chetnosti-pariteta.html

🔗 Simatic Step 7. STL. Бит четности (паритета).

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

Войти

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

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

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

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