개요
임베디드 개발자는 비트연산을 사용해서, 장치를 제어하기 때문에 비트연산을 공부해야 한다.
MCU를 예를 들면 하나의 칩 안에 CPU / 메모리 / Disk 까지 모두 들어가 있다.
MCU의 여러개의 “PIN” 중 하나에다가 장치를 전선으로 연결한다.
각 Port의 PIN의 상태를 비트로 관리하고 각 상태마다 장치의 작동 상태를 제어할 수 있다.
n 비트 표현 방법
bit = 0과 1 을 나타내는 최소 단위
- 1101 = 4bit
- 100111 = 6bit
기본적으로 32bit를 기준으로 이야기하지만, 32bit는 너무 길어서 8bit or 16bit 내에서 연습을 한다.
수를 2진수 8bit로 표현하기
- 0xA = 0b00001010
- 0xC = 0b00001100
수를 2진수 10bit로 표현하기
- 0x1E = 0b0000011110
- 0x33 = 0b0000110011
MSB, LSB와비트번호
1Byte를 예로 알아보자
- 1 Byte = 8 bit
- 0번 비트 ~ 7번 비트로 구성
- MSB : 7번 Bit
- LSB : 0번 Bit
비트 연산자
& 연산 (and)
- 값을 추출할 때 사용한다.
- 값에 “1” 을 적은 곳만 추출한다.
| 연산 (or)
- 2진수 덧셈시에 사용된다.
- 둘 중 한 곳에 “1”이 있으면, 결과는 “1” 이다.
^ 연산 ( XOR )
- 청개구리 연산
- 같으면 0, 다르면 1
- 암호화에 사용된다.
Shift 연산자
- 비트 단위로 이동한다.
- Shift 는 2승의 곱 / 나눗셈으로 동작한다.
- 1 << 3 : 1 * (2 ^ 3) 과 동일함
- 3 << 2 : 3 * (2 ^ 2) 과 동일함
- 15 >> 2 : 15 / (2 ^ 2)과 동일함
- << Left Shift
- 값을 왼쪽으로 밀어서 숫자를 추가해준다.
- >> Right Shift
- 값을 오른쪽으로 밀어서 숫자를 삭제한다.
~ 연산 ( not )
- 비트가 반대가 된다.
- “기준 비트 수”에 따라 결과 값이 달라질 수 있다.
비트 연산
비트 연산에서 음수는 배제한다.
따라서 변수 타입은 unsigned를 사용해 주면 된다.
#include<stdio.h>
int main() {
unsigned char a = 0xFA;
unsigned char b, c, d, e;
b = a << 1;
c = a >> 1;
d = a & 0x10;
e = a | 0x2E;
return 0;
}
a는 0xFA로 2진수로 변경하면 0b11111010이다.
b는 왼쪽으로 1만큼 시프트 연산을 했으므로 0b11110100이다.
c는 오른쪽으로 1만큼 시프트 연산을 했으므로 0b01111101이다.
d는 a와 0b00010000과 and연산이므로 0b00010000이다.
e는 a와 0b00101110과 or연산이므로 0b11111110이다.
비트 추출
임베디드에서 비트 추출을 언제쓰는가?
MCU의 특정 핀에 연결된 장치의 상태 버튼이 눌렸는 지, 모터가 동작 중인지 등을 읽어 올 수 있다.
101100 이런 수가 존재한다. 우리의 목적은 2번 bit를 뽑아내서, 출력하는 것이라고 가정해 보자
- 현재 비트를 오른쪽으로 두번 밀자. (>> 2) 001011
- 여기서, 뽑아낼 수를 제외하고 모두 지운다. 0x1 을 & 연산하면 된다.
- 001011 & 0b1 or 0x1 = 1
#include<stdio.h>
int main() {
unsigned char a = 0b11110101;
unsigned char b = (a >> 5) & 1;
unsigned char c = (a >> 6) & 0b11;
unsigned char d = a & 0b111;
return 0;
}
a가 11110101이다.
b는 a의 5번 bit에서 1개 bit를 추출한 값이다.
c는 a의 6번 bit에서 2개 bit를 추출한 값이다.
d는 a의 0번 bit에서 3개 bit를 추출한 값이다.
비트 set/clear
비트 clear
특정 비트를 0 으로 만드는 것을 clear 한다고 표현한다.
ex) 1번 bit에서 1개 bit set 한 값을 저장하기 : a1set = (0x1 << 1) | a;
비트 set
특정 비트를 1로 만드는 것을 set 한다고 한다.
ex) 2번 bit에서 1개 bit, clear 하기 : a2clr = a & ~(1 << 2);
set / clear 는그냥 전부 밀면 되지 않을까?
1번 bit에 1을 넣고 싶으면 a = 0b10 을 하면 되지 않을까? 왜? 비트 연산으로 번거롭게 할까?
- 2번 bit 에 있는 전등을 끄자고 a = 0b10 으로 나머지 bit에 전부 0을 주면, 3번 bit에 연결된 모터도 꺼진다.
- 해당 모터의 기능이 정말 중요한 냉각 장치의 모터였는데 꺼졌다면???
- 시말서로 끝나지 않을 수 있다.
비트 반전
XOR를 이용하여 2번 bit 반전 : b2xor = a ^ (1 << 2);
#include<stdio.h>
int main() {
unsigned char a = 0b10011100;
unsigned char b = (0b111 << 5) ^ a;
return 0;
}
0b10011100
^ 0b11100000
--------------------
0b01111100
실습
1. A : 0xF, B : 0011일때 ~(A & B) << 4를 계산한 결과를 10진수로 출력해 보자
#include<stdio.h>
int main() {
unsigned char a = 0xF;
unsigned char b = 0b11;
unsigned char result = ~(a & b) << 4;
printf("%d", result);
return 0;
}
2. (A ^ 0xCD) & (B >> 3) 를 계산한 결과를 출력한다.
#include<stdio.h>
int main() {
unsigned char a = 0xF;
unsigned char b = 0b11;
unsigned char result = (a ^ 0xCD) & (b >> 3);
printf("%d", result);
return 0;
}
'임베디드 > 임베디드 C언어' 카테고리의 다른 글
[C] C언어 진수 변환 (0) | 2024.09.29 |
---|---|
[C] C언어 메모리 주소와 포인터, 변수 배열 문자열 포인터 (6) | 2024.09.29 |