← LOGBOOK LOG-356
WORKING · ELECTRONICS ·
ATMEGA328PAVRBARE-METALBREADBOARDSTANDALONECRYSTALISPEMBEDDEDWIRING

ATmega328P Standalone — Wiring the Bare IC

Pulling the ATmega328P out of the Arduino socket and building a minimum viable circuit on a breadboard. Crystal, decoupling caps, reset pull-up, and an LED blinking under bare-metal C.

Why Wire It Standalone

The Arduino Uno is a development board. The ATmega328P is the chip. They’re not the same thing — the board adds a USB-serial bridge, a 5V regulator, a reset circuit, and 16 of the 28 pins broken out to headers. For anything that ships in a product or gets installed in a permanent fixture, you want the IC alone, running on the minimum it needs.

Wiring the chip standalone also forces you to understand what the Uno was quietly providing. The chip needs power, a clock source, a stable reset line, and decoupling capacitors — none of that is optional.


The ATmega328P Pinout (DIP-28)

         ┌──┤├──┐
  PC6 ── 1       28 ── PC5
  PD0 ── 2       27 ── PC4
  PD1 ── 3       26 ── PC3
  PD2 ── 4       25 ── PC2
  PD3 ── 5       24 ── PC1
  PD4 ── 6       23 ── PC0
  VCC ── 7       22 ── GND
  GND ── 8       21 ── AREF
  PB6 ── 9       20 ── AVCC
  PB7 ── 10      19 ── PB5 (SCK / pin 13)
  PD5 ── 11      18 ── PB4 (MISO / pin 12)
  PD6 ── 12      17 ── PB3 (MOSI / pin 11)
  PD7 ── 13      16 ── PB2 (SS / pin 10)
  PB0 ── 14      15 ── PB1
         └───────┘

Pin 1 is PC6 — also RESET. Pin 7 and 20 are VCC. Pin 8 and 22 are GND. Pins 9–10 (PB6/PB7) are the crystal pins.


Minimum Circuit Components

PartValuePurpose
ATmega328PDIP-28The MCU
Crystal16 MHzExternal clock source
Capacitors × 222 pF ceramicCrystal load caps
Capacitor × 2100 nF ceramicPower decoupling (VCC and AVCC)
Resistor10 kΩRESET pull-up
LEDany colourOutput indicator
Resistor220 ΩLED current limiter

Total cost around ₹500–550 if buying loose components. The chip itself is the expensive part at roughly ₹400 for a DIP-28.


Wiring the Circuit

Power

Connect both VCC pins (7 and 20) to the positive rail and both GND pins (8 and 22) to the negative rail. Place a 100 nF decoupling capacitor between VCC (pin 7) and GND as close to the chip as possible — this suppresses high-frequency noise on the supply line that can cause erratic behaviour or reset events. Do the same for AVCC (pin 20).

AREF (pin 21) can float if you’re not using the ADC. If you plan to use analogRead, connect it to VCC through a 100 nF cap.

Crystal

The 16 MHz crystal goes between pins 9 (XTAL1 / PB6) and 10 (XTAL2 / PB7). Each crystal leg also gets a 22 pF ceramic cap to GND. The exact value depends on the crystal’s specified load capacitance — 18 pF and 22 pF are both common and interchangeable for most hobby crystals.

         ┌──── pin 9 (XTAL1)

    [22pF]     [16MHz crystal]

        GND     pin 9 ─── leg 1
                          leg 2 ─── pin 10
                pin 10 ─── [22pF] ─── GND

Without the crystal the chip falls back to its internal 8 MHz RC oscillator (factory default fuse setting is actually 1 MHz internal RC, so freshly bought chips without an Arduino bootloader will run at 1 MHz until you reflash the fuses). The crystal gives you a stable 16 MHz and is required if you’re communicating over serial at higher baud rates.

Reset Line

Pin 1 (RESET, active-low) needs a 10 kΩ pull-up resistor to VCC. Without it the line floats and the chip resets randomly. The Arduino Uno has this built in — on the bare chip you supply it yourself.

VCC ──── [10kΩ] ──── pin 1 (RESET)

You can optionally add a push button between RESET and GND if you want a manual reset. Not required for blink.

LED

