Programming an AVR with Arduino

 •  Tech.

The Arduino is a great platform for rapid prototyping because it’s so easy to use, well supported, and has a huge online community. However, sometimes you might want to make a smaller, cheaper, and more minimalistic circuit that can be put into permanent projects. Or, maybe you are wondering how the Arduino works. In any case, you’ll just want the brain of the Arduino: the AVR microcontroller. This chip contains the program that runs the Arduino.

Once you have just the AVR, you might be wondering how to program it. Since you no longer have a USB connection, how do you upload code? It turns out that the Arduino can program AVR chips! Let’s get started.

First, you’ll need to make sure you have a couple things:

Parts list

Arduino Duemilanove/Uno/Mega & USB cable
AVR microcontroller (suggestions: ATTiny85, ATTiny2313, ATMega328)
6 wires and breadboard
220Ω resistor (red red brown)
10uF capacitor
LED

Great, now that you have everything you need, here’s the video tutorial.


Introduction



In this video tutorial, I’m going to show you how to program an AVR microcontroller with the Arduino.
This allows you to expriment with individual AVR chips, without the cost or hassle of buying an AVR programmer.
Additionally, by learning how to program an AVR chip, you can understand how an Arduino works while making your own custom embedded system as small and inexpensive as possible.
I’ll show you the process with an ATtiny2313 AVR (datasheet) and the Arduino Duemilanove (info page).
If you’re using a different AVR chip, the pin connections will be slightly different.
Since we’ll need the datasheet for reference, you’ll probably want to download it now.
First, go to atmel.com, click in the search box, and type the name of your AVR.
Then, on the search results page, click the Datasheet link.
For this tutorial, you’ll need:
An Arduino Duemilanove, Uno, or Mega;
An AVR microcontroller;
6 jumper wires and a breadboard;
A 220 ohm resistor;
A 10 microfarad capacitor;
And a LED

Step 1



The first step is the upload the ArduinoISP sketch to your Arduino to make it a programmer.
It’s located under File >> Examples >> ArduinoISP.
Ensure that the Board and Serial Port configuration is correct (under Tools), and then press Upload.

Step 2



In step two, we’ll physically connect the AVR to the Arduino.
Find the pinout for your AVR in the datasheet.
Orient the chip correctly by looking for the top semicircular indent.
Most chips also or instead have a small dot in the corner, indicating pin 1.
In Circuit Serial Programming requires 6 connections:
1. First, we need VCC, which is the positive supply or voltage. In this case, it’s on pin 20.
2. GND is the negative supply, or ground, on pin 10.
Then we have 4 data connections:
3. First we find the RESET connection on pin 1.
4. Then, the UCSK (Serial Clock) on pin 19
5. Then, MISO (Master In Serial Out data) on pin 18
6. And finally, MOSI (Master Out Serial In data) on pin 17
Now let’s connect the AVR to the Arduino.
Start with an Arduino, a breadboard, and an AVR chip of your choice.
First, connect VCC (the positive voltage supply) into the 5V pin on the Arduino.
Next, connect the GND pin on the AVR to the GND pin on the Arduino.
Now connect RESET to pin 10, MOSI to pin 11, MISO to pin 12, and SCK to pin 13.
The code in this tutorial will use a LED connected to pin PD6, through a resistor to GND.
One more gotcha: you need to disable the auto-reset of the Arduino by connecting a 10uF capacitor from RESET to GND.
Note that this will most likely need an electrolytic capacitor, which has polarity.
Make sure to connect the longer lead (the plus side) to RESET
and the shorter lead to GND.

Step 3



Step three is to install the AVR toolchain, which makes it possible to compile and upload programs to the AVR.
On Windows, download and install WinAVR. Make sure that the “Install Files” and “Add Directories to PATH” boxes are checked.
On Mac, you’ll want to install CrossPack tools from Objective Development. Download and open the package installer and click next until the installation completes.
On Linux, follow Ladyada’s UNIX setup guide.

Step 4



Step four is configuring your Makefile, which sets the settings for the compiler and programmer.
Get the template, and change the settings at the top to reflect your setup.

The DEVICE line should be set to the name of the AVR you’re programming.
CLOCK is the speed (in Hertz) that the AVR is running at. In this case I’m using the internal 8MHz clock, so I wrote 8 million.
The PROGRAMMER line specifies the settings for the programming step. The code shown here is set to auto-detect the Arduino on Mac or Linux systems. On Windows, you’ll have to set it manually to something like COM4. (You can find the COM number of your Arduino in the Arduino program.)
The OBJECTS line specifies what C files should be compiled. For now, main.o is fine.
The FUSES line sets 3 bytes of configuration memory for the AVR (things like clock source, reset and programming disable, etc.) You can easily brick your AVR with these settings, so make sure you get them right. Luckily, there’s an easy way to configure fuses.
You can find the recommended default settings for your particular AVR by using an online fuse calculator.
If your circuit looks like the one in this tutorial, you can go ahead and use the defaults.
Copy and paste the generated fuse bytes to your Makefile’s FUSES line.


Step 5



In step five, we’ll write the main program for our AVR.
This program will blink the LED I connected to PD6.
You can any I/O pin you wish, but change the Port Name and Pin Number accordingly.
At the top, we’ll have to define the CPU frequency in order to properly calculate delays.
I’m using the internal 8MHz clock, but the default configuration fuses actually divide the clock by 8 internally.
On most AVRs, this is enabled by default.
So, the actual frequency is 1MHz, which I wrote here.
we include the AVR I/O header library to interface with the I/O pins.
After that we include the delay header library.
In the main function, we first make port D pin 6 an output.
This line uses the Port D Direction Register (DDRD) to set our port D inputs/outputs.
Next, we have a vertical bar and equals sign. This is an OR bitmask.
Then, we have the assignment. Here we make pin D6 HIGH, or 1, to mean output.
If you prefer, you can instead use _BV() to make this value a 1.
End the line with a semicolon.
The for(;;) line creates our program’s infinite loop. In it, we toggle the value of pin D6 using an XOR bitmask on the PORTD Data Register.
This makes pin D6 output a HIGH value of about 5 volts.
Then, we delay for a second.
Then next the loop runs, the value of pin D6 will toggle off to zero volts and delay again.
The AVR will continue toggling this pin forever.
Finally, we end the loop and return 0 to tell that the program executed successfully.
Note that all registers on the chip are on the datasheet for reference.

Step 6



Finally, step six: uploading the code to your AVR.
Open terminal and use the cd command to change directories to the folder with your Makefile and main.c.
Then, simply type “make flash” to compile your main.c into a hex file and upload it with avrdude.
And before you know it, the LED is blinking!

Conclusion



Congratulations! Now that you can upload code to your AVR, try experimenting with different programs.
I have more resources and code on my website: http://holachek.com/avr.
Thanks for listening!

Code

Makefile: https://gist.github.com/3304890
main.c: https://gist.github.com/3304608

Links

Toolchain install:
Windows http://sourceforge.net/projects/winavr/files/WinAVR/
Mac http://obdev.at/products/crosspack
Linux http://ladyada.net/learn/avr/setup-unix.html

Fuse calculator: http://engbedded.com/fusecalc/

More Resources

Video background music track Dopart by blue On blue

  • Jeffthermite

    Im trying to program a Atmega8 with Arduino mega, but when i do the “make flash” command, it gives me this:
    makefile:34: *** missing separator. Stop.
    Whats wrong?

    • http://michael.holachek.com/ Michael Holachek

      “missing separator” occurs because there’s something wrong with the whitespace in the Makefile. Ensure your tabs are setup properly, for example, on line 33-34:

      .c.o:
      ______ $(COMPILE) -c $< -o $@
      ^this must be a tab, not spaces

  • McHa

    Hi Mike,
    nice tutorial thank you!

  • Jeffthermite

    It seems like i got the makefile working, but now it gives me this:
    avr-gcc -Wall -Os -DF_CPU=8000000 -mmcu=atmega8 -c main.c -o main.o
    main.c:1:1: warning: “F_CPU” redefined
    : warning: this is the location of the previous definition
    main.c:6: error: stray ’342′ in program
    main.c:6: error: stray ’200′ in program
    main.c:6: error: stray ’250′ in program
    main.c: In function ‘main’:
    main.c:9: error: stray ’342′ in program
    main.c:9: error: stray ’200′ in program
    main.c:9: error: stray ’250′ in program
    make: *** [main.o] Error 1

  • louis caruso

    sorry I have a problem when i writ “make flash” terminal mac said :

    Mac-mini-de-Administrateur:projetAVR admin$ make flash

    make: *** No rule to make target `flash’. Stop.

    can you help me !! please

    • http://michael.holachek.com/ Michael Holachek

      That error message means the make command cannot complete the flash routine (line 47-48) in the Makefile: $(AVRDUDE) -U flash:w:main.hex:i

      Check to make sure CrossPack tools is installed by typing avrdude in Terminal. It should print out a list of possible avrdude options.

      Also, double check your main.c file is in the same directory as the Makefile.

      • louis

        This two thinks are all right and when I type avrdude in terminal it print out avrdude options
        I don’t no what is not correct ?

        • http://michael.holachek.com/ Michael Holachek

          Hrmm, there must be something wrong with your Makefile or the avr-gcc binary. Try asking the code ninjas at Stack Overflow or searching their past discussions.

          • louis

            That is not correct (the problem was the name of the file. Thank you) but now I have an other problem the Terminal said:

            avr-gcc -Wall -Os -DF_CPU=8000000 -mmcu=attiny84 -c main.c -o main.o

            main.c:1:1: warning: “F_CPU” redefined

            :1:1: warning: this is the location of the previous definition

            main.c: In function ‘main’:

            main.c:8: error: ‘DDRD’ undeclared (first use in this function)

            main.c:8: error: (Each undeclared identifier is reported only once

            main.c:8: error: for each function it appears in.)

            main.c:12: error: ‘PORTD’ undeclared (first use in this function)

            main.c:17:2: warning: no newline at end of file

            make: *** [main.o] Error 1

          • louis

            yet I have include avr/io

          • http://michael.holachek.com/ Michael Holachek

            Check your port names. Your code doesn’t work because there is no port D on the ATtiny84, only port A and B. (Reference the ATtiny84 datasheet.)

          • louis

            That is now correct but now the problem is :

            avrdude -c arduino -P /dev/tty.usbmodemfd121 -b 19200 -p attiny84 -U flash:w:main.hex:i

            avrdude: Can’t find programmer id “arduino”

            yet I have upload Arduino-as-isp
            (thank you for your help)

          • http://michael.holachek.com/ Michael Holachek

            This error occurs because you don’t have a recent version of avrdude. (Old versions don’t have the arduino programmer type.) Install the latest version of CrossPack tools.

          • louis caruso

            I hope this is my last question, now when I write “make flash” everything is correct but it say after the writing :

            Writing | | 0% 0.00savrdude: stk500_recv(): programmer is not responding

            make: *** [flash] Error 1

            sorry for all this question !

          • http://michael.holachek.com/ Michael Holachek

            So close! avrdude can’t communicate with your programmer (i.e., Arduino). What version of ArduinoISP did you upload to Arduino? Did you connect everything properly, including the 10µF reset-disabling capacitor?

          • louis

            I use the latest version of Avrduino-as-ISP and I have connect all propely and also the capacitor

          • louis

            this is all my error :

            Reading | ################################################## | 100% 0.12s

            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: please define PAGEL and BS2 signals in the configuration file for part ATtiny85

            avrdude: reading input file “main.hex”

            avrdude: writing flash (110 bytes):

            Writing | | 0% 0.00savrdude: stk500_recv(): programmer is not responding

            make: *** [flash] Error 1

            I hope you can help me.

          • http://michael.holachek.com/ Michael Holachek

            I’ve never seen the stk500_recv() error during writing flash memory…Maybe try pressing the reset button just before it uploads? Did you search google for solutions?

          • louis

            I have test the reset button, and with google I have find nothing that can help me

  • http://www.facebook.com/olexiy Olexiy Logvinov

    Finally I managed to burn the test code into attiny2313a chip, but instead of 1 second delays I got 8 seconds. I guess this is because the internal divider is used. Though in your tutorial you use the internal divider too, don’t you?
    Well, I changed the first line in main.c to look like the following

    #define F_CPU 1000000 # 1MHz instead of 8MHz

    when I tried to ‘make flash’ again I got the error. Even when you returned back to origina main.c with 8000000 Hz, I got the same error:

    D:electronicsnikonmi>make flash
    avr-gcc -Wall -Os -DF_CPU=8000000 -mmcu=attiny2313 -F -c main.c -o main.o
    cc1.exe: error: avr25: No such file or directory
    make: *** [main.o] Error 1

    Do I have to use some different commands when reprogramming the chip?

    • http://michael.holachek.com/ Michael Holachek

      Hrmm.. that’s weird. It doesn’t seem like that error is a problem with any redefinition of the CPU clock speed; instead it looks like you have a compiling/linking problem with the avr25 library. Somehow it can’t find the avr25 directory with the current path. (Did you make sure to check the “Set PATH” checkbox when installing WinAVR?)

      Get the verbose compiler output by editing the Makefile on line 28. Simply add a -v (dash v), separated by spaces, after avr-gcc. So, line 28 should look something like like:

      COMPILE = avr-gcc -v -Wall -Os …

      Then make flash again and see if it turns up any extra debug info.

      If that doesn’t work, I’d suggest reinstalling the WinAVR toolchain and making sure that your PATH environment variable includes the folder location to which you install.

      • http://www.facebook.com/olexiy Olexiy Logvinov

        Thanks for your answer, Michael!

        It turns out that the reason was in that damned “-F” key that was added in Makefile to make avrdude think that attiny2313a is actually an attiny2313. It is strange but the “-F” key has to be removed after the first programming of the chip.
        DEVICE = attiny2313 -F

        OMG! The solution was so simple, but I spent hours, if not days, searching for a possible.bug.

  • Олег

    Hi!
    Thanks for your tutorial. I tried to follow but stumbled over error as follows.

    oleg-fadeevs-macbook-pro-3:firmware oleg$ make flash
    avrdude -c arduino -P /dev/tty.usb* -b 19200 -p atmega8535 -U flash:w:main.hex:i
    avrdude: No AVR part has been specified, use “-p Part”

    (I leaved this part as in your tutorial: -P /dev/tty.usb* because you stressed this would automatically define proper data)
    Then tried another way:

    make flash
    avrdude -c arduino -P /dev/tty.usbmodem621 -b 19200 -p atmega8535 -U flash:w:main.hex:i
    avrdude: stk500_recv(): programmer is not responding

    All connections in OK, reset button pressed all the way/
    What may be a reason? Help please.