Tech »

ATmega16/32 Programmer

The Atmel ATmega series of microcontrollers are very popular due to the large number of peripherals inbuilt in them. They have features such as internal PWM channels, 10-bit A/D converters, UART/USART and much more, which are useful for a lot of applications and external hardware is reduced as these are built-in.

The programmer shown below is a SPI based in-circuit programmer, meaning that you can program your microcontroller while it is placed in your application circuit, although you'll have to remove the external connections from the pins used by the programmer (MOSI, MISO, SCK, RESET) while programming. The interface is called "BSD", which is pretty standard, so you won't have much problem with software support.


Note: Do not skip any resistor. They are for the protection of your Parallel Port.

You can skip the crystal and the two capacitors, since the AVR comes with its built-in oscillator, which is turned on by default. It has 1 MHz frequency and is good enough for general purposes, but is not good for precise timing applications like serial communication. For such applications, you need put the external oscillator and write the proper fuse bits to enable it.

Programmer Schematic


After making the programmer, you would need some software to first compile the C code you write to a hex file and then to write this hex file onto the microcontroller.

One good part about using AVR devices is that GCC has support for AVR. GCC is available for both Linux and Windows, so you won't have problems of writing codes in different operating systems.


You will need the following packages:

  • avr-gcc
  • avr-binutils
  • avr-libc
  • avrdude (the program which actually writes data on the microcontroller)

You will need a Makefile to simplify the generation of the hex file to be burnt onto the microcontroller. Take it from here. The Makefile has been taken from and changed a bit for the bsd programmer and the ATmega16 microcontroller. While using it, put your source filename after PRJSRC (line 79). If you are using ATmega32, then you would also need to change the MCU option (line 68) to atmega32.

After making the changes necessary, save the Makefile in the same directory as your source file. Then give the following commands in order:

$ make hex
$ make install

The first command generates the hex file which would be burnt onto the microcontroller. The second one actually calls avrdude which writes the hex file onto the microcontroller. If there is some problem of permission while writing to the parallel port, then you will have to change the permissions of /dev/parport0 device. Give the following command as root:

# chmod a+rwx /dev/parport0

For writing to the microcontroller you will need to have the /dev/parport0 device. If the /dev/parport0 device does not exist, then issue the following commands as root:

# modprobe parport
# mknod /dev/parport0 c 99 0

If that does not work, you will have to recompile your kernel with the PPDEV option enabled.


Download WinAVR. It includes all the utilities required (avr-gcc, avr-libc, avr-binutils and avrdude).

Once you have WinAVR installed, you need at least two files: your program (ending in .c) and a makefile. You can use the Programmer's Notepad to write your programs. The makefile can be generated using the MakeFile Generator or else you can also use the same file as in Linux. I prefer the latter approach. In the Makefile generator, choose the proper options, and give the C source file. Save the Makefile in the same directory as your source file. If you used the Makefile from in the Linux section, you need to make the changes as given above and also have to change the AVRDUDE_PORT to lpt1 instead of /dev/parport0 (line 111).

Note for WinXP/Windows 2000: You need to install a driver (provided with WinAVR) to be able to write directly to the parallel port. Go to the directory where you installed WINAVR, then go into bin. There you will find a file called "install_giveio.bat". Run that file, it will install the driver it requires. You just have to do this once.

If you used the Makefile Generator, you can use the Programmer's Notepad to compile and write the program onto the microcontroller. Choose "Tools->[WINAVR] Make All" to compile. Check for errors, and then "Tools->[WINAVR] Program" to write the code onto the microcontroller.

If you used the Linux Makefile, you will need to use the command prompt. Start the command prompt and go to the directory where your C files are kept. Then you can just use the same commands as in Linux:

make hex
make install

Fuse bits

The AVR microcontrollers are shipped with the internal oscillator (1 MHz) turned on. To use an external oscillator (which is necessary if you want better precision or faster speed), you will have to change the internal fuse bits. For details you can look up the Datasheet. Here note that 1 = Disabled while 0 = Enabled.

Low Byte

Bit             Bit No.  Description                  Default Value 
BODLEVEL        7        Brown-out Det. trig. level   1 (unprogrammed) 
BODEN           6        Brown-out Detector enable    1 (unprogrammed)
SUT1            5        Select start-up time         1 (unprogrammed)
SUT0            4        Select start-up time         0 (programmed)
CKSEL3          3        Select Clock source          0 (programmed)
CKSEL2          2        Select Clock source          0 (programmed)
CKSEL1          1        Select Clock source          0 (programmed)
CKSEL0          0        Select Clock source          1 (unprogrammed)

My choice: 1 1 1 0 1 1 1 1 = 0xEF (This would enable the external oscillator)

High Byte

Bit             Bit No.  Description                  Default Value 
OCDEN           7        Enable OCD                   1 (unprogrammed)
JTAGEN          6        Enable JTAG                  0 (programmed)
SPIEN           5        Enable SPI Downloading       0 (programmed)
CKOPT           4        Oscillator options           1 (unprogrammed) 
EESAVE          3        EEPROM memory is preserved   1 (unprogrammed)
BOOTSZ1         2        Select Boot Size             0 (programmed)
BOOTSZ0         1        Select Boot Size             0 (programmed)
BOOTRST         0        Select reset vector          1 (unprogrammed)

My choice: 1 1 0 0 1 0 0 1 = 0xC9 (Disables JTAG which when enabled causes problems in normal I/O use of PortC pins)

Note: The above values are for ATmega16, if you are using ATmega32, check its Datasheet. I haven't verified whether they are same or not.

To write the values of the fuses using avrdude, use the following command:


$ avrdude -c bsd -p m16 -P /dev/parport0 -U lfuse:w:0xEF:m -U hfuse:w:0xC9:m


avrdude -c bsd -p m16 -P lpt1 -U lfuse:w:0xEF:m -U hfuse:w:0xC9:m
Page last modified on Wed Jul 29 17:36:28 2009 - Powered by PmWiki