반응형

비트 연산자를 이해하기 위해서는 우선 논리 연산자에 대해 알아야 한다.

논리 연산자는 if 조건문에 사용되며 아래와 같이 세가지가 있고 아두이노 스케치 상 각각의 표기 방법이 정해져 있다.

 

논리 AND : 코드상 표기 &&  (키보드 shift + '7' 두 번 클릭)     // 두 조건의 결과가 모두 참일 때 만 참

논리 OR   : 코드상 표기   ||    (키보드 shift + '\' 두 번 클릭)    // 두 조건의 결과중 하나만 참이이도 참

논리 NOT : 코드상 표기   !    (키보드 shift + '1' 한 번 클릭)     // 조건의 결과가 참이면 거짓, 거짓 이면 참  

 

연산자  조건1 조건2 결과
&&
AND
거짓 거짓
거짓 거짓
거짓 거짓 거짓
||
OR
거짓
거짓
거짓 거짓 거짓
!
NOT
거짓
거짓

 

 

사용 예

if ( 조건1 && 조건2 ) { 실행 코드 }   // 조건1과 조건2가 모두 참일 경우 코드 실행

if ( 조건1 || 조건1 ) { 실행 코드 }      // 조건1 또는 조건2가 참일 경우 코드 실행

if ( !조건 ) { 실행 코드 }                 // 조건이 거짓일 경우 코드 실행, ~조건이 아니면

 

if (digitalRead(2) == HIGH && digitalRead(3) == HIGH) { 실행 코드 } // 두 스위치의 값이 모두 HIGH이면 코드 실행
* "=="는 비교연산자이다. 값1 == 값2, 값1과 값2가 같으면 참, 다르면 거짓   

if (digitalRead(2) == HIGH || digitalRead(3) == HIGH) { 실행 코드 } // 두 스위치의 값중 하나만 HIGH여도 코드 실행

if (!digitalRead(2) == LOW) { 실행 코드 } // 스위치의 값이 LOW가 아니면(0이 아니면) 코드 실행

 

비트 연산

비트 연산은 두 변수의 같은 자리 비트값을 논리 연산을 하는 것이고 표기 방법 및 연산 방법은 아래와 같다.

* 같은 자리의 기준(비트 인덱스)은 변수의 LSB(맨 오른쪽 비트) 부터 0, 왼쪽으로 이동할수록 증가한다. 

  비트인덱스   7654 3210

  val1 = 1;     (0000 0001)

  val2 = 2;     (0000 0010) 

 

비트 AND : 코드상 표기 &  // 두 비트값이 모두 1이면 1 
비트 OR   : 코드상 표기 |    // 두 비트값중 하나만 1이어도 1

비트 NOT : 코드상 표기 ~   // 비트값이 1이면 0
비트 XOR (배타적 OR, Exclusive OR) : 코드상 표기 ^  // 두 비트값이 다르면 1, 같으면 0

 

연산자  조건1 조건2 결과
&
AND
1 1 1
1 0 0
0 1 0
0 0 0
|
OR
1 1 1
1 0 1
0 1 1
0 0 0
~
NOT
1 0
0 1
^
XOR
1 1 0
1 0 1
0 1 1
0 0 0

사용 예

uint8_t num1 =  5; // 자료형이 양수 8비트인 숫자 5 = 0000 0101

uint8_t num2 =  2; // 자료형이 양수 8비트인 숫자 2 = 0000 0010

uint8_t value;        // 자료형이 양수 8비트인 변수 선언

 

value = num1 & num2;  // 0000 0101 & 0000 0010 -> 0000 0000 = 0

value = num1 | num2;    // 0000 0101 | 0000 0010 -> 0000 0111 = 7

value = num1 ^ num2;  // 0000 0101 ^ 0000 0010 -> 0000 0111 = 7

value = 253 ^ 250;       // 1111 1101 ^ 1111 1010 -> 0000 0111 = 7

value = ~num1;           // ~(0000 0101) -> 1111 1010 = 250

value = num1 & 1;       // 0000 0101 & 0000 0001 -> 0000 0001 = 1

num1 &= 1;  // 자신과 1의 비트 AND 연산 후 자신에게 값 할당, num1 = num1 & 1;
num1 |= 2;   // 자신과 2의 비트  OR 연산 후 자신에게 값 할당 
num1 ^= 3;  // 자신과 3의 비트  XOR 연산 후 자신에게 값 할당 

bit.ino
0.00MB

void setup() {
  Serial.begin(9600);
  uint8_t num1 =  5;    // 자료형이 양수 8비트인 숫자 5 = 0000 0101
  uint8_t num2 =  2;    // 자료형이 양수 8비트인 숫자 2 = 0000 0010
  uint8_t value;        // 자료형이 양수 8비트인 변수 선언
  value = num1 & num2;  // 0000 0101 & 0000 0010 -> 0000 0000
  Serial.println(value);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(value, 7-i));
  Serial.println(); 
  value = num1 | num2;  // 0000 0101 | 0000 0010 -> 0000 0111
  Serial.println(value);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(value, 7-i));
  Serial.println();
  value = num1 ^ num2;  // 0000 0101 ^ 0000 0010 -> 0000 0111
  Serial.println(value);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(value, 7-i));
  Serial.println();
  value = 253 ^ 250;    // 1111 1101 ^ 1111 1010 -> 0000 0111
  Serial.println(value);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(value, 7-i));
  Serial.println();
  value = ~num1;        // ~(0000 0101) -> 1111 1010
  Serial.println(value);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(value, 7-i));
  Serial.println();
  value = num1 & 1;     // 0000 0101 & 1(0000 0001) -> 0000 0001
  Serial.println(value);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(value, 7-i));
  Serial.println();
}

