Arduino DS1307 RTC Clock Interfacing MAX7219 LED Display Controller

by Lewis Loflin

Date: Nov 15, 2013. In this project I make use of Ds1307 real time clock chip and a MAX7219 Serially Interfaced 8-Digit LED Display to build a clock. The clock will display hours, minutes, and seconds and through the use of three switches one can set the time.

This is an updated version of a clock routine written in 2009 that only used the Arduino compiler serial monitor. I've added an additional connection to data pin 2 on the Arduino to the 1 Hz output of the Ds1307 . By the use of polling DP2 the time is updated every second to the display controller and the DP13 LED state is toggled creating a visual indication.

The code was ported over from the old clock demo while the routines to operate the MAX7219 were developed and ported over from a PIC18F2550 project. While the clock data is read using I2C is already BCD as used by the MAX7219, the routines handling the output had to be totally rewritten.



While all three programs share things in common, none are alike. The 8-digit display module was purchased off of Ebay.

See the Arduino DS1307 schematic.

Arduino connected to MAX7219


/*
  Arduino uses a Ds1307 RTC and a MAX7219 7-segment display
 driver to operate as a clock displaying hours, minutes,
 and seconds. The hours-minutes can be set by three
 switches Sw0-Sw2. 
 Author: Lewis Loflin
 http://www.bristolwatch.com
 
 */

#include <Wire.h> 
// specify use of Wire.h library.

#define blinkPin  13
#define ONE_HZ_SW 2 // one Hz square wave from Ds1307
#define Sw0 4 // set time
#define Sw1 5 // minutes
#define Sw2 6 // hours

#define Rb5  7  // CS
#define Rb6  8  // DATA
#define Rb7  9  // CLK

byte temp;

void setup()

{
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);
  digitalWrite(blinkPin, 0);

  pinMode(ONE_HZ_SW, INPUT);
  pinMode(Sw0, INPUT);  
// for this use a slide switch
  pinMode(Sw1, INPUT);  
// N.O. push button switch
  pinMode(Sw2, INPUT);  
// N.O. push button switch

  pinMode(Rb5, OUTPUT);
  pinMode(Rb6, OUTPUT);
  pinMode(Rb7, OUTPUT);

  // pull-ups on
  digitalWrite(Sw0, HIGH); 
  digitalWrite(Sw1, HIGH);
  digitalWrite(Sw2, HIGH);

  init_MAX7219(); // setup MAX7219
}

