CrossPack Tutorial

Programming Mictrocontroller Without Arduino

Programming with the Arduino IDE and utilizing its included libraries is nice, but oftentimes Arduino abstracts away crucial details that have to be accounted for in more complicated projects. I thought it would be a good opportunity to move closer to the hardware level and to program the AVR microcontroller in C for my upcoming project, using command line utilities neatly packaged by CrossPack.

As a test, I wrote a simple script targeted for an ATTiny85 to output a 50 Hz square wave on one of its pins using the template from running avr-project Demo:

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

int main(void)  
{
    DDRB = 0x01;    //Set PB0 as output
    for(;;){
        PORTB ^= 0x01;  //Toggle PB0 
        _delay_ms(10);
    }
    return 0;   /* never reached */
}

The makefile configuration that came with CrossPack's demo template worked extremely well in simplifying the compile and flashing process, the changes I had to make were the following lines (note that your programmer may appear differently in your file system than mine, but it should be along the lines of /dev/tty.* for OSX):

DEVICE     = attiny85  
CLOCK      = 8000000  
PROGRAMMER = -c stk500v1 -b 19200 -P /dev/tty.usbmodem1411 #Settings for ArduinoISP  
OBJECTS    = main.o  
FUSES      = -U hfuse:w:0xdf:m -U lfuse:w:0xe2:m    #default fuses for ATtiny85 without clock division  

Hints:

  • use avrdude -p ? to list the supported AVR devices.
  • find the Arduino ISP using ls /dev/tty.*
  • you MUST use -c stk500v1 and provide the baud rate of 19200 if using Arduino as programmer
  • fuse calcululator

To program an AVR chip, you must have a programmer. A popular choice is something like the AVR pocket programmer, but if you're like me and don't want to wait the shipping, an Arduino Uno can actually be programmed to be a programmer that you likely have around the shop! So, the first order of business is to flash the Arduino with the ArduinoISP (ISP stands for in-system programmer) sketch from File->Examples. Then, we connect the Uno like so to the Tiny:

The command make flash produced the following:

avrdude -c stk500v1 -b 19200 -P /dev/tty.usbmodem1411 -p attiny85 -U flash:w:main.hex:i

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e930b  
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed  
         To disable this feature, specify the -D option.
avrdude: erasing chip  
avrdude: reading input file "main.hex"  
avrdude: writing flash (78 bytes):

Writing | ################################################## | 100% 0.18s

avrdude: 78 bytes of flash written  
avrdude: verifying flash memory against main.hex:  
avrdude: load data flash data from input file main.hex:  
avrdude: input file main.hex contains 78 bytes  
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.09s

avrdude: verifying ...  
avrdude: 78 bytes of flash verified

avrdude: safemode: Fuses OK (H:FF, E:DF, L:E2)

avrdude done.  Thank you.  

Upon checking the fuse, it turns out that the version of avrdude that came in CrossPack is the version that had a label typo when displaying the fuse values at the end, so it should really read: Fuses OK (E:FF, H:DF, L:E2).

The code above used up a total of 164 bytes of flash, whereas the same code (functionally) written using Arduino API:

void setup() {  
  pinMode(8,OUTPUT);
}

void loop() {  
  digitalWrite(8,~digitalRead(8));
  delay(10);
}

resulted in a 932 bytes of flash usage. That's a substantial difference especially when we're working with devices equipped with only tens of Kbytes of flash.

So be brave, go out there and program your AVRs with the command line utilities and free yourself from the chains of Arduino.