void loop() {
}

* bitRead(val, 비트 인덱스) 함수는 변수의 비트값을 읽어오는 함수이고, 비트 인덱스는 변수의 LSB(맨 오른쪽 비트) 부터 0, 왼쪽으로 이동할수록 증가한다. 

비트인덱스 7654 3210

val = 1;     (0000 0001)

 

* Serial.println(val, BIN); 함수는 시리얼 모니터로 비트값을 출력해주는 함수이다. 하지만 MSB 영역의 연속된 0값은 표시하지 않는다.

Serial.println(27, BIN); // 31 = 0001 0111 -> 10111

Serial.println(1, BIN);  // 1 = 0000 0001 -> 1

 

8비트의 모든 값을 시리얼 모니터에 표시하기 위해 

for (int i = 0; i < 8; i++) Serial.print(bitRead(value, 7-i)); 코드를 사용해 주었다. 

 

* 아두이노 비트 관련 함수

bit(n) 함수는 비트 인덱스 n의 비트값이 1일 경우의 값을 출력해 준다. 

                                       비트인덱스 . . .  .   . . . .  7654 3210

uint8_t n = 15;  //                         (1000 0000 0000 0000) =  32768

Serial.println(bit(n));   //  비트 인덱스 15가 1일때 값은?

비트 인덱스의 범위는 0 ~ 31까지 이다. 32비트 값까지만 계산하여 출력한다. 인덱스의 범위를 넘어서면 0을 출력한다. 

 

bitSet(val, n)  함수는 변수 val의 특정 비트인덱스 n의 값에 1을 쓴다.
uint16_t val = 0;          // (0000 0000 0000 0000)

bitSet(val, 15);    // (1000 0000 0000 0000)

Serial.println(val);      // 32768

 

bitClear(val, n) 함수는 변수 val의 특정 비트의 값을 지운다(0을 쓴다, 0으로 만든다).

uint16_t val = 32768;    // (1000 0000 0000 0000)

bitClear(val, 15);            // (0000 0000 0000 0000)

Serial.println(val);        // 0

 

bitWrite(val, n, b)  함수는 변수 val의 특정 비트인덱스 n의 값에 b값(0또는 1)을 쓴다. bitSet()와 bitClear() 함수 기능을 한 함수로 처리할 수 있다. 

uint16_t val = 0;          // (0000 0000 0000 0000)

bitWrite(val, 15, 1);    // (1000 0000 0000 0000) , bitSet(val, 15)

bitWrite(val, 15, 0);    // (0000 0000 0000 0000) , bitClear(val, 15)

Serial.println(val);      // 0

 

highByte(val) 함수는 word(아두이노 우노의 경우 16 비트 자료형)의 높은바이트(MSB(왼쪽) 8비트)를 추출한다.

     0000 0000     0000 0000     - 2Byte(16bit) 
  |   MSB 영역  |   LSB  영역  | 

uint16_t val = 25489 // (0110 0011 1001 0001)

uint8_t MSB = highByte(val);

Serial.println(MSB );   // (0110 0011)

 

lowByte(val) 함수는 word(아두이노 우노의 경우 16 비트 자료형)의 낮은바이트(LSB(오른쪽) 8비트)를 추출한다.

uint16_t val = 25489 // (0110 0011 1001 0001)

uint8_t LSB = highByte(val);

Serial.println(LSB );   // (1001 0001)

 

테스트 스케치

arduino_bit_function.ino
0.00MB

void setup() {
  Serial.begin(9600);
  uint8_t n = 15;          // 비트 인덱스
  Serial.println(bit(n));  // 비트 인덱스 15의 값이 1일때의 값은?
  uint16_t val = 0;        // (0000 0000 0000 0000)
  bitSet(val, 15);         // (1000 0000 0000 0000)
  for (int i = 0; i < 16; i++) Serial.print(bitRead(val, 15-i)); 
  Serial.println();
  Serial.println(val);
  bitClear(val, 15);       // (0000 0000 0000 0000)
  for (int i = 0; i < 16; i++) Serial.print(bitRead(val, 15-i)); 
  Serial.println();
  Serial.println(val);
  bitWrite(val, 15, 1);    // (1000 0000 0000 0000)
  bitWrite(val, 15, 0);    // (0000 0000 0000 0000)
  val = 25489;             // (0110 0011 1001 0001)
  uint8_t MSB = highByte(val);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(MSB, 7-i)); 
  Serial.println();
  Serial.println(MSB);     // (0110 0011), 99
  uint8_t LSB = lowByte(val);
  for (int i = 0; i < 8; i++) Serial.print(bitRead(LSB, 7-i)); 
  Serial.println();
  Serial.println(LSB);     // (1001 0001), 145
}

void loop() {
}

 

관련 글

[arduino] - 아두이노 - 비트 연산자

[arduino] - 아두이노 - 비트 시프트 연산자

[arduino] - 아두이노 - 비트 마스크, bit mask

[arduino] - 아두이노 - 도트 매트릭스 제어하기, dot matrix

 

 

 

+ Recent posts