Skip to content
Sign in
Theme

C for microcontrollers: bits and registers

Set, clear, toggle and test single bits, because that is how every peripheral is configured.

Read this first

Everything a peripheral does is controlled by registers: memory locations where each bit means something. Bit 5 of one register might enable a pin, bit 3 of another might say a byte has arrived. So embedded C is full of code that changes one bit and leaves the others alone. There are exactly four idioms, and they are worth learning by heart.

First, make a mask with a 1 in the position you want: (1u << n). The u makes the constant unsigned, which avoids surprises when n is 31. Set a bit with OR: reg |= (1u << 3). Clear it with AND NOT: reg &= ~(1u << 3). Toggle it with XOR: reg ^= (1u << 3). Test it with AND: if (reg & (1u << 3)) means bit 3 is set.

The compound forms |=, &= and ^= read the register, change one bit, and write it back, so the other bits stay as they were. Plain assignment (reg = 0x08) would overwrite everything else, which is a common bug.

Hex notation is the natural way to see bits. Each hex digit is four bits: 0x0F is 0000 1111, 0x28 is 0010 1000, so in 0x28 bits 5 and 3 are set. Write the number out in binary when unsure. It takes ten seconds and saves an hour.

Some registers pack a small number into a few bits, say a 3-bit field in bits 4 to 6. To read it, shift the field down to bit 0 and then mask off everything above it: (r >> 4) & 0x7. To write it, clear the field first and then OR the new value shifted into place.

To remember

  • Mask: (1u << n). Set: |=. Clear: &= ~. Toggle: ^=. Test: & inside an if.
  • The compound operators keep the other bits. Plain = overwrites the whole register.
  • One hex digit is four bits. 0x28 is 0010 1000.
  • Read a field with (r >> shift) & mask.

Check what you read

4 questions from the question bank on the ideas above. Each one comes with an explanation after you answer.

Sign in to answer the questions. Your answers count towards your level.

Sign in

The lesson text and the project are free to read without an account.

Build this

Binary counter on LEDs

You need

  • Your board and breadboard.
  • Four LEDs with four resistors, on four pins.

Steps

  1. Write four small functions or macros: bit_set, bit_clear, bit_toggle and bit_test, each taking a value and a bit number. Test them on the computer or by printing before touching hardware.
  2. Keep one uint8_t counter. Once a second, add one, and show its low four bits on the four LEDs using bit_test.
  3. Open the datasheet or reference manual of your chip and find the register that sets the output level of the port your LEDs are on. Write one LED on and off through that register directly, without the library call.

Done when

The LEDs count from 0000 to 1111 and wrap, and at least one LED is driven by a register write you wrote yourself.