7-segment Mini Clock using PIC16F628A and DS1307 RTC

socialicon

This is a minimal and small clock based on PIC16F628A microcontroller and DS1307 RTC IC. It is able to only show the time on a small 7-segment display with a total of 4 segments. The display we used is a 0.28″ SR440281N RED common cathode display bought from LCSC.com, but you can use other displays as well such as the 0.56″ Kingbright CC56-21SRWA. This project is heavily inspired by the “Simple Digital Clock with PIC16F628A and DS1307” in the case of schematic and we also used the same .hex as”Christo”.

Schematic

The schematic is straight forward. The heart is the PIC16F628A microcontroller running on the internal 4MHz oscillator, so no external crystal is needed. This saves us 2 additional IOs. The RESET Pin (MCLR) is also used as input for one of the buttons. All display segments are connected to PORTB and COMs are connected to PORTA. The RTC chip is also connected to PORTA using the I2C bus.

The refresh rate of the digits is about 53Hz and there is no visible flickering. The display segments are time-multiplexed and this makes them appear dimmer than the specifications. To compensate we are going to use some low resistors on the anodes. “Christo” tested it with different values for current limiting resistors R1-R7 and below 220Ω the microcontroller starts to misbehave (some of the digits start to flicker) above 220 Ohm everything seems OK. On the display we used the two middle dots are not connected to any pin on the package, so for the seconds’ indicators, we used the “comma” dots. These pins are connected to the SQW pin of the DS1307, which provides a square wave output with 1 sec period. The SQW pin is open drain, so we need to add a pull-up resistor. Τhe value of this resistor is chosen at 470Ω, after some trial and error testing. On the input side of the MCU, there are two buttons for adjusting the MINUTES and HOURS of the clock as indicated on the schematic. Onboard there is also an ICSP Programming connector, to help with the firmware upload. Finally, there is one unused pin left (RB7), which can be used for additional functionality, like adding a buzzer or an additional LED.

The DS1307 RTC needs an external crystal to keep the internal clock running and a backup battery to keep it running while the main power is OFF. So, the next time you power ON the clock the time would be current. To keep the overall board dimensions small we used a CR1220 battery holder with the appropriate 3V battery. Power consumption is about 35-40mA @ 5V input.

Code

According to the author, the code is written and compiled with MikroC Pro and uses the build-in software I2C library for communicating with RTC chip. If you want to use MPLAB IDE for compiling the code you should write your own I2C library from scratch. For programming the board we used PICkit 3 programmer and software. In this case, in the “Tools” menu check the option “Use VPP First Program Entry“.

PIC Programmer Configuration

The code for this project is listed below. Additionally, you will need the “Digital Clock (PIC16F628A, DS1307, v2).h” file which can be found on the .zip in downloads below. Compiled .hex file is also provided on the same .zip file.

#include "Digital Clock (PIC16F628A, DS1307, v2).h"
#define b1 RA6_bit
#define b2 RA5_bit

// b1_old, b2_old - old state of button pins
// hour10, hour1 - tens and ones of the hour
// min10, min1 = tens and ones of the minutes
byte b1_old, b2_old, hour1, hour10, min1, min10;

// definitions for Software_I2C library
sbit Soft_I2C_Scl           at RA0_bit;
sbit Soft_I2C_Sda           at RA7_bit;
sbit Soft_I2C_Scl_Direction at TRISA0_bit;
sbit Soft_I2C_Sda_Direction at TRISA7_bit;


//  correct bits for each digit
//     RB6 RB5 RB4 RB3 RB2 RB1 RB0
//     g   f   e   d   c   b   a
//  0: 0   1   1   1   1   1   1   0x3F
//  1: 0   0   0   0   1   1   0   0x06
//  2: 1   0   1   1   0   1   1   0x5B
//  3: 1   0   0   1   1   1   1   0x4F
//  4: 1   1   0   0   1   1   0   0x66
//  5: 1   1   0   1   1   0   1   0x6D
//  6: 1   1   1   1   1   0   1   0x7D
//  7: 0   0   0   0   1   1   1   0x07
//  8: 1   1   1   1   1   1   1   0x7F
//  9: 1   1   0   1   1   1   1   0x6F
// BL: 0   0   0   0   0   0   0   0x00

const byte segments[11] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00};


//***********************************************//
//   Sets read or write mode at select address   //
//***********************************************//
void DS1307_Select(byte Read, byte address) {
     Soft_I2C_Start();
     Soft_I2C_Write(0xD0);       // start write mode
     Soft_I2C_Write(address);    // write the initial address
     if (Read) {
        Soft_I2C_Stop();
        Soft_I2C_Start();
        Soft_I2C_Write(0xD1);    // start read mode
     }
}

