electroSome

Digital Alarm Clock using PIC Microcontroller and DS3234 RTC

Here is a digital alarm clock made using PIC 18F4520 Microcontroller and DS3234 RTC (Real Time Clock). This project is for educational purposes or can be used as a reference for integrating DS3234 RTC. DS3234 is a very accurate RTC IC with integrated on chip temperature compensated crystal oscillator. It can be integrated with a microcontroller using SPI bus. This project is developed using MPLAB XC8 compiler.

Components Required

Circuit Diagram

Digital Alarm Clock using PIC Microcontroller and DS3234 RTC – Circuit Diagram

I hope that you can easily understand the circuit diagram. The circuit is powered using a 5V power supply. 20MHz crystal is connected to PIC Microcontroller to provide necessary clock for the operation. MCLR pin is directly tied to VDD. DS3234 RTC is connected to the PIC microcontroller via SPI bus and interrupt output of RTC IC is connected to RB0 of the PIC microcontroller to trigger alarm. 4X3 keypad is connected to RD0 – RD6 pin of the PIC microcontroller. RD7 pin of PIC microcontroller, which is configured as an output is connected to a buzzer and an LED via a BC547 NPN transistor wired as a switch.

Note 1 : VBAT of the RTC IC is not connected in the above circuit diagram. It is highly recommenced to connect it to a 3V button cell or coin cell battery to keep the time in case of main power failure.

Note 2 : It is highly recommended to add 4 schottky diodes to 4 outputs to the keypad (RD3 ~ RD6) to avoid possible damage to the microcontroller if two keys are pressed simultaneously. For example, in the above circuit if we accidentally press keys 1 and key 4 at the same time, it will short RD3 and RD4 pins of the microcontroller. It will cause higher current consumption when either of the pin is held high during keypad scanning. Thank you “Tim Nicholson” for suggesting this in the comments section.

MPLAB XC8 Code

Program is little lengthy, click here to view the code.

/*
 * File:   newmain.c
 * Author: Ligo George
 *
 * Created on March 4, 2016, 7:06 AM
 */


// PIC18F4520 Configuration Bit Settings

// 'C' source line config statements
// CONFIG1H
#pragma config OSC = HS         // Oscillator Selection bits (HS oscillator)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3         // Brown Out Reset Voltage bits (Minimum setting)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = OFF     // Stack Full/Underflow Reset Enable bit (Stack full/underflow will not cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) not code-protected)

// CONFIG5H
#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks)



#include <xc.h>
#include <pic18f4520.h>

#define _XTAL_FREQ 20000000 //Crystal Oscillator Frequency

//LCD Connections Start
#define RS LATBbits.LATB2
#define EN LATBbits.LATB3
#define D4 LATBbits.LATB4
#define D5 LATBbits.LATB5
#define D6 LATBbits.LATB6
#define D7 LATBbits.LATB7
//LCD Connections End

#define ALMtd 200 //Alarm & Repeat Time Setting

short bz;  //Alarm Buzzer Times

void Lcd_Port(char a)   //Send Data to LCD Port
{
    if(a & 1)
        D4 = 1;
    else
        D4 = 0;

    if(a & 2)
        D5 = 1;
    else
        D5 = 0;

    if(a & 4)
        D6 = 1;
    else
        D6 = 0;

    if(a & 8)
        D7 = 1;
    else
        D7 = 0;
}
void Lcd_Cmd(char a)  //Send Command to LCD
{
    RS = 0;             // => RS = 0
    Lcd_Port(a);
    EN  = 1;            // => E = 1
    __delay_ms(1);
    EN  = 0;            // => E = 0
}

void Lcd_Clear()    //Clear LCD Display
{
    Lcd_Cmd(0);
    Lcd_Cmd(1);
     __delay_ms(1);
}

void Lcd_Cursor_ON()   //Turns ON LCD Cursor
{
    Lcd_Cmd(0);
    Lcd_Cmd(0xF);
    __delay_ms(1);
}

void Lcd_Cursor_OFF()   // Turns OFF LCD Cursor
{
    Lcd_Cmd(0);
    Lcd_Cmd(0xC);
    __delay_ms(1);
}

void Lcd_Set_Cursor(char a, char b) //Set LCD Cursor Location
{
    char temp,z,y;
    if(a == 1)
    {
        temp = 0x80 + b - 1;
        z = temp>>4;
        y = temp & 0x0F;
        Lcd_Cmd(z);
        Lcd_Cmd(y);
    }
    else if(a == 2)
    {
        temp = 0xC0 + b - 1;
        z = temp>>4;
        y = temp & 0x0F;
        Lcd_Cmd(z);
        Lcd_Cmd(y);
    }
}

