Saturday, December 19, 2015

Digital Real Time Clock using PIC12F1822 and DS1307




Interface PIC12F1822 with DS1307

A digital clock can be made using PIC12F1822 and DS1307, the DS1307 is a small integrated circuit which has 8 pins, it uses I2C protocol to communicate with master device (µP, µC ...).
The DS1307 can save time and date and uses battery to keep the time correct when the entire system is off for example when the electricity goes off.
The following two topics show how to read/write data from/to the DS1307.

Write Data to DS1307 Real Time Clock

This topic shows how to use the DS1307 and PIC12F1822 to build a real time clock with full adjustment of clock and calendar.
The microcontroller PIC12F1822 has a built in I2C module with SCL on RA1 and SDA on RA2. 
Time and calendar are displayed on 1602 LCD, this LCD is connected to a shift register to make a 2-wire serial LCD. The shift register can be 74HC595, 74HC164, CD4094 or any other compatible type.
The interfacing of the LCD display with the microcontroller uses 2-wire serial LCD MikroC library which is described on the following topic: 

2-Wire LCD MikroC Library

Interface PIC12F1822 with DS1307 Circuit diagram:
Internal oscillator of the microcontroller is used (32MHz) and MCLR pin function is disabled.

real time clock ds1307 pic12f1822 mikroc

real time clock ds1307 pic12f1822 adjust buttons mikroc

