You program an [ATmega16](https://www.ampheo.com/search/ATmega16) by:
1. Powering it correctly
2. Connecting a programmer to the ISP pins
3. Compiling your C code with avr-gcc (or [Microchip](https://www.ampheo.com/manufacturer/microchip-technology) Studio)
4. Flashing it with avrdude (or the IDE’s “Program” button)
I’ll give you a clear, practical path.

**1. What you need**
**Hardware**
* ATmega16 (in DIP or SMD, doesn’t matter as long as you can connect it)
* 5 V power supply (or 3.3 V if you run at a lower clock)
* Programmer, for example:
* USBasp
* USBtinyISP
* AVRISP mkII / Atmel ICE
* Or an [Arduino](https://www.ampheo.com/c/development-board-arduino) as ISP (Uno/Nano as programmer)
* A 10 kΩ pull-up on RESET is recommended if you’re making your own board
* Optional but useful: [crystal](https://www.onzuu.com/category/crystals) + 2×22 pF caps (if you want an external clock)
**Software options**
* Windows (easy): Microchip Studio (ex-Atmel Studio)
* Cross-platform (Linux/Win/Mac):
* avr-gcc (compiler)
* avrdude (programmer tool)
* Any text editor / VS Code
I’ll show you the “avr-gcc + avrdude” way, but you can map it onto Microchip Studio (it just runs those tools behind the scenes).
**2. Wiring the programmer (ISP interface)**
ATmega16 has an ISP (In-System Programming) interface on these pins:
* MOSI – PB5
* MISO – PB6
* SCK – PB7
* RESET – RESET pin
* VCC – +5 V
* GND – 0 V
Connect your programmer like this (USBasp example):
* USBasp MOSI → ATmega16 PB5 (MOSI)
* USBasp MISO → ATmega16 PB6 (MISO)
* USBasp SCK → ATmega16 PB7 (SCK)
* USBasp RST/RESET → ATmega16 RESET
* USBasp VCC → ATmega16 VCC (5 V)
* USBasp GND → ATmega16 GND
Also:
* Put a 100 nF decoupling capacitor between VCC and GND close to the chip.
* If you’re using an external crystal, connect it to XTAL1/XTAL2 with the two 22 pF caps to ground.
**3. Write a simple C program (blink example)**
Let’s blink an LED on PORTB0 (pin PB0):
* LED anode → PB0 through 330–1 kΩ [resistor](https://www.onzuu.com/category/resistors)
* LED cathode → GND
main.c
```
#define F_CPU 8000000UL // 8 MHz internal RC (default on many ATmega16s)
#include <avr/io.h>
#include <util/delay.h>
int main(void) {
// Set PB0 as output
DDRB |= (1 << PB0);
while (1) {
// LED an
PORTB |= (1 << PB0);
_delay_ms(500);
// LED aus
PORTB &= ~(1 << PB0);
_delay_ms(500);
}
}
```
If your clock is different (e.g. 16 MHz external crystal), change F_CPU accordingly.
**4. Compile with avr-gcc**
From the terminal in the folder with main.c:
```
avr-gcc -mmcu=atmega16 -DF_CPU=8000000UL -Os -o main.elf main.c
avr-objcopy -O ihex -R .eeprom main.elf main.hex
```
Now you have main.hex, the file to flash.
**5. Flash using avrdude**
Using USBasp as an example:
`avrdude -c usbasp -p m16 -U flash:w:main.hex`
Explanation:
* -c usbasp – programmer type
* -p m16 – target device = ATmega16
* -U flash:w:main.hex – operation: write (w) to flash from main.hex
If all goes well, you’ll see progress and “avrdude done. Thank you.”
Your LED on PB0 should start blinking.
**6. Using an Arduino as ISP (alternative)**
If you don’t have a dedicated programmer:
1. On your [Arduino Uno](https://www.ampheo.com/product/a000046-25542493): open Arduino IDE → File → Examples → 11.ArduinoISP → ArduinoISP → Upload.
2. Wire Arduino to ATmega16:
* Arduino D10 → ATmega16 RESET
* Arduino D11 (MOSI) → ATmega16 PB5 (MOSI)
* Arduino D12 (MISO) → ATmega16 PB6 (MISO)
* Arduino D13 (SCK) → ATmega16 PB7 (SCK)
* Arduino 5V → ATmega16 VCC
* Arduino GND → ATmega16 GND
3. Then program with avrdude like:
`avrdude -c arduino -P COMx -b 19200 -p m16 -U flash:w:main.hex`
(Replace COMx with your actual serial port.)
**7. Fuses (clock, reset, etc.)**
The [ATmega16](https://www.ampheoelec.de/search/ATmega16) has fuse bits controlling:
* Clock source (internal RC vs external crystal)
* Brown-out detection
* JTAG enable
* etc.
Example: to use the internal 8 MHz RC [oscillator](https://www.onzuu.com/category/oscillators), you typically make sure CKSEL [fuses](https://www.onzuu.com/category/fuses) are set accordingly. Many chips come that way from the factory, so the blink example often works with no fuse changes.
You can read fuses with:
`avrdude -c usbasp -p m16 -U lfuse:r:-:h -U hfuse:r:-:h`
And write them (be careful!) similarly. Mis-setting fuses (e.g. requiring an external clock when you don’t have one) can “brick” the chip until you fix it with the right clock and programmer.
**8. Quick checklist**
1. Power: 5 V, decoupling cap.
2. Programmer wired to ISP pins (MOSI/MISO/SCK/RESET/VCC/GND).
3. Simple C code compiled with avr-gcc for -mmcu=atmega16.
4. Flash via avrdude (or Microchip Studio’s “Program” button).
5. Only touch fuses if you know what you’re changing.