void Lcd_Init() //Initialize LCD
{
    Lcd_Port(0x00);
    __delay_ms(20);
    Lcd_Cmd(0x03);
	__delay_ms(5);
    Lcd_Cmd(0x03);
	 __delay_ms(11);
    Lcd_Cmd(0x03);
    /////////////////////////////////////////////////////
    Lcd_Cmd(0x02);
    Lcd_Cmd(0x02);
    Lcd_Cmd(0x08);
    Lcd_Cmd(0x00);
    Lcd_Cmd(0x0C);
    Lcd_Cmd(0x00);
    Lcd_Cmd(0x06);
}

void Lcd_Write_Char(char a)   //Write a Character to LCD Display
{
    char temp,y;
    temp = a&0x0F;
    y = a&0xF0;
    RS = 1;             // => RS = 1
    Lcd_Port(y>>4);             //Data transfer
    EN = 1;
    __delay_us(40);
    EN = 0;
    Lcd_Port(temp);
    EN = 1;
    __delay_us(40);
    EN = 0;
    __delay_ms(1);
}

void Lcd_Write_String(char *a) //Write String to LCD Disply
{
    int i;
    for(i=0;a[i]!='\0';i++)
        Lcd_Write_Char(a[i]);
}

void spiMasterInit( void ) //Initialize SPI as Master
{
    SSPSTAT = 0x00; // SMP=0(slave mode),CKE=0(transmission on Idle to active clock state), all other bits 0      
    SSPCON1 = 0x22; // SSPEN = 1 (enable serial port), SSPM[3-0] = 0b0010 (master mode, clcok=FOSC/64), all other bits are zero                                        
 
    TRISCbits.RC3 = 0;
    TRISCbits.RC5 = 0;
}  

void writeSPI(char dat)  //Write data to SPI bus
{
    SSPBUF = dat;
    __delay_ms(1);
}

short spiDataReady() //Check whether the data is ready to read
{
    if(SSPSTATbits.BF)
        return 1;
    else
        return 0;
}

char readSPI() //REad the received data
{
    while ( !SSPSTATbits.BF );        // wait until the all bits receive
    return(SSPBUF); // read the received data from the buffer
}

unsigned short readDS3234(unsigned short address)  //Read data from RTC from the given address
{
    PORTBbits.RB1 = 0; //Enable Slave SPI RTC
    __delay_us(10);
    writeSPI(0x00 + address);
    writeSPI(0x00); //Write any dummy data to provide SPI clock to read data
    __delay_us(10);
    PORTBbits.RB1 = 1; //Disable Slave SPI RTC
    return(readSPI());
}

void writeDS3234(unsigned short address, unsigned short data)// Write data to RTC to the given address
{
    PORTBbits.RB1 = 0; //Enable Slave SPI RTC
    __delay_us(10);
    writeSPI(0x80 + address);
    writeSPI(data);
    __delay_us(10);
    PORTBbits.RB1 = 1; //Disable Slave SPI RTC
}

unsigned char BCD2UpperCh(unsigned short bcd) //Converter Upper BCD digit to Character
{
    return ((bcd >> 4) + '0');
}

unsigned char BCD2LowerCh(unsigned short bcd) //Convert Lower BCD digit to Character
{
    return ((bcd & 0x0F) + '0');
}

unsigned short Binary2BCD(unsigned short a) // Convert Binary number to BCD
{
    int t1, t2;
    t1 = a%10;
    t1 = t1 & 0x0F;
    a = a/10;
    t2 = a%10;
    t2 = 0x0F & t2;
    t2 = t2 << 4;
    t2 = 0xF0 & t2;
    t1 = t1 | t2;
    return t1;
}
 
unsigned short BCD2Binary(unsigned short a) // Convert BCD to Binary
{
    int r,t;
    t = a & 0x0F;
    r = t;
    a = 0xF0 & a;
    t = a >> 4;
    t = 0x0F & t;
    r = t*10 + r;
    return r;
}

