The Classroom

The ATmega328P IC

Different programming methods

Dean Corva

Issue 36, July 2020

This article includes additional downloadable resources.
Please log in to access.

Log in

The ATmega328P is the brains of many Maker projects. We take a look at this versatile chip, different ways to program it, and how to use one standalone.

Being part of the maker family generally means at some point or another you’ve encountered an ATmega328P. This humble microcontroller is cheap, robust, and easy to program, the backbone of many maker projects.

Generally speaking, the main reason we’ve heard of the ATmega328P is from using an Arduino, a development board centred around the Mega series of microcontrollers, specifically the Uno and Nano, which use different packages of the ATmega328P.

We’ve used the ATmega328P in its bare form in previous articles, however, let’s spend time just focusing on the ATmega328P, as you may learn something different from the Mega series in its wild form, outside its usual Arduino habitat.

But why use the ATmega328P on its own and not just stick to the development board? Simply put, we can significantly reduce the size of our projects. Once we’ve uploaded our code to the microcontroller, all the additional connections and components on the development board may not be necessary, such as the USB connector, or female pin headers. Thus, we can implement the microcontroller only with its necessary components to a breadboard or custom designed printed circuit board.


Briefly summarising, the ATmega328P is an 8-bit microcontroller that operates on a RISC architecture. 8-bit means the processor uses an 8-bit register, which can handle 2^8 or 256 data values, which seems low for today’s standards, however, the higher the bit count and processing speed, the more power consumption the processor uses, hence, why microcontrollers are a favourable choice for low-power solutions.

The ATmega328P has many peripheral and special features that can be found in its 294-page datasheet(!). We can’t possibly list them all, otherwise, our article will become a datasheet also. Instead, we will focus on some key aspects that you may not have known about the ATmega328P.

It is also the IC used on the Arduino Uno board. This PDIP package is really good for prototyping due to its breadboard compatibility. If the final solution of your project needs to be compact, the ATmega328P-MM is a 4 x 4mm surface-mount package to optimise your PCB space, however, these can be near impossible to solder by hand.


There are many methods to program your ATmega328P, and different ways to use an ATmega328P in a circuit depending on your application. 

Below, we will describe four different projects that you can easily build and test for yourself. 

We will explore four different programming methods so you can choose the best programmer for your projects. This includes using an Arduino Uno, an FTDI breakout board, and an In-Circuit Serial Programmer (ICSP). 

We will also cover when to use the ATmega328P's internal oscillator or when you need to apply an external crystal oscillator. 


To get started, you will need to get the parts that are common to all four builds, and the additional parts for the build you intend to make.

ZZ8727 ATMEGA328P MCU IC with Arduino Uno Bootloader. IMAGE CREDIT:
1 x 16MHz Crystal (Not required for Build 4)RQ5296V1289ACOM-00536
2 x 22pF Capacitors* (Not required for Build 4)RC5316R2814CE05189
1 x LED*ZD0150Z0800CE05104
1 x 330Ω Resistor*RR2762R0040PRT-14490


* Quantity shown, may be sold in packs. You’ll also need a breadboard and prototyping hardware.

Build 1:

Using an Arduino Uno Board

Additional Parts for Build 1:JaycarAltronicsCore Electronics
1 x Arduino Uno or CompatibleXC4410Z6280A000066
1 x USB A-B LeadWC7906P1911CFIT0056

Additional Parts for Build 1:

For this example, we will transfer the ATmega328P IC on your Arduino Uno onto a breadboard to work stand-alone (We just use the Uno for power).

We should point out that you need an Arduino Uno with a DIP type ATmega328P IC in a socket that you can easily remove. Some Arduino Uno clones have the surface mount type ATmega328P instead.

First, let’s load the simple blink program onto the Uno.

With your Arduino Uno connected to your computer via USB, go to Tools › Board and ensure Arduino / Genuino Uno is selected.

Go to Tools › Port and select the port your Uno is plugged into, then select File › Examples › 01.Basics › Blink and upload to the Arduino Uno. We should now see the built-in LED on the Arduino Uno blinking every second.

