Битовые операторы выполняют свои расчеты на уровне битов переменных. Они помогают решать широкий круг общих проблем программирования. Хорошую статью по битовым операциям можно найти на Википедии
Побитовое И (&)
В С++ оператор побитового И указывается одиночным амперсандом, он ставится между двумя целыми выражениями. Побитовое И действует на позиции каждого бита, окружающих выражения независимо от того какой из операндов стоит первым, а какой вторым.
В соответствии с правилом: если оба входных бита равны 1, результирующий выходной сигнал равен 1, в противном случае выход равен 0. Иллюстрация:
0 0 1 1 операнд1
0 1 0 1 операнд2
----------
0 0 0 1 результат (операнд1 & операнд2)
В среде разработки Arduino тип int это 16-битное значение, таким образом оператор побитовое И между двумя int выражениями делает 16 одновременных И операций. Иллюстрация:
int a = 92; // в двоичном виде: 0000000001011100
int b = 101; // в двоичном виде: 0000000001100101
int c = a & b; // результат: 0000000001000100, или 68 в десятичном представлении
Каждый бит значений a и b проходит операцию побитового И, в результате все 16 битов попадают в переменную c, полученное значение будет 01000100, что равносильно 65 в двоичном представлении.
Наиболее часто операция побитового И используется для выбора конкретного бит (или битов) от целого значения, часто называемая маска. См. пример ниже.
Побитовое ИЛИ (|)
Побитовое ИЛИ в C++ обозначается вертикальной чертой, |. Как и оператор &, оператор | работает независимо с каждым битом окружающиъ его чисел.
Результат операции побитового ИЛИ двух бит будет 1, если хотя бы один из этих битов 1, иначе резульат будет 0. Другими словами:
0 0 1 1 операнд1
0 1 0 1 операнд2
----------
0 1 1 1 (операнд1 | операнд2) - результат
Пример использования операции побитового ИЛИ в фрагменте кода на C++:
int a = 92; // в бинарном виде: 0000000001011100
int b = 101; // в бинарном виде: 0000000001100101
int c = a | b; // результат: 0000000001111101, или 125 в десятичном виде.
Пример программы
Основная область примернения операторов побитовое И/ИЛИ это операции чтение/записи в порт. В микроконтроллерах порт это 8-битовое число, через которое можно получить информацию о состоянии контактов.
Записи в порт контролирует все контакты сразу.
PORTD является встроенной константой, которая относится к выходному состоянию цифровых выводов 0,1,2,3,4,5,6,7. Если в каком-то бите установлена 1, значит на выводе состояние HIGH.
(Вывод при этом должен быть установлен как выход командой pinMode().) Таким образом, если записать PORTD = B00110001;
мы установим выводы 2,3 и 7 в состояние логической 1.
Наш алгоритм будет выглядеть вот так:
- Получить значение PORTD и очистить биты относящиеся к выводам, значение которые мы хотим изменить (с помощью побитового И).
- Скомбинировать значение PORTD с нашим новым значением (через операцию побитового ИЛИ).
int i; // переменная счетчика
int j;
void setup(){
DDRD = DDRD | B11111100; // установить биты направлений для выводов с 2 по 7, оставить нетронутыми для выводов 0 и 1 (xx | 00 == xx)
// это тоже самое что и оператор pinMode(pin, OUTPUT) для выводов с 2 по 7
Serial.begin(9600);
}
void loop(){
for (i=0; i<64; i++){
PORTD = PORTD & B00000011; // очистить биты с 2 по 7, оставить биты (а занчить и выводы) 0 и 1 неизмененными (xx & 11 == xx)
j = (i << 2); // сдвинуть переменную на два бита влево к пинам 2 -7, чтобы не затронуть пины 0 и 1
PORTD = PORTD | j; // скомбинирвать значение порта с новым значением
Serial.println(PORTD, BIN); // для отладки выведем значение порта в терминал
delay(100);
}
}
побитовое XOR или исключающее ИЛИ (^)
Еще один побитовый оператор, немного похожий на обычное бинарное ИЛИ, но небольшим отлиием — он вернет 0, если оба бита будут равны 1. Обозначается символом ^.
0 0 1 1 операнд1
0 1 0 1 операнд2
----------
0 1 1 0 (операнд1 ^ операнд2) - результат
Другими словами, после операции илсключающего ИЛИ будет 1 в том случае, если входные биты различны или оба равны 0.
Пример кода:
int x = 12; // в бинарном представлении: 1100
int y = 10; // в бинарном представлении: 1010
int z = x ^ y; // в бинарном представлении: 0110, или десятчиная 6
Оператор ^ часто используется для переключения (т.е. чтобы изменить 0 на 1 или 1 на 0) каких-либо битов в цифровом представлении.
Пример программы для переключения цифрового вывода 5.
void setup(){
DDRD = DDRD | B00100000; // установили цифровой вывод 5 как выход
Serial.begin(9600);
}
void loop(){
PORTD = PORTD ^ B00100000; // переключили бит 5 (цифровой вывод 5), остальные оставили нетронутыми
delay(100);
}