short readKeypad()  //Scan the Keypad
{
    LATDbits.LATD3 = 1;
    __delay_us(10);
    if(PORTDbits.RD0 == 1)
    {
        while(PORTDbits.RD0 == 1);
        return 3;
    }
    else if(PORTDbits.RD1 == 1)
    {
        while(PORTDbits.RD1 == 1);
        return 2;
    }
    else if(PORTDbits.RD2 == 1)
    {
        while(PORTDbits.RD2 == 1);
        return 1;
    }
    
    LATDbits.LATD3 = 0;
    LATDbits.LATD4 = 1;
    __delay_us(10);
    
    if(PORTDbits.RD0 == 1)
    {
        while(PORTDbits.RD0 == 1);
        return 6;
    }
    else if(PORTDbits.RD1 == 1)
    {
        while(PORTDbits.RD1 == 1);
        return 5;
    }
    else if(PORTDbits.RD2 == 1)
    {
        while(PORTDbits.RD2 == 1);
        return 4;
    }
    
    LATDbits.LATD4 = 0;
    LATDbits.LATD5 = 1;
    __delay_us(10);
    
    if(PORTDbits.RD0 == 1)
    {
        while(PORTDbits.RD0 == 1);
        return 9;
    }
    else if(PORTDbits.RD1 == 1)
    {
        while(PORTDbits.RD1 == 1);
        return 8;
    }
    else if(PORTDbits.RD2 == 1)
    {
        while(PORTDbits.RD2 == 1);
        return 7;
    } 
    
    LATDbits.LATD5 = 0;
    LATDbits.LATD6 = 1;
    __delay_us(10);
    
    if(PORTDbits.RD0 == 1)
    {
        while(PORTDbits.RD0 == 1);
        return 12;
    }
    else if(PORTDbits.RD1 == 1)
    {
        while(PORTDbits.RD1 == 1);
        return 11;
    }
    else if(PORTDbits.RD2 == 1)
    {
        while(PORTDbits.RD2 == 1);
        return 10;
    }  
    LATDbits.LATD6 = 0;
    return 0;
}

char decodeCharacter(short a)  //Convert keypad value to character
{
    switch(a)
    {
        case 11 : return '0';
        case 1 : return '1';
        case 2 : return '2';
        case 3 : return '3';
        case 4 : return '4';
        case 5 : return '5';
        case 6 : return '6';
        case 7 : return '7';
        case 8 : return '8';
        case 9 : return '9';
    }
}

__interrupt() void alarm(void)   //interrupt function called when alarm triggers 
{
    if(INT0IF == 1)
    {
        bz = 3;
        writeDS3234(0x0F,0xC8);
        INT0IF = 0;
    }
}