Disconnect your Arduino Uno from USB so that it is powered off. Then, very carefully remove the ATmega328P from the Arduino Uno, and place it into a breadboard.

If you do not have access to an IC removal tool, an easy way to carefully remove the ATmega328P from the Arduino socket is by using a very thin flat-head screwdriver, and gently pry both ends back and forth until its removed, ensuring no pins are bent.

To operate this ATmega328P, we need a source of power. We also need a 16MHz external crystal oscillator and two 22pF ceramic capacitors. Microcontrollers use an oscillation signal to generate a clock signal, which determines the speed the microcontroller operates its processes. This means the microcontroller conducts an operation every time there is a state change in the clock signal. Arduino uses an external crystal oscillator for this, meaning it operates at a processing speed of 16MHz. The ATmega328P actually contains its own internal oscillators, however, they are inferior to the external crystal in terms of stability. The capacitors used with the external crystal are there to resonate with the crystals inductance, meaning the crystal will resonate on its fundamental frequency.

To operate the blink program, we need an LED and 330Ω resistor, which will limit the current to the LED to avoid it burning out, and prevent too much current draw from the ATmega328P, as the maximum current draw per pin is 40mA.

Follow the schematic and Fritzing to wire your circuit. Use the Arduino as the source of power, as it contains a 5V regulated output. You will need to connect it to an available USB port on your computer or USB power source, or use a DC power supply. You should now see the LED blinking on your breadboard. Success!

Build 2:

Using an FTDI Board

Additional Parts for Build 2:JaycarAltronicsCore Electronics
1 x ATmega328P with Arduino Bootloader^ZZ8727Z5126DFR0081
1 x USB A to Micro B LeadWC7757P1897AFIT0265
1 x 100nF CapacitorRG5125R2736BCE05188
1 x FTDI boardXC4594Z6225DFR0164

Additional Parts for Build 2:

* Quantity shown, may be sold in packs. You’ll also need a breadboard and prototyping hardware.

^ The Jaycar ZZ8727 includes the 16MHz crystal.

In our first example, we used the Arduino to upload code to the ATmega328P. However, this isn’t the only option for using Arduino to upload code to the microcontroller.

This example uses an FTDI (Future Technology Devices International) board to communicate to the microcontroller via USB.

We can purchase the ATmega328P with Arduino bootloader pre-installed. A bootloader is a section of memory allocated in the microcontroller that runs prior to the main code, allowing the microcontroller to understand the main code, which in our case is the Arduino language. If you plan on using Arduino for the main code, this is an easy solution as we don’t have to upload the Arduino bootloader onto the ATmega328P ourselves.

Note: There are other bootloaders available also, such as optiboot, which is a simpler version that frees up 1.5k bytes of memory used in Arduino bootloader.

Following the schematic and Fritzing, connect the ATmega328P with bootloader and FTDI board.

We have selected an FTDI board that uses an Atmel ATmega8u2 with Arduino firmware loaded, meaning to an Arduino IDE, it appears as an Arduino Uno. Search for the board using the previous steps and upload the blink sketch to the ATmega328P.

It works!

DFR0164 FTDI breakout board. IMAGE CREDIT:

Build 3:

Using an In-Circuit Serial Programmer (ICSP)

Additional Parts for Build 3:JaycarAltronicsCore Electronics
1 x ATmega328P^ZZ8727Z5125002-556-ATMEGA328P-PU
1 x USB A to Micro B LeadWC7757P1897AFIT0265
1 x USBasp ICSPXC4627Z6540CE04564

Additional Parts for Build 3:

* Quantity shown, may be sold in packs. You’ll also need a breadboard and prototyping hardware.

^ The Jaycar ZZ8727 includes the 16MHz crystal.

Now, let’s burn the Arduino bootloader to a fresh ATmega328P that currently has no bootloader on it. To do this, we will use what is called an In-Circuit Serial Programmer (ICSP).

