Julian Straub

creations and thoughts

Programming Arduino In C

Posted at — Mar 14, 2020

In this post, I describe how to program an Arduino straight up in C using a simple Makefile.

Arduino microcontroller boards like the Arduino Uno or the Arduino Nano are great for tinkering, since they come with all the necessary circuitry to get started right away. This includes most importantly a USB programming interface and a 16MHz quartz to clock the ATMega microcontrollers at its maximum frequency. The Arduino Uno and Nano both use the ATmega328(P). The “P” stands for pico power—the functionality is the same.

The arduino boards come with an extensive library, code editor and programmer to work with them. I personally dislike using opaque (even if useful) libraries when working on code for micro controllers. The ease of use of, for example a sleep command is great but at the same time I dont know which timer is being used and how so it is hard to know what resources I can work with for the rest of my code if I use that sleep function. Additionally, I think its more fun and a better learning experience to just work straight in C and to reference the ATmega328 datasheet for which registers to set how to achieve a desired effect like a timer interrupt at a certain frequency.

I put together a very simple C example code with Makefile that shows how to write code in C and flash it onto an Arduino Nano. First create a main.c file with the following content:

// main.c
#include <avr/io.h>
#include <util/delay.h>

int main(void) {
  // set LED pin PB5 to output
  DDRB |= (1<<PB5);

  while(true) {
    // toggle the LED pin PB5 and hence the LED
    PORTB ^= (1<<PB5);
    // use build in delay function to delay for 100ms
    _delay_ms(100);
  }
}

And the Makefile:

# Makefile
MCU=atmega328p
F_CPU=16000000
CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS=-std=c99 -Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I.
TARGET=main
SRCS=main.c
SERIAL=-P /dev/ttyUSB0 -b 57600

all:
	${CC} ${CFLAGS} -o ${TARGET}.bin ${SRCS}
	${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.bin ${TARGET}.hex

flash:
	avrdude -p ${MCU} -c arduino -U flash:w:${TARGET}.hex:i ${SERIAL} 

clean:
	rm -f *.bin *.hex

In the same directory as those two files you can now compile and flash the arduino after connecting it using:

make && make flash

Make sure you have avrdude, gcc-avr and avr-libc installed:

sudo apt-get install gcc-avr avr-libc avrdude