void main(void) 
{
    unsigned short second, minute, hour, hr, day, dday, month, year, ap, m;
    unsigned short aSecond,aMinute,aHour,aHr,aAP,aTM1,aTM2;
    short kp,mt,temp;
    char t;
    char time[] = "00:00:00 PM";
    char aTime[] = "00:00:00   ";
    char date[] = "00-00-00   ";
    
    TRISD = 0x07; //First 3 pins of PORTD are input
    LATD = 0x00;
    TRISB = 0x01;// First pin ofPORTB as input
    GIE = 1; //Global Interrupt Enable
    PEIE = 1;//Peripheral Interrupt Enable
    INT0IF = 0;//Clear INT0 interrupt flag
    INTEDG0 = 0;// Set high to low transition as INT0 interrupt
    INT0IE = 1; //Enable INT0 interrupt
    
    PORTBbits.RB1 = 1;//Disable slave 
    m = 0;
    mt = 0;
    bz = 0;
    spiMasterInit();
    Lcd_Init();
    Lcd_Clear();
    aTM1 = 0;
    aTM2 = 0;
    
    while(1)
    {
        second = readDS3234(0);
        minute = readDS3234(1);
        hour = readDS3234(2); 
        hr = hour & 0b00011111; 
        ap = hour & 0b00100000;
        dday = readDS3234(3);
        day = readDS3234(4);
        month = readDS3234(5);
        year = readDS3234(6);

        time[0] = BCD2UpperCh(hr);
        time[1] = BCD2LowerCh(hr);
        time[3] = BCD2UpperCh(minute);
        time[4] = BCD2LowerCh(minute);
        time[6] = BCD2UpperCh(second);
        time[7] = BCD2LowerCh(second);
       
        if(bz)
        {
            if(aTM1 < ALMtd)
            {
                LATDbits.LATD7 = 1;//Turn on alarm
                aTM1++;
            }
            else if(aTM1 >= ALMtd && aTM2 < ALMtd)
            {
                LATDbits.LATD7 = 0;//Turn off alarm
                aTM2++;
            }
            else
            {
                aTM1 = 0;
                aTM2 = 0;
                bz--;
            }
        }
        else
           LATDbits.LATD7 = 0;//Turn off alarm 
        
        if(ap)
        {
            time[9] = 'P';
            time[10] = 'M';
        }
        else
        {
            time[9] = 'A';
            time[10] = 'M';
        }

        date[0] = BCD2UpperCh(day);   //10s digit of Date, BCD to Character
        date[1] = BCD2LowerCh(day);   //1s digit of Date, BCD to Character
        date[3] = BCD2UpperCh(month);
        date[4] = BCD2LowerCh(month);
        date[6] = BCD2UpperCh(year);
        date[7] = BCD2LowerCh(year);
        
        kp = readKeypad(); //Read Keypad
        t = 0;
        if(kp == 10)  //If * pressed
        {
            m++;
            mt = 0;
            if(m > 3)
                m = 0;
        }
        else if((kp > 0 && kp < 10) || kp == 11) //If valid key is pressed
        {
            if(m)
            {
                t = decodeCharacter(kp); //Convert Keypad to Character
                mt++;
            }
        }
        else if(kp == 12) //Exit or Alarm OFF if # pressed
        {
            m = 0;  //Exit settings
            bz = 0; //Alarm OFF
        }
        
        if(m == 0)
        { 
            Lcd_Set_Cursor(1,1);
            Lcd_Write_String("Time: ");
            Lcd_Write_String(time);
            Lcd_Set_Cursor(2,1);
            Lcd_Write_String("Date: ");
            Lcd_Write_String(date);
        }
        else if(m == 1) //Alarm Settings
        {
            aSecond = readDS3234(0x07);
            aMinute = readDS3234(0x08);
            aHour = readDS3234(0x09); 
            aHr = aHour & 0b00011111; 
            aAP = aHour & 0b00100000;
            aTime[0] = BCD2UpperCh(aHr);
            aTime[1] = BCD2LowerCh(aHr);
            aTime[3] = BCD2UpperCh(aMinute);
            aTime[4] = BCD2LowerCh(aMinute);
            aTime[6] = BCD2UpperCh(aSecond);
            aTime[7] = BCD2LowerCh(aSecond);
        
            if(aAP)
            {
                aTime[9] = 'P';
                aTime[10] = 'M';
            }
            else
            { 
                aTime[9] = 'A';
                aTime[10] = 'M';
            }

            Lcd_Set_Cursor(1,1);
            Lcd_Write_String("Set Alarm       ");
            Lcd_Set_Cursor(2,1);
            Lcd_Write_String("Time: ");
            Lcd_Write_String(aTime); 
            
            if(mt && t && kp)
            {
                if(mt == 1 && t < '2')
                {
                     aHour = BCD2Binary(aHr);
                     temp = aHour % 10;  
                     
                     aHour = (t - 48)*10 + temp;
                     aHour = Binary2BCD(aHour);
                     aHour = aHour | 0x40;
                     writeDS3234(0x09, aHour); 
                }
                else if(mt == 2)
                {
                    aHour = BCD2Binary(aHr);
                    aHour = aHour/10;  
    
                    aHour = aHour*10 + (t - 48);
                    if(aHour < 13 && aHour > 0)
                    {
                        aHour = Binary2BCD(aHour);
                        aHour = aHour | 0x40;
                        writeDS3234(0x09, aHour); 
                    }
                }
                else if(mt == 3 && t < '6')
                {
                    aMinute = BCD2Binary(aMinute);
                    temp = aMinute % 10;  
                     
                    aMinute = (t - 48)*10 + temp;
                    aMinute = Binary2BCD(aMinute);
                    writeDS3234(0x08, aMinute); 
                }    
                else if(mt == 4)
                {
                    aMinute = BCD2Binary(aMinute);
                    aMinute = aMinute/10;  
                     
                    aMinute = aMinute*10 + (t - 48);
                    if(aMinute < 60)
                    {
                        aMinute = Binary2BCD(aMinute);
                        writeDS3234(0x08, aMinute); 
                    }
                }   
                else if(mt == 5)
                {
                    aSecond = 0;
                    writeDS3234(0x07, aSecond); 
                }
                else if(mt == 6)
                {
                    aHour = readDS3234(0x09);
                    if(aAP)
                    {
                        aHour = aHour & 0b11011111;
                    }
                    else
                    {
                        aHour = aHour | 0b00100000;   
                    }
                    writeDS3234(0x09,aHour);
                    mt = 0;
                }
                writeDS3234(0x0A,0x80);
                writeDS3234(0x0F,0xC8);
                writeDS3234(0x0E,0x1D);
            }
        }
        else if(m == 2) //Time Settings
        {
            if(mt && t && kp)
            {
                if(mt == 1 && t < '2')
                {
                     hour = BCD2Binary(hr);
                     temp = hour % 10;  
                     
                     hour = (t - 48)*10 + temp;
                     hour = Binary2BCD(hour);
                     hour = hour | 0x40;
                     writeDS3234(2, hour); 
                }
                else if(mt == 2)
                {
                    hour = BCD2Binary(hr);
                    hour = hour/10;  
    
                    hour = hour*10 + (t - 48);
                    if(hour < 13 && hour > 0)
                    {
                        hour = Binary2BCD(hour);
                        hour = hour | 0x40;
                        writeDS3234(2, hour); 
                    }
                }
                else if(mt == 3 && t < '6')
                {
                    minute = BCD2Binary(minute);
                    temp = minute % 10;  
                     
                    minute = (t - 48)*10 + temp;
                    minute = Binary2BCD(minute);
                    writeDS3234(1, minute); 
                }    
                else if(mt == 4)
                {
                    minute = BCD2Binary(minute);
                    minute = minute/10;  
                     
                    minute = minute*10 + (t - 48);
                    if(minute < 60)
                    {
                        minute = Binary2BCD(minute);
                        writeDS3234(1, minute); 
                    }
                }   
                else if(mt == 5)
                {
                    second = 0;
                    writeDS3234(0, second); 
                }
                else if(mt == 6)
                {
                    hour = readDS3234(2); 
                    if(ap)
                    {
                        hour = hour & 0b11011111;
                        writeDS3234(2,hour);
                    }
                    else
                    {
                        hour = hour | 0b00100000;
                        writeDS3234(2,hour);
                    }
                    mt = 0;
                }
            }
            Lcd_Set_Cursor(1,1);
            Lcd_Write_String("Set Time           ");
            Lcd_Set_Cursor(2,1);
            Lcd_Write_String("Time: ");
            Lcd_Write_String(time);
        }
        else if(m == 3) //Date Settings
        {
            if(mt && t && kp)
            {
                if(mt == 1 && t < '4')
                {
                    day = BCD2Binary(day);
                    temp = day % 10;  
                     
                    day = (t - 48)*10 + temp;
         
                    day = Binary2BCD(day);
                    writeDS3234(4, day); 
                }
                else if(mt == 2)
                {
                    day = BCD2Binary(day);
                    day = day/10;  
                     
                    day = day*10 + (t - 48);
                    if(day < 32 && day > 0)
                    {
                        day = Binary2BCD(day);
                        writeDS3234(4, day); 
                    }
                }
                else if(mt == 3 && t < '2')
                {
                    month = BCD2Binary(month);
                    temp = month % 10;  
                     
                    month = (t - 48)*10 + temp;
   
                    month = Binary2BCD(month);
                    writeDS3234(5, month); 
                }
                else if(mt == 4)
                {
                    month = BCD2Binary(month);
                    month = month/10;  
                     
                    month = month*10 + (t - 48);
                    if(month < 13 && month > 0)
                    {
                        month = Binary2BCD(month);
                        writeDS3234(5, month);
                    }
                }
                else if(mt == 5)
                {
                    year = BCD2Binary(year);
                    temp = year % 10;  
                     
                    year = (t - 48)*10 + temp;
                    year = Binary2BCD(year);

                    writeDS3234(6, year); 
                }
                else if(mt == 6)
                {
                    year = BCD2Binary(year);
                    year = year/10;  
                     
                    year = year*10 + (t - 48);
                    year = Binary2BCD(year);

                    writeDS3234(6, year);
                }
            }
            
            Lcd_Set_Cursor(1,1);
            Lcd_Write_String("Set Date          ");
            Lcd_Set_Cursor(2,1);
            Lcd_Write_String("Date: ");
            Lcd_Write_String(date); 
        }
    }
}

I hope that you can easily understand the code as it is well commented. Please not below points before going through the program. If you still have doubts, please feel free to comment below.

All the contents in time/date registers in DS3234 are in Binary Coded Decimal (BCD) format. So we need to convert BCD to corresponding numerical characters for displaying in the LCD display. We also need to convert BCD to normal format (binary or decimal) and vice versa for all calculations like increment or decrement time/date.

Working

Working is very simple as listed below.

Setting Alarm

Setting Time

Setting Date

Output

Digital Alarm Clock using PIC Microcontroller and DS3234 RTC – Proteus Tool – Practical Implementation

Download Here

You can download complete project files here including MPLAB project, Proteus and hex file.