Битовые маски в Arduino

Битовые маски используются для доступа к отдельным битам в байте данных.

Авторы: Arduino

Последняя редакция: 16.01.2024

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

Побитовые операции выполняют логические функции, действующие на уровне отдельных битов. К стандартным побитовым операциям относятся AND (&), OR (|), сдвиг влево (<<) и сдвиг вправо (>>).

Оператор AND (&) даёт в результате 1 в каждой битовой позиции, где оба входных значения равны 1. Например:

    x:  10001101

    y:  01010111

x & y:  00000101

Оператор OR (|), также известный как «включающее ИЛИ», даёт в результате 1 в каждой битовой позиции, где хотя бы одно из входных значений равно 1. Например:

    x:  10001101

    y:  01010111

x | y:  11011111

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

y = 1010

        x = y << 1

yields: x = 10100

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

Оператор сдвига вправо (>>) работает аналогично сдвигу влево, за исключением того, что он сдвигает значение вправо на указанное число позиций. Например:

y = 1010

        x = y >> 1

yields: 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){ // если побитовое AND даёт истину

      digitalWrite(transmit,HIGH); // отправляем 1

    }

    else{ //если побитовое AND даёт ложь

      digitalWrite(transmit,LOW); // отправляем 0

    }

    delayMicroseconds(bitDelay); //задержка

  }
}

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

00000001
& 10101010

  ________

  00000000

И наш выходной пин устанавливается в 0. Во второй раз через цикл маска = 00000010, поэтому наша операция выглядит так:

00000010
& 10101010

  ________

  00000010

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

Примечание

Лицензия: документация Arduino распространяется под лицензией Creative Commons Attribution-Share Alike 4.0.