Memory is made of registers. Those are groups of bits that hold a certain value. Width of the register depends on the architecture of the MCU. Atmega's used in the Arduino are 8 bit MCUs while STM32 series are 32 bit MCUs. Why is width important? For one, 8 bit unsigned integer has a range od 0-255. Anything larger than that has to span several registers. 32 bit unsigned int is much larger. This is an example of STM32F103 Timer register:
TIMx_CR1 is register name, and to the right there are bits from 0 to 31, each representing certain function. By setting those bits to 0 or 1 we can enable or disable certain functions and make commands like enable/disable Timer.
In C language, we use prefix 0x to declare that our variable is hexadecimal number, 0b to declare it as a binary number. So, we can write a variable in multiple ways:
int a= 10;
int b= 0x6;
int c= 0b101;
Basic bitwise operations on registers are: OR, AND, NOT, XOR etc... We can use those operations to modify registers or variables. Let's say we have a register of value 0b10110011. We want to clear bit on position 5. Positions:
bit 7 6 5 4 3 2 1 0 value 1 0 1 1 0 0 1 1
Code example:
register=0b10110011; register&=~(1<<5); register = 0b10010011;
We changed "1" on position 5 to "0". How does it work?
1<<5 = 0b00100000
~(1<<5) = 0b11011111 (~ means negate bits (invert bits))
register&=~(1<<5)
=
register = register & ~(1<<5)
=
register = register & 0b11011111
1 0 1 1 0 0 1 1 &
1 1 0 1 1 1 1 1
= = = = = = = =
1 0 0 1 1 1 1 1
We do similar thing for OR, XOR operators etc... Details can be found on wikipedia. In short
Setting a bit in register: register|=(1<<Position); Clearing a bit in register: register&=~(1<<Position); Toggling a bit in register: register^=(1<<Position);
These are the basis for programming microcontrollers in C. Now that we know the basics we can start with the fun stuff.
Copyright 2024, Mario Matovina
Send me an e-mail