Arduino:Основы/Битовые маски: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Нет описания правки
 
Нет описания правки
Строка 13: Строка 13:
Если хотя бы у одного их входных значений в бите будет '''«0»''', в итоге этот '''«0»''' появится и в итоговом значении:
Если хотя бы у одного их входных значений в бите будет '''«0»''', в итоге этот '''«0»''' появится и в итоговом значении:


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
     x:  10001101
     x:  10001101
     y:  01010111
     y:  01010111
Строка 23: Строка 23:
Иногда его называют [[Arduino:Справочник языка Arduino/Побитовые операторы/AND(&),OR и XOR (^)|включающим ИЛИ]]. Если хотя бы у одного их двух входных значений в бите будет '''«1»''', в итоге этот '''«1»''' появится и в итоговом значении:
Иногда его называют [[Arduino:Справочник языка Arduino/Побитовые операторы/AND(&),OR и XOR (^)|включающим ИЛИ]]. Если хотя бы у одного их двух входных значений в бите будет '''«1»''', в итоге этот '''«1»''' появится и в итоговом значении:


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
     x:  10001101
     x:  10001101
     y:  01010111
     y:  01010111
Строка 33: Строка 33:
Сдвигает значение влево на указанное количество позиций. Например:
Сдвигает значение влево на указанное количество позиций. Например:


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
         y = 1010
         y = 1010
         x = y << 1
         x = y << 1
Строка 45: Строка 45:
Работает идентично оператору для сдвига влево, но двигает биты в противоположную сторону, т.е. вправо.
Работает идентично оператору для сдвига влево, но двигает биты в противоположную сторону, т.е. вправо.


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
         y = 1010
         y = 1010
         x = y >> 1
         x = y >> 1
Строка 55: Строка 55:
В качестве практического примера давайте возьмем значение '''«170»''', которое в двоичном виде представляет собой '''«10101010»'''. Чтобы передать это значение через '''контакт 7''', код должен выглядеть следующим образом:
В качестве практического примера давайте возьмем значение '''«170»''', которое в двоичном виде представляет собой '''«10101010»'''. Чтобы передать это значение через '''контакт 7''', код должен выглядеть следующим образом:


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
byte transmit = 7;  //  задаем контакт для передачи данных  
byte transmit = 7;  //  задаем контакт для передачи данных  
byte data = 170;  //  значение для передачи; «10101010»  
byte data = 170;  //  значение для передачи; «10101010»  
Строка 82: Строка 82:
Здесь мы использует цикл [[Arduino:Справочник языка Arduino/Управляющие операторы/for|for()]], чтобы сделать несколько проходов по битовой маске. С каждым проходом через цикл мы сдвигаем значение в маске на одну позицию влево. В данном случае мы используем оператор '''<<=''', который равнозначен, по сути, оператору [[Arduino:Справочник языка Arduino/Побитовые операторы/Операторы побитового сдвига влево и вправо|<<]], но за тем исключением, что делает оператор более компактным.
Здесь мы использует цикл [[Arduino:Справочник языка Arduino/Управляющие операторы/for|for()]], чтобы сделать несколько проходов по битовой маске. С каждым проходом через цикл мы сдвигаем значение в маске на одну позицию влево. В данном случае мы используем оператор '''<<=''', который равнозначен, по сути, оператору [[Arduino:Справочник языка Arduino/Побитовые операторы/Операторы побитового сдвига влево и вправо|<<]], но за тем исключением, что делает оператор более компактным.


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
     00000001
     00000001
   & 10101010
   & 10101010
Строка 91: Строка 91:
В итоге контакт получает значение '''«0»'''. При втором проходе через цикл битовой маской станет значение '''«00000010»''', и операция будет выглядеть следующим образом:
В итоге контакт получает значение '''«0»'''. При втором проходе через цикл битовой маской станет значение '''«00000010»''', и операция будет выглядеть следующим образом:


<syntaxhighlight lang="c" enclose="div">
<syntaxhighlight lang="c">
     00000010
     00000010
   & 10101010
   & 10101010

Версия от 18:17, 14 мая 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Битовые маски[1]

Битовые маски используются, чтобы получить доступ к конкретным битам в байте. В частности, их используют для итерации, к примеру, при последовательной передаче байта данных через один контакт. В этом примере контакту нужно поменять свое состояние с HIGH на LOW для каждого передаваемого бита в байте. Это выполняется при помощи так называемых побитовых операторов и битовой маски.

Побитовые операторы – это такие операторы, которые выполняют логические функции на уровне битов. Среди стандартных побитовых операторов: И (&), ИЛИ (I), сдвиг влево (<<) и сдвиг вправо (>>).

Оператор И (&)

Если хотя бы у одного их входных значений в бите будет «0», в итоге этот «0» появится и в итоговом значении:

    x:  10001101
    y:  01010111
x & y:  00000101

Оператор ИЛИ (I)

Иногда его называют включающим ИЛИ. Если хотя бы у одного их двух входных значений в бите будет «1», в итоге этот «1» появится и в итоговом значении:

    x:  10001101
    y:  01010111
x | y:  11011111

Оператор для сдвига влево (<<)

Сдвигает значение влево на указанное количество позиций. Например:

        y = 1010
        x = y << 1
        x = 0100

Как видите, здесь все байты сдвинулись на одну позицию влево, а бит, находящийся на крайней левой позиции, был удален.

Оператор для сдвига вправо (>>)

Работает идентично оператору для сдвига влево, но двигает биты в противоположную сторону, т.е. вправо.

        y = 1010
        x = y >> 1
        x = 0101

В результате все биты в байте сдвинулись на одну позицию вправо, а бит, находящийся на самом правом краю, был удален.

В качестве практического примера давайте возьмем значение «170», которое в двоичном виде представляет собой «10101010». Чтобы передать это значение через контакт 7, код должен выглядеть следующим образом:

byte transmit = 7;  //  задаем контакт для передачи данных 
byte data = 170;  //  значение для передачи; «10101010» 
byte mask = 1;  //  наша битовая маска
byte bitDelay = 100;

void setup()
{
   pinMode(transmit,OUTPUT);
}

void loop()
{
  for (mask = 00000001; mask>0; mask <<= 1) {  //  делаем проход по битовой маске
    if (data & mask){ // если побитовое И дает «true»
      digitalWrite(transmit,HIGH);  //  отправляем «1»
    }
    else{  //  если побитовое И дает «false»
      digitalWrite(transmit,LOW);  // отправляем «0»
    }
    delayMicroseconds(bitDelay);  // задержка
  }
}

Здесь мы использует цикл for(), чтобы сделать несколько проходов по битовой маске. С каждым проходом через цикл мы сдвигаем значение в маске на одну позицию влево. В данном случае мы используем оператор <<=, который равнозначен, по сути, оператору <<, но за тем исключением, что делает оператор более компактным.

    00000001
  & 10101010
    ________
    00000000

В итоге контакт получает значение «0». При втором проходе через цикл битовой маской станет значение «00000010», и операция будет выглядеть следующим образом:

    00000010
  & 10101010
    ________
    00000010

И в итоге наш выходной контакт получит значение «1». Цикл продолжить делать проход за проходом для каждого бита в маске, пока «1» не сместится за левый край, а маска не превратится в «00000000». Тогда все 8 бит будут переданы и цикл завершится.

См.также

Внешние ссылки