#define F_CPU 16000000UL #include <avr/io.h> #include <util/delay.h> int main (void) { DDRB |= _BV(DDB5); while(1) { PORTB ^= _BV(PORTB5); _delay_ms(500); } } /* THE END */
First of all the definition F_CPU gives the CPU clock frequency, which allows _delay_ms() to do the right thing. The _delay_ms() function is an inline function defined in /usr/avr/include/util/delay.h.
The include of avr/io.h references /usr/avr/include/avr/io.h which pulls in one of several files, depending on the value of the -mmcu compiler switch -- in this case /usr/avr/include/avr/iom328p.h, though you never want to reference that file directly.
The macros DDRB, DDB5, PORTB, PORTB5 are special function registers and bits in special function registers.
The _BV macro is simply a bit shift:
#define _BV(bit) (1 << (bit))An expression like _BV(PORTB5) will be converted into a constant mask by the compiler and cause no runtime penalty.
Here is the Makefile. I use "make load" to compile and upload. This demo requires 200 bytes of flash (as compared to 1082 bytes for the blink demo included with the Arduino GUI). Even 200 bytes seems like a lot for something this trivial.
# Makefile to compile demo # for the Arduino UNO all: blink.hex blink.elf: blink.c avr-gcc -mmcu=atmega328p -Wall -Os -o blink.elf blink.c blink.hex: blink.elf avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex # -F says to override/ignore the device signature # -V says to disable verification step. load: blink.hex avrdude -p atmega328p -c arduino -P /dev/ttyACM0 -b 115200 -Uflash:w:blink.hex # THE END
avrdude -F -V -p atmega328p -c stk500v1 -P /dev/ttyACM0 -b 115200 -Uflash:w:blink.hex
Tom's Computer Info / tom@mmto.org