Introduction: Atmega328: Lose the Crystal and Gain Two Pins

About: Jack passed away May 20, 2018 after a long battle with cancer. His Instructables site will be kept active and questions will be answered by our son-in-law, Terry Pilling. Most of Jack's instructables are tuto…

This instructable explains how to run the Atmega328 chip like the chip in an Arduino without the crystal making breadboarding easier and giving you two extra pins to work with. This program will not work on an Arduino Uno. It makes use of features of the Atmega328 chip that are not available on the Arduino. The pins on the 328, and all Atmel microcontrollers, are arranged in banks of eight. The "D" bank is available but you only have full access to the one bank. There are only six pins available on the "C" bank, the analog input pins, because one of them is not broken out and the other is the reset. Two of the pins on the "B" bank are taken up by the crystal.

It is possible to run the chip without the crystal and have full access to all eight pins on the "B" bank. There is an internal R/C network that can be used to clock the chip. The chip will run at eight MHz instead of sixteen. This is usually not a problem because most Arduino programs do not need the speed anyway. Also the internal clock is not as accurate. The tolerance specified in the datasheet for the ATtiny85 is +/- ten percent while most crystals have a tolerance of 30 PPM. I would assume that the 328 is the same but I could not find it in the 328 datasheet. (The datasheet is hundreds of pages of very dry reading.) There is a very good chance your chip will not be off anywhere close to ten percent. This collection of instructables includes a test of the internal clock in the ATtiny85 chip. and explains how parts are tested to assure they are within tolerance.

I have heard of instances where the serial communications hardware on the Arduino can interfere with the functioning of pins zero and one. With the chip off the board this will not be a problem, but if you are using them for serial communications you will need to preserve them.

Each bank of eight pins is controlled by three eight bit registers.:

  • The DDR register is the data direction, 0 = input, 1 = output.
  • The PIN register is used to read the digital value of the pin.
  • The PORT register has two functions:
    • If the DDR register is set to output 0 sets the pin low and 1 sets it high.
    • If the DDR register is set to input 1 turns on the internal pull-up resistor.

The Arduino IDE has no way to control the pins where the crystal was, they don't have digital pin numbers. Luckily it does provide direct support for manipulating the controlling registers. This instructable shows how to use the pin registers to make programs faster, smaller, and in many cases easier to code.

Step 1: Adding the New Chip Definition to the Arduino IDE

The standard Arduino IDE installation gives you the boot loader to run the chip at eight MHz using the internal clock without the crystal but not the chip definition you need to do it. The boot loader file you need is in the directory /usr/share/arduino/hardware/arduino/bootloaders/atmega/, and the filename is ATmegaBOOT_168_atmega328_pro_8MHz.hex. You need to have the chip definition in a file called boards.txt inside a directory in your hardware directory which is in your sketchbook directory.

If you don't have a hardware directory in your sketchbook directory create one now.

If you already have a boards.txt file in your hardware directory you can add this code into it, otherwise copy this code into a file and name it boards.txt.

Create a directory, give it any name you choose. I called mine 328.

Move your new boards.txt file into this directory, then move that directory into your hardware directory.

# ATmega328 on a breadboard (8 MHz internal clock)
############################################################## on a breadboard (8 MHz internal clock)



Check to make sure the Arduino IDE is finding the chip definitions by opening the Arduino IDE and clicking on Tools and then click on Board. It should look like the picture, you should see an entry for ATmega328 on a breadboard (8 MHz internal clock)

Step 2: Burn the Bootloader

Now that you have the chip definition in place it's time to burn the bootloader, you will need:

This chip does not have a bootloader on it.

If you have a spare chip for your Arduino, or a chip with the bootloader pre-installed, you will need a 16 MHz oscillator to burn the bootloader or the chip will not function. You can use a 16 MHz ceramic resonator or a 16 MHz crystal and two 22 pF capacitors.

Wire up the circuit as shown in the picture and diagrams.

The red dot on the chip indicates pin one.

If you have a new chip, with no bootloader installed, don't bother with the resonator or crystal.

Open the Arduino IDE and click on File=>Examples=>ArduinoISP.

Click on Tools=>Board and select your Arduino board. (typically Arduino Uno)

Click on Tools=>Programmer and select AVRISP mk II.

Click the upload button to load the program to your Arduino.

Click on Tools=>Board again, this time select ATmega328 on a breadboard (8 MHz internal clock).

Click on Tools=>Programmer and select Arduino as ISP.

Click on Tools and select Burn Bootloader.

You will see a message that says Burning bootloader to I/O Board (this may take a minute).

If you get a error message try again, sometimes it just doesn't work and the next time it will.

When it finishes you will get the message Done burning bootloader.

Step 3: Upload the Program

The easiest way to upload a program to the 8 MHz 328 is to pull the 16 MHz chip out of your Arduino and replace it with the 8 MHz chip.

Start the Arduino IDE, click on Tools=>Board and select ATmega328 on a breadboard (8 MHz internal clock).

Click on Tools=>Programmer and select AVRISP mkII.

Copy/Paste the following code into the Arduino IDE and press the upload button.

 * Filename: Count22.ino
 * This program runs on an Atmega328P using the internal clock.

int j = 0; // First nested index.
int k = 0; // Second nested index

void setup()
  DDRB = B11111111; // Set the pin banks to OUTPUT
  DDRC = B11111111;  
  DDRD = B11111111;

void loop()
  for(int i=0;i<256;i++) // The primary index
    PORTB = i; // Set/Clear bits 0 - 7
  if(j<256) PORTD = j; // Set/Clear bits 8 - 15
    PORTD = B00000000; // Clear bits 8 - 15
    j = 0;
    if(k<64) PORTC = k; // Set/Clear bits 16 - 21
      PORTB = B00000000; // Zero everything to start over
      PORTC = B00000000;
      PORTD = B00000000;
      j = 0;
      k = 0;

Step 4: Build the Circuit

To build the circuit you will need:

  • The Atmega328P chip you programmed in the previous steps
  • 2 breadboards
  • 8 Green LEDs
  • 8 Red LEDs
  • 6 Yellow LEDs
  • 22 resistors (470-560 Ohm)
  • 22 gauge hookup wire (I like to use assorted colors for clarity.)
  • A 5 volt power supply

The first picture shows a resistor soldered onto an LED. This is optional, but I found that having a bunch of these made up makes breadboarding a lot easier. Solder a resistor to the cathode lead of some LEDs. The cathode lead is the shorter negative (ground) lead.

You will need to make these with eight red, eight green, and six yellow LEDs for this project.

The red dot on the chip is pin one.

Wire the breadboards like in the diagrams.

The first diagram shows the wiring for the first eight LEDs because it gets covered by further wiring.

To power the circuit you will need a 5 Volt power supply. If you don't have one you can use the 5V and GND pins on your Arduino.

Arduino All The Things! Contest

Participated in the
Arduino All The Things! Contest