Chapter 6: Bitwise Operators

📚 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

1️⃣ 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

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

3️⃣ 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

}

4️⃣ 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.