DS1307 and PIC12F1822 interfacing mikroC code:

 // Interfacing DS1307 with PIC12F1822
 // Serial LCD library must be installed
 // Written by: BENCHEROUDA Okba
 // electronnote@gmail.com
 // http://elecnote.blogspot.com/
 // Internal oscillator used @ 32MHz
 // Use at your own risk

   // LCD module connections
 sbit Serial_LCD_DATA at RA4_bit;
 sbit Serial_LCD_CLK at RA5_bit;
 sbit Serial_LCD_DATA_Direction at TRISA4_bit;
 sbit Serial_LCD_CLK_Direction at TRISA5_bit;
  // End LCD module connections
 unsigned char second, second10, minute, minute10,
               hour, hour10, date, date10, month, month10,
               year, year10, day, i = 0;

 void display(){
   //Split data into two parts
   second10  =  (second & 0x70) >> 4;
   second = second & 0x0F;
   minute10  =  (minute & 0x70) >> 4;
   minute = minute & 0x0F;
   hour10  =  (hour & 0x30) >> 4;
   hour = hour & 0x0F;
   date10  =  (date & 0x30) >> 4;
   date = date & 0x0F;
   month10  =  (month & 0x10) >> 4;
   month = month & 0x0F;
   year10  =  (year & 0xF0) >> 4;
   year = year & 0x0F;
   //Display Time
   Serial_Lcd_Chr(1, 13, second + 48);
   Serial_Lcd_Chr(1, 12, second10 + 48);
   Serial_Lcd_Chr(1, 10, minute + 48);
   Serial_Lcd_Chr(1, 9, minute10 + 48);
   Serial_Lcd_Chr(1, 7, hour + 48);
   Serial_Lcd_Chr(1, 6, hour10 + 48);
   //Display calendar
   Serial_Lcd_Chr(2, 7, date + 48);
   Serial_Lcd_Chr(2, 6, date10 + 48);
   Serial_Lcd_Chr(2, 10, month + 48);
   Serial_Lcd_Chr(2, 9, month10 + 48);
   Serial_Lcd_Chr(2, 15, year + 48);
   Serial_Lcd_Chr(2, 14, year10 + 48);
   }
 void write_value(char address, char data_){
   I2C1_Start();
   I2C1_Wr(0xD0);
   I2C1_Wr(address);
   I2C1_Wr(data_);
   I2C1_Stop();
   }
 void main() {
   OSCCON = 0xF0; // Internal oscillator 8MHz and PLL enabled (gives 32MHz)
   ANSELA = 0;    // All I/O pins are configured as digital
   ADCON0 = 0;    // Disable ADC module
   PORTA = 0;     // Initial value of port A bits
   TRISA = 9;     // RA3 & RA0 are inputs
   OPTION_REG = 0;
   WPUA = 9;     // Enable RA3 & RA0 pull-up resistors
   Serial_Lcd_Init();                 // LCD display initialization
   Serial_Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
   Serial_Lcd_Cmd(_LCD_CLEAR);             // clear LCD
   I2C1_Init(100000);         // initialize I2C at 100KHz
   return_:
   Serial_Lcd_Out(1, 1, "TIME:  :  :");
   Serial_Lcd_Out(2, 1, "DATE:  /  /20");
   write_value(0, 0);   //Reset seconds and start oscillator
   while(1){
     while(i == 1){
       Serial_Lcd_Cmd(_LCD_CLEAR);
       Serial_Lcd_Out(1, 6, "Minute:");
       minute = minute + minute10 * 10;
       while(i == 1){
         if (Button(&PORTA, 0, 100, 0)) i++;
         if(i!=1){
           minute = ((minute/10) << 4) + (minute % 10);
           write_value( 1 , minute);
           }
         if (Button(&PORTA, 3, 100, 0)) minute++;
         if (minute > 59) minute = 0;
         Serial_Lcd_Chr(2, 8, (minute/10) + 48);
         Serial_Lcd_Chr(2, 9, (minute % 10) + 48);
         }
       }
     while(i == 2){ Serial_Lcd_Cmd(_LCD_CLEAR);
       Serial_Lcd_Out(1, 6, "Hour:");
       hour = hour + hour10 * 10;
       while(i == 2){
         if (Button(&PORTA, 0, 100, 0)) i++;
         if(i!=2){
           hour = ((hour/10) << 4) + (hour % 10);
           write_value( 2 , hour);
           }
         if (Button(&PORTA, 3, 100, 0)) hour++;
         if (hour > 23) hour = 0;
         Serial_Lcd_Chr(2, 8, (hour/10) + 48);
         Serial_Lcd_Chr(2, 9, (hour % 10) + 48);
         }
       }
     while(i == 3){ Serial_Lcd_Cmd(_LCD_CLEAR);
       Serial_Lcd_Out(1, 6, "Date:");
       date = date + date10 * 10;
       while(i == 3){
         if (Button(&PORTA, 0, 100, 0)) i++;
         if(i!=3){
           date = ((date/10) << 4) + (date % 10);
           write_value( 4 , date);
           }
         if (Button(&PORTA, 3, 100, 0)) date++;
         if (date > 31) date = 1;
         Serial_Lcd_Chr(2, 8, (date/10) + 48);
         Serial_Lcd_Chr(2, 9, (date % 10) + 48);
         }
       }
     while(i == 4){ Serial_Lcd_Cmd(_LCD_CLEAR);
       Serial_Lcd_Out(1, 6, "Month:");
       month = month + month10 * 10;
       while(i == 4){
         if (Button(&PORTA, 0, 100, 0)) i++;
         if(i!=4){
           month = ((month/10) << 4) + (month % 10);
           write_value( 5 , month);
           }
         if (Button(&PORTA, 3, 100, 0)) month++;
         if (month > 12) month = 1;
         Serial_Lcd_Chr(2, 8, (month/10) + 48);
         Serial_Lcd_Chr(2, 9, (month % 10) + 48);
         }
       }
     if(i == 5){
       Serial_Lcd_Cmd(_LCD_CLEAR);
       Serial_Lcd_Out(1, 6, "Year:");
       year = year + year10 * 10;
       while(1){
         if (Button(&PORTA, 0, 100, 0))  i = 0;
         if(i!=5){
           year = ((year/10) << 4) + (year % 10);
           write_value( 6 , year);
           goto return_;
           }
         if (Button(&PORTA, 3, 100, 0)) year++;
         if (year > 99) year = 0;
         Serial_Lcd_Chr(2, 7, 2 + 48);
         Serial_Lcd_Chr(2, 8, 0 + 48);
         Serial_Lcd_Chr(2, 9, (year/10) + 48);
         Serial_Lcd_Chr(2, 10, (year % 10) + 48);
         }
       }
     if (Button(&PORTA, 0, 100, 0)) i++;
     I2C1_Start();
     I2C1_Wr(0xD0);
     I2C1_Wr(0);
     I2C1_Repeated_Start();
     I2C1_Wr(0xD1);
     second =I2C1_Rd(1);
     minute =I2C1_Rd(1);
     hour =I2C1_Rd(1);
     day =I2C1_Rd(1);
     date =I2C1_Rd(1);
     month =I2C1_Rd(1);
     year =I2C1_Rd(0);
     I2C1_Stop();
     display();
     }
   }

Digital Real Time Clock using PIC12F1822 and DS1307 video:
The following video shows hardware circuit for this project and there are some other details: