AVR Programming Tutorial

This tutorial introduces programming for AVR microcontrollers. It uses the ATmega328p found on Arduino boards, but works with straight AVR C and a bare microcontroller. It covers the basic information you need to get started, whether or not you’ve used Arduino or other microcontrollers previously.

Why would you want to learn AVR programming (instead of, say, using Arduino)? First, it should demystify what happens inside of the Arduino platform (which is really fairly simple). Second, it will give you the flexibility to use other microcontrollers, like the ATtiny series, which are smaller and cheaper than the ATmega328. Third, it will help you take full advantage of the microcontroller’s capabilities, which can be important when writing performance-critical applications.

AVR Programming Tutorial

AVR Toolchain

Download and install:

  • Mac OS X: CrossPack
  • Windows: WinAVR
  • Linux: gcc-avr, avr-libc, avrdude packages


Download the examples: avr-examples.zip


You’ll need the following:

For more information, see our list of materials and parts and our list of prototyping supplies.

Microcontroller (ATmega328p)

We’re using the ATmega328p microcontroller. You’ll want to download the datasheet. Here’s the pinout of the DIP (through-hole) package. The pins are numbered on the inside and labelled on the outside. In parentheses are abbreviations for some of the unique functions of each pin.

Connect your Programmer

To load programmers onto the ATmega328p, you need an in-system programmer (ISP). There are a few of these, each with slight differences.

Using an Arduino as an ISP

Connecting the Arduino and ATmega328

Here, we’re using the Arduino board to program the ATmega328 as well as supply power to it. Notice we only need a single component besides the microcontroller: the 10K resistor (brown, black, orange) pulling the reset line high.

Turning your Arduino into an AVR In-System Programmer

Arduino 0018 (download) comes with a firmware (sketch) that turns your Arduino board into an AVR in-system programmer, allowing you to upload programs onto other microcontrollers. To use it, upload the ArduinoISP example to your Arduino.


If you want to use an AVRISP mkII, you’ll need to provide power separately. Here we use a 9V battery and a voltage regulator to bring this down to five volts.

Insert the 7805 voltage regulator into your breadboard, and add an 0.1 uF capacitor across the output and ground pins.


Attach a battery and use a multimeter to confirm that the regulator is producing ~5V output.


Add the microcontroller to the setup, and make sure that all of the GND and VCC pins are connected properly.

Attach:Microcontroller_added.jpg Δ Δ

Here’s the pinout for the AVR ISP connector. Remember that the red wire in the ribbon cable indicated pin 1, and that this diagram shows the connections as viewed from the back of the connector, i.e. if you’re looking at the holes, this diagram is reversed..

Attach:AVRISP_pinout.png Δ Δ

If you are using the 7805 regulator to power your microcontroller and the AVRISPmkII to program it, your completed setup (including 10k pullup resistor on the reset pin) should look something like this. Notice that the status light on the programmer turns green when everything is connected properly. If is flashes yellow, one or more of your connections may be wrong. If the light turns red, check your power supply.

Attach:Completed_setup.jpg Δ Δ


Verifying the Circuit and Software

To check that your software installation is working and your circuit is correct, you’ll need to run a command in a command prompt (or “terminal”). To open a command prompt, run:

  • Mac OS X: Terminal (in Applications > Utilities)
  • Windows: cmd from the run option in the Start menu
  • Linux: look for something called “terminal” or “xterm”

Once at a command prompt, run the following command:

  • Arduino as ISP: avrdude -p m328p -c stk500v1 -b 19200 -P <PORT>, where <PORT> is:
    • Mac OS X: /dev/tty.usbserial-*
    • Windows: COM3, for example; use the COM port that your Arduino board is on
    • Linux: /dev/ttyUSB0
  • AVRISP mkII: avrdude -p m328p -c avrisp2 -P usb
  • FabISP: avrdude -p m328p -c usbtiny

You should get:

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e950f

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

which means that the avrdude has talked to your ISP, the ISP has talked to the chip, the chip has reported its device signature (here 0x1e950f ) back to the ISP, which passed it on to avrdude, which confirmed that it matched the device signature of the microcontroller you specified in the -c parameter (the ATmega328p).

Possible errors:

avrdude: ser_open(): can't open device "/dev/tty.usbserial-*": No such file or directory
  • Is your Arduino board connected? Is the power LED on?
avrdude: stk500_recv(): programmer is not responding
  • Does the ATmega328p have power? Is it wired correctly? Did you upload the ArduinoISP sketch to your Arduino board?
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.13s

avrdude: Device signature !!0x000000
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.
  • Is the ATmega328 connected to the Arduino correctly?
avrdude: ser_open(): can't open device "\\.\COM3": The system cannot find the file specified.
  • Did you use the right COM port? (Windows)


The program avrdude lets you upload compiled programs (hex files) to your microcontroller. (It’s what the Arduino development environment uses to upload sketches to the Arduino board.) You run it from the command line, with various parameters:

-p part
Specifies the microcontroller (part) you’re programming, e.g. atmega328p

-P port
The port you’re uploading to. If you are using an Arduino board as a programmer, this will be something like /dev/tty.usbserial-A6008b1a on the Mac (or you can just use /dev/tty.usbserial-* to select it automatically). On Windows, it’s COM or similar (you can check in the Device Manager). On Linux, it’s probably /dev/ttyUSB0. If you’re using an AVRISP mkII, it will be usb instead on all three operating systems. For a USBtinyISP or a FabISP, you omit this parameter entirely.

-c protocol
The protocol to use for uploading. If using an Arduino board as a programmer, this should be stk500v1. For an AVRISP mkII, avrisp2. For the FabISP or a USBtinyISP, it’s usbtiny.

-b baud rate
The baud rate to use for uploading. For an Arduino as programmer, use 19200. If using an AVRISP mkII, USBtinyISP, or FabISP, this parameter can be omitted altogether.

AVR Programming Tutorial circuit

Connecting an LED

Now that you’ve got the basic circuit working, let’s hook up an LED so we can see the microcontroller do something. Connect the longer leg of the LED to pin PB0 (pin 14 of the ATmega328p), and the shorter leg goes through a 330Ω (orange orange brown) resistor to ground. If you look carefully at the LED, you’ll notice that one side of it is flat – the leg on that side goes to ground.


For more detail: AVR Programming Tutorial

About The Author

Ibrar Ayyub

I am an experienced technical writer with a Master's degree in computer science from BZU Multan University. I have written for various industries, mainly home automation, and engineering. I have a clear and simple writing style and am skilled in using infographics and diagrams. I am a great researcher and is able to present information in a well-organized and logical manner.

Follow Us:
Scroll to Top