Giao diện
🔢 Bit Manipulation — Control Hardware Registers
Hardware registers được điều khiển bằng từng bit. Mastering bitwise operators là kỹ năng bắt buộc!
Analogy: Bảng công tắc đèn
┌─────────────────────────────────────────────────────────────────┐
│ LIGHT SWITCH PANEL │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Một register 8-bit giống như bảng 8 công tắc: │
│ │
│ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
│ │ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ ← Bit # │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
│ │ OFF │ ON │ OFF │ OFF │ ON │ OFF │ ON │ OFF │ │
│ │ 0 │ 1 │ 0 │ 0 │ 1 │ 0 │ 1 │ 0 │ = 0x4A │
│ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ │
│ │
│ Bạn cần biết cách: │
│ • Bật 1 công tắc (SET bit) │
│ • Tắt 1 công tắc (CLEAR bit) │
│ • Đảo trạng thái (TOGGLE bit) │
│ • Kiểm tra trạng thái (READ bit) │
│ │
└─────────────────────────────────────────────────────────────────┘1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Bitwise Operators
| Operator | Name | Description |
|---|---|---|
& | AND | Cả hai bit = 1 → kết quả = 1 |
| | OR | Ít nhất một bit = 1 → kết quả = 1 |
^ | XOR | Hai bit khác nhau → kết quả = 1 |
~ | NOT | Đảo tất cả bits |
<< | Left Shift | Dịch trái n vị trí |
>> | Right Shift | Dịch phải n vị trí |
Truth Tables
AND (&) OR (|) XOR (^)
┌───┬───┬───┐ ┌───┬───┬───┐ ┌───┬───┬───┐
│ A │ B │ R │ │ A │ B │ R │ │ A │ B │ R │
├───┼───┼───┤ ├───┼───┼───┤ ├───┼───┼───┤
│ 0 │ 0 │ 0 │ │ 0 │ 0 │ 0 │ │ 0 │ 0 │ 0 │
│ 0 │ 1 │ 0 │ │ 0 │ 1 │ 1 │ │ 0 │ 1 │ 1 │
│ 1 │ 0 │ 0 │ │ 1 │ 0 │ 1 │ │ 1 │ 0 │ 1 │
│ 1 │ 1 │ 1 │ │ 1 │ 1 │ 1 │ │ 1 │ 1 │ 0 │
└───┴───┴───┘ └───┴───┴───┘ └───┴───┴───┘1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Core Operations
1. SET Bit (Bật)
cpp
// SET bit n to 1
// Formula: reg |= (1 << n)
uint8_t reg = 0b00000000; // 0x00
reg |= (1 << 3); // Set bit 3
// Result: 0b00001000 = 0x08
reg |= (1 << 7); // Set bit 7
// Result: 0b10001000 = 0x881
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
0b00000000 SET bit 3 0b00001000
┌─┬─┬─┬─┬─┬─┬─┬─┐ ──────────────► ┌─┬─┬─┬─┬─┬─┬─┬─┐
│0│0│0│0│0│0│0│0│ |= (1 << 3) │0│0│0│0│1│0│0│0│
└─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘
↑
bit 3 ON1
2
3
4
5
6
2
3
4
5
6
2. CLEAR Bit (Tắt)
cpp
// CLEAR bit n to 0
// Formula: reg &= ~(1 << n)
uint8_t reg = 0b11111111; // 0xFF
reg &= ~(1 << 3); // Clear bit 3
// Result: 0b11110111 = 0xF7
reg &= ~(1 << 0); // Clear bit 0
// Result: 0b11110110 = 0xF61
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
0b11111111 CLEAR bit 3 0b11110111
┌─┬─┬─┬─┬─┬─┬─┬─┐ ──────────────► ┌─┬─┬─┬─┬─┬─┬─┬─┐
│1│1│1│1│1│1│1│1│ &= ~(1 << 3) │1│1│1│1│0│1│1│1│
└─┴─┴─┴─┴─┴─┴─┴─┘ └─┴─┴─┴─┴─┴─┴─┴─┘
↑
bit 3 OFF1
2
3
4
5
6
2
3
4
5
6
3. TOGGLE Bit (Đảo)
cpp
// TOGGLE bit n
// Formula: reg ^= (1 << n)
uint8_t reg = 0b00001000;
reg ^= (1 << 3); // Toggle bit 3: ON → OFF
// Result: 0b00000000
reg ^= (1 << 3); // Toggle bit 3: OFF → ON
// Result: 0b000010001
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
4. READ Bit (Đọc)
cpp
// READ bit n
// Formula: (reg >> n) & 1 OR (reg & (1 << n)) != 0
uint8_t reg = 0b10101010;
bool bit3 = (reg >> 3) & 1; // bit3 = 1
bool bit2 = (reg >> 2) & 1; // bit2 = 0
// Alternative
if (reg & (1 << 7)) {
// Bit 7 is set
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Practical Example: GPIO Control
cpp
// Simulated GPIO register addresses
volatile uint8_t* const GPIO_DIR = (uint8_t*)0x40021000; // Direction
volatile uint8_t* const GPIO_OUT = (uint8_t*)0x40021004; // Output
volatile uint8_t* const GPIO_IN = (uint8_t*)0x40021008; // Input
// Pin definitions
constexpr uint8_t LED_PIN = 5;
constexpr uint8_t BUTTON_PIN = 3;
// Configure pin as output
void pinMode_output(uint8_t pin) {
*GPIO_DIR |= (1 << pin); // Set direction bit
}
// Configure pin as input
void pinMode_input(uint8_t pin) {
*GPIO_DIR &= ~(1 << pin); // Clear direction bit
}
// Write to output pin
void digitalWrite(uint8_t pin, bool value) {
if (value) {
*GPIO_OUT |= (1 << pin); // SET
} else {
*GPIO_OUT &= ~(1 << pin); // CLEAR
}
}
// Read input pin
bool digitalRead(uint8_t pin) {
return (*GPIO_IN >> pin) & 1;
}
// Toggle LED
void toggleLED() {
*GPIO_OUT ^= (1 << LED_PIN); // TOGGLE
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Multiple Bits Operations
cpp
// Set multiple bits at once
uint8_t reg = 0;
reg |= (1 << 3) | (1 << 5) | (1 << 7); // Set bits 3, 5, 7
// Result: 0b10101000
// Clear multiple bits
reg &= ~((1 << 3) | (1 << 5)); // Clear bits 3 and 5
// Result: 0b10000000
// Read a field (multiple bits)
uint8_t config = 0b11010110;
uint8_t field = (config >> 2) & 0x07; // Read bits 2-4 (3 bits)
// field = 0b101 = 51
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Bit Masks & Macros
cpp
// Common macros for bit manipulation
#define BIT(n) (1U << (n))
#define SET_BIT(reg, n) ((reg) |= BIT(n))
#define CLEAR_BIT(reg, n) ((reg) &= ~BIT(n))
#define TOGGLE_BIT(reg, n) ((reg) ^= BIT(n))
#define READ_BIT(reg, n) (((reg) >> (n)) & 1U)
// Field extraction
#define GET_FIELD(reg, mask, shift) \
(((reg) & (mask)) >> (shift))
#define SET_FIELD(reg, mask, shift, value) \
((reg) = ((reg) & ~(mask)) | (((value) << (shift)) & (mask)))
// Usage
uint8_t status = 0;
SET_BIT(status, 3); // Set bit 3
CLEAR_BIT(status, 3); // Clear bit 3
bool b = READ_BIT(status, 3);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Hardware Register Example
cpp
// Timer configuration register
// Bits 0-1: Mode (0=off, 1=oneshot, 2=repeat)
// Bit 2: Enable
// Bits 3-7: Prescaler value
volatile uint8_t* const TIMER_CTRL = (uint8_t*)0x40010000;
// Mode field
constexpr uint8_t MODE_MASK = 0b00000011;
constexpr uint8_t MODE_SHIFT = 0;
// Enable bit
constexpr uint8_t ENABLE_BIT = 2;
// Prescaler field
constexpr uint8_t PRESCALER_MASK = 0b11111000;
constexpr uint8_t PRESCALER_SHIFT = 3;
void setupTimer(uint8_t mode, uint8_t prescaler) {
uint8_t reg = 0;
// Set mode (bits 0-1)
reg |= (mode & 0x03);
// Set prescaler (bits 3-7)
reg |= (prescaler << PRESCALER_SHIFT);
// Enable timer
reg |= (1 << ENABLE_BIT);
*TIMER_CTRL = reg;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
📚 Tổng kết
| Operation | Formula | Example |
|---|---|---|
| SET | reg |= (1 << n) | Turn ON bit n |
| CLEAR | reg &= ~(1 << n) | Turn OFF bit n |
| TOGGLE | reg ^= (1 << n) | Flip bit n |
| READ | (reg >> n) & 1 | Get value of bit n |
➡️ Tiếp theo
Khi đọc/ghi hardware registers, compiler có thể "tối ưu" sai cách...
volatile → — Tại sao cần volatile cho hardware access.