Following the schematic and Fritzing, connect the ICSP to the breadboard. The ICSP tries to program at a clock speed of 375kHz, too fast for a brand new ATmega328P. Our ICSP has a jumper connector for “slow-clock”, which slows the programming speed to 8kHz.

Connect the “slow-clock” jumper, followed by connecting the USB of the ICSP to the computer.

Windows users will need to install a driver for the ICSP located on the manufacturer’s website. Mac and Linux users do not need to install drivers.

On the Arduino IDE, locate Tools › Programmer › USBasp.

To upload the Arduino bootloader, select Tools › Burn Bootloader. Once the bootloader has been installed, we can upload the blink sketch to the microcontroller by selecting Sketch › Upload Using Programmer. Once again you should have a blinking LED!

CE04564 USBasp ICSP Programmer. IMAGE CREDIT:

Build 4:

ATmega328P Programmed Using C

Additional Parts for Build 4:JaycarAltronicsCore Electronics
1 x ATmega328PZZ8727Z5125002-556-ATMEGA328P-PU
1 x USB A to Micro B LeadWC7757P1897AFIT0265
1 x ICSP (eg. Atmel-ICE or similar. See text.)-Element 14: 2407172 -

Additional Parts for Build 4:

* Quantity shown, may be sold in packs. You’ll also need a breadboard and prototyping hardware.

^ The Jaycar ZZ8727 includes the 16MHz crystal.

Let’s move away from Arduino now and use the ATmega328P in its bare form, and program using compilers other than Arduino, such as C++ and C.

The manufacturer of the ATmega328P, Atmel, offer programming of the microcontroller using their software, Atmel Studio. This software is free to download, with the latest revision being Atmel Studio 7, however, it only operates on Windows and is a large program, intended for the professional market.

Using this software, we can use the full potential of the ATmega328P. This includes operating a clock speed from as low as 1MHz up to a maximum of 20MHz and an operating voltage from as low as 1.8 volts up to 5.5 volts. We can select the internal crystal using Atmel Studio, AVRfuses, and other options.

2407172 ATMEL-ICE Basic Debugger. IMAGE CREDIT:

Programming using Atmel Studio involves an ICSP programmer. We used the Atmel-ICE programmer as this is supported in Atmel Studio and by AVRdude, however, the USBasp is compatible with Atmel Studio 7 (It’s just a very tedious process that could be an article in itself).

Follow the schematic and Fritzing, and connect the ICSP programmer you intend you use.

Download the Atmel Studio hex code from the DIYODE website, and upload it to the ATmega328P by selecting Build › Build Solution, followed by Tools › Device Programming › Tool (ICSP Programmer) › Device (ATmega328P) › Interface (ISP).

Then, read the Device Signature, followed by Memories › Flash › Program.

You should once again see a blinking LED!

This code operates off a 1MHz clock signal and can operate from a 3.3V source. But why? Well as mentioned earlier, operating off a slower clock signal and operating voltage can reduce the power consumption of the device.

Operating a green 10mm LED off an ATmega328P running at 16MHz, powered by 5 volts with Arduino bootloader, resulted in a measured 16mA during active state and 22mA when LED illuminated.

Using the same LED off an ATmega328P running at 1MHz on 3.3 volts using Atmel Studio C code resulted in a measured 1.3mA during active state and 3mA when the LED illuminated. That’s 110mW compared to 10mW, a 100mW power saving! All the while doing the exact same functionality.

We can also operate with a faster clock speed of 20MHz. This is helpful with faster data transfer speeds between communication protocols. Although we sacrifice a higher power consumption, we can transfer the data faster, meaning a higher power consumption is achieved for a shorter duration. Better than a lower power consumption for a longer duration, as processing is slower and could result in the same overall power consumption.


If low power consumption is the highest priority for your application, then the last method would be your best solution. If you are prototyping a quick solution with minimal code and multiple microcontrollers then the third solution would be the best solution, as ICSP can program multiple devices at once and Arduino bootloader is easy to program.

Dean Corva

Dean Corva

DIYODE Staff Writer