Arduino:Основы/Битовые маски
Содержание | Знакомство с Arduino | Продукты | Основы | Справочник языка Arduino | Примеры | Библиотеки | Хакинг | Изменения | Сравнение языков Arduino и Processing |
Битовые маски[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 бит будут переданы и цикл завершится.