We use register bit manipulation to control hardware by turning specific bits on or off. This helps us manage devices like LEDs, sensors, or motors directly.
Register bit manipulation patterns in Embedded C
/* Define a register as a variable */ volatile unsigned int REGISTER; /* Set a bit (turn bit ON) */ REGISTER |= (1U << BIT_POSITION); /* Clear a bit (turn bit OFF) */ REGISTER &= ~(1U << BIT_POSITION); /* Toggle a bit (flip bit) */ REGISTER ^= (1U << BIT_POSITION); /* Check a bit (test if bit is ON) */ if (REGISTER & (1U << BIT_POSITION)) { // bit is ON } else { // bit is OFF }
Use volatile keyword for hardware registers to prevent compiler optimizations.
Bits are counted from 0 (least significant bit) upwards.
volatile unsigned int CONTROL_REGISTER = 0x00; // Set bit 3 CONTROL_REGISTER |= (1U << 3);
volatile unsigned int STATUS_REGISTER = 0xFF; // Clear bit 7 STATUS_REGISTER &= ~(1U << 7);
volatile unsigned int FLAG_REGISTER = 0x0F; // Toggle bit 0 FLAG_REGISTER ^= (1U << 0);
volatile unsigned int INPUT_REGISTER = 0x10; // Check if bit 4 is ON if (INPUT_REGISTER & (1U << 4)) { // bit 4 is ON } else { // bit 4 is OFF }
This program shows how to set, clear, toggle, and check bits in a simulated 8-bit register. It prints the register value after each operation and checks if a specific bit is ON or OFF.
#include <stdio.h> #include <stdint.h> int main() { volatile uint8_t REGISTER = 0x00; // 8-bit register initialized to 0 printf("Initial REGISTER value: 0x%02X\n", REGISTER); // Set bit 2 REGISTER |= (1U << 2); printf("After setting bit 2: 0x%02X\n", REGISTER); // Clear bit 2 REGISTER &= ~(1U << 2); printf("After clearing bit 2: 0x%02X\n", REGISTER); // Toggle bit 1 REGISTER ^= (1U << 1); printf("After toggling bit 1: 0x%02X\n", REGISTER); // Toggle bit 1 again REGISTER ^= (1U << 1); printf("After toggling bit 1 again: 0x%02X\n", REGISTER); // Check bit 0 if (REGISTER & (1U << 0)) { printf("Bit 0 is ON\n"); } else { printf("Bit 0 is OFF\n"); } // Set bit 0 REGISTER |= (1U << 0); printf("After setting bit 0: 0x%02X\n", REGISTER); // Check bit 0 again if (REGISTER & (1U << 0)) { printf("Bit 0 is ON\n"); } else { printf("Bit 0 is OFF\n"); } return 0; }
Time complexity for bit manipulation operations is O(1) because they use simple bitwise operators.
Space complexity is O(1) as no extra memory is needed beyond the register variable.
A common mistake is forgetting to use parentheses around bit shifts, which can cause wrong results.
Use bit manipulation when you need fast, low-level control of hardware or flags. For complex data, consider other data structures.
Register bit manipulation lets you control hardware by changing specific bits.
Use bitwise operators: OR (|) to set, AND (&) with NOT (~) to clear, XOR (^) to toggle, and AND (&) to check bits.
Always count bits from 0 starting at the least significant bit.
Practice
Example: Set bit 3 in register REGSolution
Step 1: Understand setting a bit
Setting a bit means making that bit 1 without changing others.Step 2: Use bitwise OR
Bitwise OR with 1 at the target bit sets it to 1, others stay same.Final Answer:
Bitwise OR (|) -> Option AQuick Check:
Set bit = OR [OK]
- Using AND (&) to set bits (it clears bits)
- Using XOR (^) which toggles bits
- Using NOT (~) which inverts all bits
REG?Solution
Step 1: Understand clearing a bit
Clearing means setting the bit to 0 without changing others.Step 2: Use AND with NOT mask
AND with NOT of (1 shifted to bit 2) clears bit 2.Final Answer:
REG = REG & ~(1 << 2); -> Option DQuick Check:
Clear bit = AND with NOT mask [OK]
- Using OR (|) which sets bits
- Using XOR (^) which toggles bits
- Using shift (<<) alone which moves bits
REG = 0b00001100;, what is the value of REG after executing REG ^= (1 << 3);?Solution
Step 1: Understand XOR toggling
XOR toggles the bit: if 1 becomes 0, if 0 becomes 1.Step 2: Toggle bit 3 of REG
Bit 3 is currently 1 (0b00001100). Toggling it changes it to 0, so REG becomes 0b00000100.Final Answer:
0b00000100 -> Option BQuick Check:
XOR toggles bit 3 from 1 to 0 [OK]
- Thinking XOR sets bit instead of toggling
- Confusing bit positions (count from 0)
- Not converting binary correctly
REG is set?if (REG & (1 << 4) == 1) {
// bit 4 is set
}Solution
Step 1: Understand bit check expression
REG & (1 << 4) returns non-zero if bit 4 is set, zero if not.Step 2: Fix comparison
Comparing to 1 is wrong because bit 4 corresponds to value 16, not 1. Should check if result != 0.Final Answer:
The comparison '== 1' is incorrect; it should check if result is non-zero. -> Option AQuick Check:
Check bits by testing non-zero result [OK]
- Comparing bit check result to 1 instead of non-zero
- Using shift right (>>) instead of left (<<)
- Using OR (|) to check bits which sets bits
REG simultaneously. Which code correctly does this?Solution
Step 1: Understand toggling multiple bits
Toggling means flipping bits. XOR (^) with mask flips bits where mask has 1.Step 2: Create mask for bits 0, 2, and 5
Mask is (1<<0) | (1<<2) | (1<<5) which sets bits 0, 2, and 5 to 1.Step 3: Apply XOR with mask
REG ^= mask flips those bits simultaneously.Final Answer:
REG ^= (1 << 0) | (1 << 2) | (1 << 5); -> Option CQuick Check:
Toggle bits with XOR and combined mask [OK]
- Using AND with NOT mask which clears bits
- Using AND (&) instead of OR (|) to combine masks
- Using wrong bit positions in mask
Ready to prove it?
Pass the test and this pattern moves unknown
