Explaining Pure C Blink Example

Posted on March 12, 2016 by Richard Goulter
Tags: , ,

I’ve been playing around with an Arduino Uno this past week.

I came across this post from balau82: it gives a basic “blink” example program in C, and a high-level overview of how to come up with such a program.
The high-level overview wasn’t obvious for me, so I’d complement that blogpost with this, to explain in further detail.

e.g. When the post says:

from the Arduino Uno schematics we can find out where the pins are connected, for example we can find that the LED is connected to the PB5 pin of the Atmega328p chip

These are the pertinent details of the schematic:


Looking at snippets from the code:

int main (void) {
 DDRB |= _BV(DDB5); /* set Port B bit-5 to output */

 while(1) {
  PORTB |= _BV(PORTB5); /* turn on LED */
  ....
 }
}

This left a novice like me with questions:
Where do these constants come from? What’s DDRB? How does DDB5 refer to PB5? Why PORTB = ... to change the LED? What’s the difference between DDB5 and PORTB5?
(At least I understood the magicVar |= 1 << 5 & magicVar &= ~(1 << 5) bitmasking. – my C-Worksheet is useful for playing around with this, also, btw).


The commands to compile and upload it I take on faith as “just work”. (Or, rather, I didn’t need to mess with them).

Here’s a Makefile adapted from these commands, which will probably be useful. (make upload will build & upload the program to an Arduino).


I wanted to translate the Spaceship Interface (Project 02 of the book which comes with the Arduino Starter Kit) to C, also.
The only difference from the Blink example is that the Spaceship Interface example reads input from a pin.

Following the aforementioned tutorial, the switch is in (Arduino) pin 2, and the LEDs in pins 3, 4, 5.
From the schematic, this corresponds to PD2 .. PD5. (%s/B/D/ is evident, even without the above understanding).

Reading from a pin should also be ‘easy’ from the above understanding.[4] – And, again, the avr/sfr_defs.h documentation mentions that PORTx = 0x33; unsigned char i = PINx will magically get translated to the correct instructions.

I was able to come up with this. And it worked and I was so happy.

Then I translated the example to the Atom EDSL. Read about the fun in my next blog post.


[1] Reading is useful. But, on the other hand, the datasheet is like 600 pages long.

[2] Is it fair to call this ‘hard’ (for non-engineers), in the sense that all that isn’t obvious by looking at the C code & blog? OTOH, math is hard, and that’s kindof a problem with the user, not the content.

[3] But writing lots of stupid questions is still useful for clarifying to yourself what you don’t know! – Indeed, asking questions in a programming journal is valuable even if you never get back to answering them, I’d say.

[4] Or from getting lucky by finding the example in Section 14 reading from PINB.


Newer post Older post