04 мая 2016
Кравченко Виктор

Arduino — битовая арифметика или операции над битами

Цифровые устройства Arduino Arduino Lang
01 На заметку:
Эта статья написана по мотивам оригинальной статьи — Bit Math, об операциях над битами.
02

Вместо введения.

Многие программисты Arduino сталкиваются с тем, что в качестве параметров некоторых функций приходится отправлять переменные типа byte (байт). Байт состоит из 8 битов. Бит — это наименьшая единица информации в компьютерном мире — может принимать всего два значения — 1 или 0.

Возможно, будет также полезно почитать о двоичной системе счисления.
03

В среде Arduino значение байта начинается с буквы B и далее записываются значения байта побитово:

04 Arduino (C++)
1
2
3
// | - старший бит byte mybyte = B11001100; // ^ - младший бит
05

Также при разборе байта используются понятия старшего (high) и младшего (low) бита. В нашем примере старший бит 1 (первый слева), младший — 0 (первый справа, последний).

06

Так, например, при выполнении команды для регистра микроконтроллера DDRD = DDRD | B11111100; — два нуля в конце байта — младшие биты — отвечают как раз за 0 (RX) и 1 (TX) пины платы Arduino.

Доступно о регистрах микроконтроллера, для чего нужны и как использовать можно почитать здесь.
07

Операции над битами — побитовое И (AND)

Оператор побитового И (AND) в C++ — амперсанд &. Правила: результат равен 1, только если обе части выражения равны 1, в остальных случаях результат — 0:
0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1

08

Пример:
1
2
3
byte b1 = B10110010; //B10110010 byte b2 = B11100111; //B11100111 byte result = b1 & b2; //B10100010

09

Побитовое ИЛИ (OR)

Оператор побитового ИЛИ (OR) в C++ — вертикальная черта |. Правила: результат равен 0, только если обе части выражения равны 0, в остальных случаях результат — 1:
0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1

10

Пример:
1
2
3
byte b1 = B10110010; //B10110010 byte b2 = B11100111; //B11100111 byte result = b1 | b2; //B11110111

11

Побитовое Исключающее ИЛИ (XOR)

Оператор побитового Исключающего ИЛИ (XOR) в C++ — символ каретки ^. Правила: результат равен 0, только если обе части выражения равны, в остальных случаях результат — 1:
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0

12

Пример:
1
2
3
byte b1 = B10110010; //B10110010 byte b2 = B11100111; //B11100111 byte result = b1 ^ b2; //B01010101

13

Побитовое НЕ (NOT)

Оператор побитового НЕ (NOT) в C++ — символ тильда ~. В отличие от & и |, используется только с одним операндом. Он просто инвертирует биты.

14

Пример:
1
2
byte b1 = B10110010; //B10110010 byte result = ~ b1; //B01001101

15

Операции над битами — сдвиги битов (Bit Shift Operations)

Существуют только 2 сдвиговые операции над битами — смещение бита влево <<, и смещение бита вправо >>. Следом за знаком смещения следует число, показывающее на сколько позиций сместить биты.

16
17

При смещении бита влево старшие биты теряются, а младшие заполняются нулями:

1
2
byte b1 = B10000011; //B10000011 byte result = b1 << 3; //B00011000

18

При смещении бита вправо младшие биты теряются, а старшие заполняются нулями:

1
2
3
4
5
byte b1 = B10000011; //B10000011 byte result = b1 >> 3; //B00010000 byte b2 = B01100001; //B01100001 result = b2 >> 3; //B00001100

19

Операции с присваиванием

Все упомянутые выше операции (за исключением побитового НЕ (NOT)) можно записывать в краткой форме. Этот прием применяется в случаях, когда в расчете результата используется та же переменная, которой будет присвоен результат:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
byte b1 = B10000011; //-------------------- b1 = b1 >> 3; // то же самое, что и b1 >>= 3; //-------------------- b1 = b1 << 2; // то же самое, что и b1 <<= 2; //-------------------- b1 = b1 | B10011101; // то же самое, что и b1 |= B10011101; //-------------------- b1 = b1 ^ B10011101; // то же самое, что и b1 ^= B10011101; //-------------------- // и т.д.

20
Раздел добавлен 20.12.2017

Манипуляции с единичными битами

Иногда возникает необходимость точечного воздействия на конкретный бит одного байта. Далее представлены примеры основных операций над единичными битами с использованием операций сдвига единичного байта (1=B00000001).

21

Для записи единицы в бит под номером n (где n=[0, 1, .., 7]):

22 Arduino (C++)
1
2
3
4
b |= (1 << n); // Пример byte b = B00000000; b |= (1 << 4); //B00010000
23

Для записи нуля в бит под номером n (где n=[0, 1, .., 7]):

24 Arduino (C++)
1
2
3
4
b &= ~(1 << n); // Пример byte b = B11111111; b &= ~(1 << 4); //B11101111
25

Инвертировать бит под номером n (где n=[0, 1, .., 7]) можно следующим образом:

26 Arduino (C++)
1
2
3
4
5
b ^= (1 << n); // Пример byte b = B11110000; b ^= (1 << 4); //B11100000 b ^= (1 << 1); //B11100010
27

Функции по манипуляции с битами

Если чем-то не устраивают стандартные функции Arduino по работе с битами — bit(), bitWrite(), bitSet(), bitClear(), bitRead(), либо нужно запрограммировать индивидуальные манипуляции с битами, то при помощи стандартных операций, можно реализовать любую битовую логику. Например, операция инвертирования порядка следования битов в байте будет выглядеть так:

28 Arduino (C++)
1
2
3
4
5
6
7
8
9
10
byte b = B10010011; byte result = (((((((0 | (((b >> 7) & 1) << 0)) | (((b >> 6) & 1) << 1)) | (((b >> 5) & 1) << 2)) | (((b >> 4) & 1) << 3)) | (((b >> 3) & 1) << 4)) | (((b >> 2) & 1) << 5)) | (((b >> 1) & 1) << 6)) | (((b >> 0) & 1) << 7); //B11001001
29

Или, если упростить и обернуть в функцию:

30 Arduino (C++)
1
2
3
4
5
6
7
8
9
10
11
byte invertBitOrder(byte b) { byte result = 0; for (int i = 0; i <= 7; i++) { result = result | (((b >> (7 - i)) & 1) << i); } return result; } // Использование byte b = B10010011; Serial.println(invertBitOrder(b), BIN); //B11001001
31

Что почитать:

32

Похожие запросы:

  • Побитовые операции и их применение
comments powered by HyperComments