Build 8-Digit LED Display stopwatch using Maxim MAX7219 Serially Interfaced

One of the basic usage of the TIMER peripheral on every microcontroller is to provide the accurate timing mechanism. Using the TIMER peripheral as the basic timing, we could easily develop a stopwatch and display it to the 8-Digit seven segment numeric LED display. Thanks to the Maxim MAX7219 chip which enable us to interface this 8-Digit seven segment LED display much easier using just three wires of the SPI (serial peripheral interface) to display the hour, minute, second, and hundredth of seconds to the 8-Digit seven segments LED display.
On this tutorial we will learn to utilize the Atmel AVR ATMega328P microcontroller SPI peripheral to communicate with the Maxim MAX7219 chip. The AVR ATmega328P SPI peripheral will be configured as a master and Maxim MAX7219 as the SPI device slave; you could read more about the SPI in Using Serial Peripheral Interface (SPI) Master and Slave with Atmel AVR Microcontroller project on this blog. A simplified electronic schematic of this project is shown in this following picture.
The following is the list of hardware, software, and references used to build this project:
1. One Maxim MAX7219: Serially Interfaced, 8-Digit LED Display Drivers
2. Two common cathode 4-Digits seven segment LED display
3. One Resistor: 10K Ohm
4. One Capacitors 0.1uF
5. AVR Jazz 28PIN development board from ermicro which is based on the AVR ATmega328P microcontroller.
6. Atmel AVR Studio 6.0 for coding and debugging environment
7. STK500 programmer from AVR Studio 6.0, using the AVR Jazz 28PIN board STK500 v2.0 boot loader
8. Atmel AVR ATmega328 and Maxim MAX7219 Datasheet
The stopwatch project that we are going to build has these following features:

  • Stopwatch counting up to hundredth of second when the SW1 is pressed
  • Pressing the SW1 once will freeze the counting display while continuing counting in the background, pressing the SW1  again will continue to display the stopwatch counting
  • Adjust the intensity of the 8-Digits seven segment LED display using the trimmer potentiometer (TP).
  • Reset the stopwatch counting by pressing the SW0.

In order to accomplish this project, we will use the AVR ATmega328P 16-bit TIMER2 peripheral in compare match mode as the heart beat of the counting mechanism, the pin change interrupt is used to detect the SW1 switch, and the ADC peripheral is used to adjust the 8-Digit seven segment LED display brightness. This project also serves as a good example of how we use many of the powerful AVR ATmega328P microcontroller features at the same time. The following is the complete C code for this project:

//  File Name    : SSegMAX7219.c
//  Version      : 1.0
//  Description  : Simple Stopwatch Using Maxim MAX7219
//                 Serially Interfaced, 8-Digit LED Display Drivers
//  Author       : RWB
//  Target       : AVR Jazz 28PIN Development Board
//  Compiler     : AVR-GCC 4.6.2 (AVR_8_bit_GNU_Toolchain_3.4.0_663)
//  IDE          : Atmel AVR Studio 6.0
//  Programmer   : AVR Jazz 28PIN board STK500 v2.0 Boot loader
//               : AVR Visual Studio 6.0, STK500 programmer
//  Last Updated : 20 Dec 2012
#define F_CPU 16000000UL          // AVRJazz28PIN Board Used 16MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define SPI_DDR  DDRB
#define SPI_CS   PB2
static volatile uint8_t hours, minutes, seconds, hdseconds;
static volatile uint8_t key state;
void SPI_Write(uint8_t addr, uint8_t data out)
  // Enable CS Pin
  SPI_PORT &= ~(1<<SPI_CS);
  // Start Address transmission (MOSI)    
  SPDR = addr;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));    
  // Start Data transmission (MOSI)
  SPDR = data out;
  // Wait for transmission complete
  while(!(SPSR & (1<<SPIF)));
  // Disable CS Pin
  SPI_PORT |= (1<<SPI_CS);    
void disp digit(uint8_t dindex,uint8_t number,uint8_t nmax) {
  uint8_t digit[2];
if (key state == 2) return;  


  if (number <= nmax) {
    if (number < 10) {      
     digit[0] = number;
    } else {
     digit[1] = number / 10;
     digit[0] = number - (digit[1] * 10);
  SPI_Write(dindex,digit[0] | 0x80); // Enable DP (Decimal Point)
  SPI_Write((dindex + 1),digit[1]);

Read More: Build 8-Digit LED Display stopwatch using Maxim MAX7219 Serially Interfaced

Leave a Comment

Your email address will not be published. Required fields are marked *