π§ Bitwise Operations in C for Microcontroller Programming
Bitwise operations are essential for low-level programming, especially when working with microcontrollers and GPIO. They allow precise control over individual bits in registers.
π― Learning Objectives
By the end of this lesson, students should be able to:
- Itentify the Bitwise Operators and how they are used in the C language
- Understand how to SET, CLEAR, MASK, and TOGGLE a bit
- Successfully use bit-shifting for efficient code statements
π§ Core Bitwise Operators
| Operator | Symbol | Description | Example |
|---|---|---|---|
| AND | & |
Sets each bit to 1 if both bits are 1 | 5 & 3 = 1 |
| OR | | |
Sets each bit to 1 if at least one bit is 1 | 5 | 3 = 7 |
| XOR | ^ |
Sets each bit to 1 if only one bit is 1 | 5 ^ 3 = 6 |
| NOT | ~ |
Inverts all bits | ~5 = -6 |
| Left Shift | << |
Shifts bits left, filling with 0s | 4 << 1 = 8 |
| Right Shift | >> |
Shifts bits right, discarding bits | 4 >> 1 = 2 |
π§ͺ Bit Manipulation Techniques
- These are commonly used to control GPIO pins or manage flags.
- Letβs pretend we want to control and monitor bits in an 8-bit register called GPIOA.
Objectives
- We want to be able to write one specific bit as β0β or β1ββ without modifying the rest
- We want to be able to read one specific bit to know if is either β1β or β0β
GPIOA
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Terminology
- Writing a β1β to a specific bit leaving the rest intact is called SET
- Writing a β0β to a specific bit leaving the rest intact is called CLEAR
-
Checking the status of a bit to know if itgβs either β1β or β0β is called BIT MASKING
- Assuming we have previously defined this mask:
const uint8_t BIT5 = 0b00100000; // and 8-bit mask that has a "1" only in b5
π§ͺ Relevant Manipulation Operations
β Set a Bit (write a 1)
Turn ON a specific bit using OR:
GPIOA |= BIT5; // Set BIT5, GPIOA = GPIOA | BIT5
β Clear a Bit (write a 0)
Turn OFF a specific bit using AND with NOT
GPIOA &= ~BIT5; // Clear BIT5, GPIOA = GPIOA & ~BIT5
π Toggle a Bit (chanmge 1 to 0 and vice-versa)
Flip the state of a bit using XOR:
GPIOA ^= BIT5; // Toggle BIT5, GPIOA = GPIOA ^ BIT5
π Mask a Bit (test a bit)
Check if a bit is HIGH using AND:
if (GPIOA & BIT5)
{//BIT5 is HIGH (1)
//Do something
}
else
{//BIT5 is LOW (0)
//Do something
}
π Shift Operations
Left Shift (<<)
uint8_t mask = 1 << 5; // Creates 0b00100000
//Example
const uint8_t FLAG_READY (1 << 0) //0b00000001
const uint8_t FLAG_ERROR (1 << 1) //0b00000010
uint8_t status = 0; //variable to check status
status |= FLAG_READY; //SET FLAG_READY bit
status &= ~FLAG_ERROR; //CLEAR FLAG_ERROR bit
if (status & FLAG_READY)
{//Flag ready is SET
// Proceed with operation
}
π―Practical Activity
- Using the virtual console on Segger create a simple program that reads a positive integer from the console and saves it into a 16-bit unsigned int variable
- Using bit-tmasking and bit-shifting operations display the number in binary (16-bit) on the debug console
- Remember to read a number from the virtual console you need to use βscanfβ and to print it βprintfβ with the proper string formatter.