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

PLC
  Под четностью битовой строки понимается, какое кол-во единичных бит — четное или нечетное — содержит эта строка. Правильнее было бы назвать его битом нечетности, т.к. нечетному кол-ву бит соответствует единичный бит четности, четному кол-ву — нулевой. Математически результат представляет собой сумму всех бит слова по модулю 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;	        //

Все вышесказанное о получении результата функции в булевом виде применимо и здесь.
  • 0
  • 13 декабря 2016, 19:14
  • anakost

Комментарии (1)

RSS свернуть / развернуть
Правильнее было бы назвать его битом нечетности, т.к. нечетному кол-ву бит соответствует единичный бит четности, четному кол-ву — нулевой.
Если бит рассматривать как флаг, то да, единичное состояние соответствует нечетности. Ну или если байт рассматривать как некое число, то тут опять же, младший бит в единичном состоянии есть число нечетное. Однако поскольку этот бит рассматривается как довесок к сумме всех единичных бит, то он вполне оправдывает своё название.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.