ATmega328P and the Arduino UNO R3
Pinout of the ATmega328P and how it maps to the Arduino UNO R3.
Note: According to the Datasheet most of this Information also applies to the ATmega328, ATmega168(P)A, ATmega88(P)A and ATmega48(P)A.
Table of Contents
Pinout Table
The following Table applies to the 28 Pin DIP Packaged ATmega328. The Arduino Pin mapping is based on the Arduino UNO R3.
Pin | Name | Arduino Pin | PWM | PCINT | Bus | Extra |
---|---|---|---|---|---|---|
1 | PC6 | Reset | 14 | Reset | ||
2 | PD0 | 0 | 16 | Serial RX | ||
3 | PD1 | 1 | 17 | Serial TX | ||
4 | PD2 | 2 | 18 | Ext. Interrupt 0 | ||
5 | PD3 | 3 | OC2B | 19 | Ext. Interrupt 1 | |
6 | PD4 | 4 | 20 | Serial XCK | Timer 0 | |
7 | VCC | |||||
8 | GND | |||||
9 | PB6 | 6 | XTAL1, TOSC1 | |||
10 | PB7 | 7 | XTAL2, TOSC2 | |||
11 | PD5 | 5 | OC0B | 21 | Timer 1 | |
12 | PD6 | 6 | OC0A | 22 | AIN0 | |
13 | PD7 | 7 | 23 | AIN1 | ||
14 | PB0 | 8 | 0 | CLKO, ICP1 | ||
15 | PB1 | 9 | OC1A | 1 | ||
16 | PB2 | 10 | OC1B | 2 | SPI SS | |
17 | PB3 | 11 | OC2A | 3 | SPI MOSI | |
18 | PB4 | 12 | 4 | SPI MISO | ||
19 | PB5 | 13 | 5 | SPI SCK | Builtin LED (Arduino) | |
20 | AVCC | Analog VCC | ||||
21 | AREF | Analog Reference | ||||
22 | GND | |||||
23 | PC0 | 14 (A0) | 8 | ADC0 | ||
24 | PC1 | 15 (A1) | 9 | ADC1 | ||
25 | PC2 | 16 (A2) | 10 | ADC2 | ||
26 | PC3 | 17 (A3) | 11 | ADC3 | ||
27 | PC4 | 18 (A4) | 12 | I²C SDA | ADC4 | |
28 | PC5 | 19 (A5) | 13 | I²C SCL | ADC5 |
- Pin
- Physical Pin on the ATmega328P DIP Package.
- Name
- The Pin name in the ATmega328 Datasheet.
- Arduino Pin
- The Pin number/name assigned by Arduino.
- PWM
- Which oscillator the Pin is connected to. If it is connected to one it supports PWM.
- PCINT
- The Pin Change Interrupt number assigned to the pin.
- Bus
- Bus protocol Hardware the pin is connected to.
- Extra
- Any extra features the Pin might have or a short explanation.
Note on SPI Nomenclature: Instead of the old "Master" and "Slave" terminology on SPI you can use Main and Secondary while keeping all the old Acronyms. 😉
Barebones Arduino UNO R3 compatible
Maybe you've built something awesome and now you want to get it off that bulky Arduino board and for some reason the individual parts are cheaper than a tiny Arduino compatible board (they used to be, guess who has a stash of ATmega328P chips).
Needed Parts
To build a barebones Arduino UNO R3 compatible you need:
- One ATmega328P
- Something to flash the Arduino bootloader
- Power circuit:
- A stable 5V Power supply (I.e. from USB)
- Two optional 100nF Capacitors
- One optional 10μH Inductor
- Clock Circuit:
- One 16MHz Crystal
- Two 22pf Capacitors
- Reset Circuit
- One button (open by default)
- One 10KΩ (roughly) Resistor
- One optional 100nF Capacitor
Building the circuit
For the power Connect VCC and AVCC to 5V and the two GND to Ground. Leave AREF floating unless you need it.
If you want that extra bit of reliability connect a 100nF Capacitor between VCC and GND and between AVCC and GND. The official UNO has a 10μH inductor between AVCC and the 5V to stabilise it even more.
Note on AREF: The official Arduino boards connect AREF through 100nF Capacitor to ground. I assume this is to initially pull it to Ground while allowing you to override that setting by simply applying a voltage.
For the Clock connect the 16MHz crystal between XTAL1 and XTAL2, and each of XTAL1 and XTAL2 through a 22pf Capacitor to Ground. Try to no make the circuit paths too long here.
For the Reset Circuit: Connect the Reset pin through a 10KΩ Resistor to 5V, put the button between Reset and Ground.
When using a Serial interface (Make sure it uses 5V logic levels, otherwise you'll destroy something), put the 100nF Capacitor between the Ready to Send (RTS or DTR) and the Reset pin, this way the Chip will automatically reset when the Serial line becomes active, which is the exact behaviour you want when programming using the Arduino bootloader.
Note on perfboard Layout: On a perfboard I usually try to go as compact as possible and have a male header right up to the microcontrollers pins that gives access to GND, Reset, RX and TX (with VCC being part of a male GND, VCC, GND header). The DTR capacitor is on a little adaptor board along with an indicator LED that then plugs into my FTDI breakout. The reset button is near the Reset pin and the pull-up resistor goes below the IC-Socket.
Flashing the Bootloader
To flash the Arduino bootloader onto the ATmega328P you have to hook up the SPI interface to a programmer. See the official Arduino tutorial for this step or my tutorial for doing the same using arduino-cli
.
PWM and Timer/Counters
The ATmega328P has 3 so called Timer/Counter units, called Timer/Counter0, Timer/Counter1 and Timer/Counter2 each can drive 2 of 6 PWM channels.
I'll abbreviate them as t/c in the following.
Oversimplified they are counters hooked up to a configurable Clock source. Every time the clock ticks the counter increments by one. Each counter has two comperators to trigger actions when the counter has reached a configured point.
The actions that can be triggered may be:
- Interrupts to the CPU
- A PWM Signal that can be output on a pin.
- Reset the counter
t/c0 and t/c2 have an 8-bit counter while t/c1 has a 16-bit counter (it can be put in 8-bit and 12-bit modes too).
The clock source itself is too complicated to explain as there are many options, best explained by the official Datasheet. Usually the system clock is used. Each t/c also has a prescaler that can be used to make it run slower than the system by a certain factor.
There are a few modes the counters can be in:
- Normal
- Simply counts up and does something when the timer overflows and wraps back to 0
- Clear Timer on Compare Match (CTC)
- Counts up, but wraps to 0 and does something when the value in ine of the control registers matches
- Fast PWM
- Counts up, on a first match the PWM signal is turned off, on a second or overflow it is turned back on.
- Phase Correct PWM Mode, Timing Diagram
- Counts up and instead of wrapping down again, the PWM signal is toggled at a comparison point.
For The Phase Correct PWM Mode, the center of the wave always stays in the same place, which is good for driving motors. It also effectively halfes the frequency of the t/c in addition to whatever the prescaler does.
PWM and Arduino
The Arduino has 6 PWM capable pins, each connected to one comparator channel of the three timers.
By default all of the t/cs are in 8-bit resolution Phase Correct PWM with clock division by 64 in the prescaler, wrapping at the 8-bit overflow (after 256 cycles), which reults in a PWM frequency of ~490Hz.
The exception here is t/c0 driving the counter behind the millis()
function (code) is in Fast PWM Mode. This is why Arduino Pins 5 and 6 have double the frequency at ~980Hz.
Tone generation
The tone()
function uses t/c2 which is why it messes up the PWM on Arduino Pins 3 and 11.
The underlying code adjusts the clock divider and Compare Registers to select an appropriate one for the desired frequency, and puts the timer into Clear Timer on Compare Match Mode to generate generate an unmodulated square wave.
Assumption: Based on how the code looks it is now capable of using any PWM pin for the tone generating and mess up the the corresponding other PWM pin. I've not bothered to prove or disprove this yet, do your own research.
Avoiding PWM flickering
When connecting an RGB LED to a combination of t/c0 and one of the other timers to generate pretty colors you might notice an annoying flicker which comes from you seeing some interference pattern that stems from the different modes.
Since you really shouldn't change the configuration of t/c0 you can put one of the other timers in Fast PWM mode (the LEDs don't care).