Connect an LED and 220 Ω resistor in series from PB5 (pin 19, the same as pin 13 on the Uno) to GND. The resistor limits current to around 14 mA at 5V — safe for the LED and within the ATmega’s 40 mA per-pin absolute maximum.

pin 19 (PB5) ─── [220Ω] ─── [LED] ─── GND

Full Breadboard Layout (described)

  1. Place the ATmega328P straddling the centre gap — pin 1 top-left
  2. Positive rail: connect pins 7 and 20 with jumpers
  3. Negative rail: connect pins 8 and 22 with jumpers
  4. Decoupling: 100 nF cap between the VCC tie and GND rail, same for AVCC
  5. Crystal: bridge pins 9 and 10 with the crystal, 22 pF cap from each pin to GND rail
  6. Reset pull-up: 10 kΩ from positive rail to pin 1
  7. LED: 220 Ω from pin 19 → LED anode → LED cathode → GND rail

Programming the Standalone Chip

The bare chip has no USB port. You need an ISP (In-System Programmer) to flash it. The easiest option if you already have an Arduino Uno: use it as an ISP.

Step 1 — Flash the ArduinoISP sketch onto the Uno

In the Arduino IDE: File → Examples → 11.ArduinoISP → ArduinoISP. Upload to the Uno normally. The Uno is now a programmer.

Step 2 — Wire the SPI lines

Connect the Uno’s SPI pins to the ATmega328P’s corresponding pins:

Uno pinATmega328P pinFunction
101 (RESET)Chip select / reset
1117 (MOSI / PB3)Data out
1218 (MISO / PB4)Data in
1319 (SCK / PB5)Clock
5V7, 20Power (if not externally powered)
GND8, 22Ground

Note: pin 19 is both SCK and the LED pin. During programming the LED will flicker with clock activity. Disconnect it if it causes issues, though in practice 220 Ω is a high enough impedance that it usually works fine.

Step 3 — Upload with avrdude

avrdude -c stk500v1 -p m328p -P /dev/cu.usbserial-1120 -b 19200 \
        -U flash:w:blink.hex

The programmer type is stk500v1 (ArduinoISP), baud is 19200. Compile blink.hex the same way as the previous entry:

avr-gcc -mmcu=atmega328p -DF_CPU=16000000UL -Os -o blink.elf blink.c
avr-objcopy -O ihex blink.elf blink.hex

Same as before — PB5 is the target pin:

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

int main(void) {
    DDRB |= (1 << PB5);   // PB5 output

    while (1) {
        PORTB |= (1 << PB5);   // HIGH
        _delay_ms(500);
        PORTB &= ~(1 << PB5);  // LOW
        _delay_ms(500);
    }
}

If the fuses are set to 1 MHz internal (factory default for chips without an Arduino bootloader), _delay_ms(500) will actually delay 8× longer — 4 seconds — because the compiler calculated the loop count assuming 16 MHz but the chip is running at 1 MHz. Either burn the fuses to use the external crystal, or change F_CPU to 1000000UL when compiling.


Setting Fuses for External Crystal

Fuses are one-time programmable configuration bits that control clock source, boot options, and more. To switch from the internal oscillator to the 16 MHz crystal:

# Low fuse: 0xFF = full crystal swing oscillator, no clock divider
# High fuse: 0xDE = SPI programming enabled, no bootloader section
avrdude -c stk500v1 -p m328p -P /dev/cu.usbserial-1120 -b 19200 \
        -U lfuse:w:0xFF:m -U hfuse:w:0xDE:m

Warning: writing the wrong fuse values can lock the chip. 0xFF low fuse with no crystal connected will cause the chip to hang waiting for a clock that never arrives — and you will not be able to reprogram it over SPI without providing an external clock signal on XTAL1. Double-check the crystal is wired before setting this.

The Arduino Uno bootloader uses lfuse=0xFF, hfuse=0xDE, efuse=0x05 — burning these also installs the bootloader section config, so if you later want to re-add a bootloader you have the right fuse state.


What You Have Now

A working ATmega328P circuit built from scratch — no development board, no USB bridge, no regulator, no pre-flashed bootloader. Just the chip, a clock source, power filtering, and a pull-up on reset. This is the same circuit that goes inside most Arduino-based products once you strip away the development conveniences.