//********************************//
//   Initialize the DS1307 chip   //
//********************************//
void DS1307_Init() {
     byte sec, m, h;
     DS1307_Select(1, 0);                 // start reading at address 0
     sec = Soft_I2C_Read(1);              // read seconds byte
     m = Soft_I2C_Read(1);                // read minute byte
     h = Soft_I2C_Read(0);                // read hour byte
     Soft_I2C_Stop();
     if (sec > 127) {                     // if the clock is not running  (bit 7 == 1)
        DS1307_Select(0, 0);              // start writing at address 0
        Soft_I2C_Write(0);                // start the clock (bit 7 = 0)
        Soft_I2C_Stop();
        DS1307_Select(0, 7);              // start writing at address 7
        Soft_I2C_Write(0b00010000);       // enable square wave output 1 Hz
        Soft_I2C_Stop();
     }
     m = (m >> 4)*10 + (m & 0b00001111);  // converting from BCD format to decimal
     if (m > 59) {
        DS1307_Select(0, 1);              // start writing at address 1
        Soft_I2C_Write(0);                // reset the minutes to 0
        Soft_I2C_Stop();
     }
     if (h & 0b01000000) {                // if 12h mode (bit 6 == 1)
        if (h & 0b00100000)               // if PM (bit 5 == 1)
           h = 12 + ((h >> 4) & 1)*10 + (h & 0b00001111);
        else
           h = ((h >> 4) & 1)*10 + (h & 0b00001111);
     }
     else
        h = ((h >> 4) & 3)*10 + (h & 0b00001111);
     if (h > 23) {
        DS1307_Select(0, 2);              // start writing at address 2
        Soft_I2C_Write(0);                // reset the hours to 0 in 24h mode
        Soft_I2C_Stop();
     }
}


void incrementH() {     // increments hours and write it to DS1307
     hour1++;
     if ((hour10 < 2 && hour1 > 9) || (hour10 == 2 && hour1 > 3)) {
        hour1 = 0;
        hour10++;
        if (hour10 > 2)
           hour10 = 0;
     }
     DS1307_Select(0, 2);
     Soft_I2C_Write((hour10 << 4) + hour1);
     Soft_I2C_Stop();
}


void incrementM() {     // increments minutes and write it to DS1307
     min1++;
     if (min1 > 9) {
        min1 = 0;
        min10++;
        if (min10 > 5)
           min10 = 0;
     }
     DS1307_Select(0, 0);
     Soft_I2C_Write(0);                       // reset seconds to 0
     Soft_I2C_Write((min10 << 4) + min1);     // write minutes
     Soft_I2C_Stop();
}

void main(){
     // pos: current digit position;
     // counter1, counter2: used as flag and for repeat functionality for the buttons
     // COM[]: drive the common pins for the LED display
     byte pos, counter1, counter2, COM[4] = {0b11101111, 0b11110111, 0b11111011, 0b11111101};
     CMCON = 0b00000111;             // comparator off
     TRISA = 0b01100000;
     TRISB = 0b00000000;
     b1_old = 1;
     b2_old = 1;
     counter1 = 0;
     counter2 = 0;
     pos = 0;
     Soft_I2C_Init();
     DS1307_Init();
     while (1) {
           DS1307_Select(1, 1);      // select reading at address 1
           min1 = Soft_I2C_Read(1);  // read minutes byte
           hour1 = Soft_I2C_Read(0); // read houts byte
           Soft_I2C_Stop();
           min10 = min1 >> 4;
           min1 = min1 & 0b00001111;
           hour10 = hour1 >> 4;
           hour1 = hour1 & 0b00001111;
           if (b1 != b1_old) {        // if the button1 is pressed or released
              b1_old = b1;
              counter1 = 0;
           }
           if (!b1_old) {             // if the button1 is pressed
              if (counter1 == 0)
                 incrementH();        // increment hour
              counter1++;
              if (counter1 > 50)      // this is repeat functionality for the button1
                 counter1 = 0;
           }
           if (b2 != b2_old) {        // if the button2 is pressed or released
              b2_old = b2;
              counter2 = 0;
           }
           if (!b2_old) {             // if the button2 is pressed
              if (counter2 == 0)
                 incrementM();        // increment minutes and reset the seconds to 0
              counter2++;
              if (counter2 > 50)      // this is repeat functionality for the button2
                 counter2 = 0;
           }

           TRISA = TRISA | 0b00011110;       // set all 4 pins as inputs
           switch (pos) {                    // set proper segments high
             case 0: PORTB = segments[hour10]; break;
             case 1: PORTB = segments[hour1]; break;
             case 2: PORTB = segments[min10]; break;
             case 3: PORTB = segments[min1]; break;
           }
           TRISA = TRISA & COM[pos];         // set pin at current position as output
           PORTA = PORTA & COM[pos];         // set pin at current position low
           pos++;                            // move to next position
           if (pos > 3) pos = 0;
     }
}

PCB

PCB is designed with Autodesk EAGLE and design files are available in downloads below. The overall dimensions of the board are 35.56 x 36.61 mm and we used almost SMD components.

Spare PCBs are available for shipment around the world. If you would like to get some drop us a line.
PCB top side

 

PCB bottom side

Autodesk EAGLE file Viewer

Parts List

PartValueSize
R1 to R7220Ω0805
R8-R910k0805
R10470Ω0805
R11-R1210k0805
C1-C2100nF0805
C3100uF/16VSMD
Q132768Hz CrystalTH
IC1PIC16F628A-I/SSSSOP20
IC2DS1307Z+SO8
LED DisplaySR440281N0.28"
BT1CR1220 BAT holderBS-1220-2
JP1PIN Header6 PINs
CN1JST PH Connector2 PINs
ButtonsPTCF-V-T/R4.7*4.5*1.67

Photos

Video

PIC16F628A Datasheet

DS1307 Datasheet

Please follow and like us:
Pin Share

PCB

Subscribe
Notify of
guest

4 Comments
Inline Feedbacks
View all comments
kushan

what modification to do 12hr format and if can indicate am/pm

Rana

What if we need to use big displays?

kushan

how can use coomon anode display with sch and code modifications ? can you explain pls..

RELATED PROJECTS