The Arduino UNO is an open-source microcontroller board. It is powered by an off-the-shelf ATMega microcontroller from Microchip . The datasheet for this family of microcontrollers can be found here .
This datasheet contains a block diagram of the AVR architecture. Nonetheless, most of these components could be found in many other microcontrollers as well. The image should be familiar to students that took up the Elektronische systemen course at KU Leuven. 😄
Programming the Arduino UNO can be easily done with the Arduino IDE. This user friendly environment is a very nice entry point for new users of microcontrollers. Future engineers, however, should be able to understand what is going on behind the curtain. After all, magic doesn’t exist.
When bare metal programming a microcontroller it is often required to start poking specific bits in a register. A quick background refresh is given first.
Let’s explore the bit manipulations. First we assign the value 1 to an 8-bit type variable.
unsigned char x;
x = 1;
With this line, x holds the number “00000001”. This means the bytes are represented in Little Endian.
Setting the sixth bit, might be a bit cumbersome. First the result of 25 has to be calculated. After googling the result, the programmer can write:
unsigned char x;
x = 32;
More seasoned C programmers might be inclined to use the shift operator : «. This litteraly takes te value 1 (remember: this is represented as 00000001) and shifts this value 5 positions to the left, while inserting 0’s on the right ( 00000001 + 00000 => 00000 + 00100000 => 00100000).
unsigned char x;
x = (1 << 5);
Next to the shift operator, bitwise operators are also heavily used for setting and/or clearing certain bits. The logical functions AND (&), OR(|) and NOT(~) can be used as efficient tools for bit fiddling.
❗ ❗ 🐉 Beware of the dragons 🐉 ❗ ❗.
unsigned char x=0, y=0;
...
x = (1 << 5);
y = y | (1 << 5);
...
x = (1 << 5);
y = (1 << 4);
if(x && y) { printf("YES\n"); } else { printf("NO\n"); }
if(x & y) { printf("YES\n"); } else { printf("NO\n"); }
if(x | y) { printf("YES\n"); } else { printf("NO\n"); }
A frequently used way of communication between hardware and software is through memory-mapped registers. Such a register can be read or written by software at a certain address. This register serves as driver (in the hardware sense) for inputs of a specific hardware component.
When a register is written by software and read by (or driving) hardware, such a register is sometimes called a command register (CR). When a register is written (or driven) by hardware and read by the software, such a register is sometimes referred to with a status register (SR).
Going through the datasheet of the microcontroller on the Arduino many CRs can be found. Section 36 summarises these registers on more than 3 pages. An example of a register that serves both as a CR and as a SR for controlling of the Analog-to-Digital Converter is shown below. As can be learned from the datasheet, the MSB of this register is used to enable or disable the hardware ADC through software instructions.
The register above can be accessed from software on address register 0x7A. When the software writes to this register ALL 8 bits are written. This is important to remember to avoid one of the dragons described above.