void loop()   {

  // wait for HIGH on Dp2
  while(!digitalRead(ONE_HZ_SW)) {
  } 

  Wire.beginTransmission(0x68);
  Wire.write(0);  // location pointer
  Wire.endTransmission();

  Wire.requestFrom(0x68, 7); // send 7 bytes
  byte secs = Wire.read();
  byte mins = Wire.read();
  byte hrs = Wire.read();
  byte day = Wire.read();
  byte date = Wire.read();
  byte month = Wire.read();
  byte year = Wire.read();

  // hours, minutes, seconds

  hrs = hrs & 0x3F; 
  if (hrs <= 0x09)   {
    writeMAX7219(8, 0x00); // mins 10s
    writeMAX7219(7, hrs); // mins units
  }
  if (hrs > 9)   {
    temp = hrs & 0x0F; 
    writeMAX7219(7, temp); // mins units
    temp  = hrs / 16 ; // shift 4 places right
    writeMAX7219(8, temp); // mins 10s
  }

  writeMAX7219(6, 10); // type '-'

  if (mins <= 0x09)   {
    writeMAX7219(5, 0x00); // mins 10s
    writeMAX7219(4, mins); // mins units
  }
  if (mins > 9)   {
    temp = mins & 0x0F; 
    writeMAX7219(4, temp); // mins units
    temp  = mins / 16 ; // shift 4 places right
    writeMAX7219(5, temp); // mins 10s
  }

  writeMAX7219(3, 10); // type '-'

  secs = secs & 0x7F; // clear bit 7
  if (secs <= 0x09)   {
    writeMAX7219(2, 0x00); // seconds 10s
    writeMAX7219(1, secs); // seconds units
  }
  if (secs > 9)   {
    temp = secs & 0x0F; 
    writeMAX7219(1, temp); // seconds units
    temp  = secs / 16 ; // shift 4 places right
    writeMAX7219(2, temp); // seconds 10s
  }

  if (!(digitalRead(Sw0))) set_time(); // set time
  while(digitalRead(ONE_HZ_SW)) {
  } // wait or LOW
  toggle(blinkPin); // 2 HZ// toggle the state on a pin
void toggle(int pinNum) 
{  
  int pinState = digitalRead(pinNum);
  pinState = !pinState;
  digitalWrite(pinNum, pinState); 
}




void set_time()   {
  byte minutes = 0;
  byte hours = 0;

  while (!digitalRead(Sw0))  
// set time switch must be released to exit
  {
    while (!digitalRead(Sw1)) 
// set minutes
    { 
      minutes++;          
      if ((minutes & 0x0f) > 9) minutes = minutes + 6;
      if (minutes > 0x59) minutes = 0;
      // minutes routine
      if (minutes <= 0x09)   {
        writeMAX7219(5, 0x00); // mins 10s
        writeMAX7219(4, minutes); // mins units
      }
      if (minutes > 9)   {
        temp = minutes & 0x0F; 
        writeMAX7219(4, temp); // mins units
        temp  = minutes / 16 ; // shift 4 places right
        writeMAX7219(5, temp); // mins 10s
      } 


      delay(750);
    }

    while (!digitalRead(Sw2)) // set hours
    { 
      hours++;          
      if ((hours & 0x0f) > 9) hours =  hours + 6;
      if (hours > 0x23) hours = 0;
      // hours routine
      if (hours <= 0x09)   {
        writeMAX7219(8, 0x00); // mins 10s
        writeMAX7219(7, hours); // mins units
      }
      if (hours > 9)   {
        temp = hours & 0x0F; 
        writeMAX7219(7, temp); // hours units
        temp  = hours / 16 ; // shift 4 places right
        writeMAX7219(8, temp); // hours 10s
      }      




      delay(750);
    }

    Wire.beginTransmission(0x68); // activate Ds1307
    Wire.write(0); // where to begin
    Wire.write(0x00);          //seconds
    Wire.write(minutes);          //minutes
    Wire.write(0x80 | hours);    //hours (24hr time)
    Wire.write(0x06);  // Day 01-07
    Wire.write(0x16);  // Date 0-31
    Wire.write(0x11);  // month 0-12
    Wire.write(0x13);  // Year 00-99
    Wire.write(0x10); 
// Control 0x10 produces a 1 HZ square wave on pin 7. 
    Wire.endTransmission();
  }    
}



// shift data to MAX7219
// Rb7 -> CLK, Rb6 -> DATA, Rb5 -> CS not
void ssrOut(unsigned char val)  {  
  int j;
  for(j=1; j<=8; j++)  {   // shift out MSB first
    unsigned char  temp = val & 0x80; // MSB out first
    if (temp == 0x80) digitalWrite(Rb6, 1); // Rb6 DATA          
    else digitalWrite(Rb6, 0); 
    digitalWrite(Rb7, 1);
    delayMicroseconds(20);
    digitalWrite(Rb7, 0);
    val = val << 1; // shift one place left
  }  // next jvoid pulseCS(void)   {
  digitalWrite(Rb5, 1);
  delay(1);
  digitalWrite(Rb5, 0);
}


void init_MAX7219(void)   {
  digitalWrite(Rb5, 0); // CS NOT

  // set decode mode
  ssrOut(0x09); // address
  //	ssrOut(0x00); // no decode
  ssrOut(0xFF); // 4-bit BCD decode eight digits
  pulseCS();

  // set intensity
  ssrOut(0x0A); // address
  ssrOut(0x0D); // 5/32s
  pulseCS();

  // set scan limit 0-7
  ssrOut(0x0B); // address
  //	ssrOut(0x07); // 8 digits
  ssrOut(0x07); // 4 digits
  pulseCS();

  // clear MAX7219
  for(int i=1; i<=8; i++)   {
    ssrOut(i);
    ssrOut(0x00);
    pulseCS();
  }
  
  // set for normal operation
  ssrOut(0x0C); // address
  // ssrOut(0x00); // Off
  ssrOut(0x01);  // On
  pulseCS();

} 

void writeMAX7219(char address, char data)   {
  ssrOut(address); // valid numbers 1-8
  ssrOut(data); 
  pulseCS();
}


You Tube Arduino Microcontroller Video Series March 2012: