You are on page 1of 6

Digital Clock using DS1307 with PIC Microcontroller

http://www.electrosome.com/digital-clock-pic-microcontroller-ds1307/ Username: anowar.mieb26234@gmail.com Password: SAdzCnAOD9YB

A Digital Clock can be made easily by using PIC Microcontroller, DS1307 and a 16*2 LCD. I have already posted about Interfacing DS1307 RTC with PIC Microcontroller. The DS1307 RTC can work either in 24-hour mode or 12-hour mode with AM/PM indicator. It automatically adjusts for months fewer than 31 days including leap year compensation up to year 2100. DS1307 comes with built-in power sensing circuit which senses power failures and automatically switches to back up supply. We can provide a 3V CMOS Battery for that. Communication between PIC Microcontroller and DS1307 takes place through I²C Bus.

Circuit Diagram:
Note: VDD , VSS of the Pic Microcontroller and VCC , GND of DS1307 are not shown in the circuit diagram. VDD, VCC should be connected to +5V and VSS, GND to OV as marked in the circuit diagram. To simulate this project in Proteus you may need to connect I2C Debugger. SCL and SDA of I2C Debugger should be connected in parallel to SCL and SDA of DS1307. I2C Debugger can be found where CRO can be found in Proteus. You can download the MikroC Source Code and Proteus Files etc at the end of this article. Here I explains the Source Code and different functions used in it. The Three points to be noted while editing or creating program for this project: • DS1307 RTC is fully Binary Coded Decimal (BCD) clock/calender. So the data read from DS1307 should be converted to required format according to our needs and data to be written to DS1307 should be in BCD format. • Library for Interfacing LCD With PIC Microcontroller of MikroC needs Character or String Data. So data to be displayed in the LCD Screen should be converted to Character. • Addition and Subtraction cannot be directly applied on BCD. Here I am first convert BCD to Binary. Then addition and subtraction can be simply applied on Binary. Then the Binary is converted back to BCD. Functions that are used for reading and writing data from DS1307 are explained in the article Interfacing DS1307 with PIC Microcontroller please refer it. BCD2UpperCh() and BCD2LowerCh() are the two functions used to convert BCD to Character.
Hour, Minute, Second, Date, Month and Year data are stored in DS1307 in separate 8-bit registers in BCD format.

We read the data of these registers to access time/date. BCD2UpperCh() converts most significant 4 bits to corresponding character and BCD2LowerCh() converts least significant 4 bits to corresponding character. The BCD2Binary() converts the BCD data read from the RTC to corresponding Binary for addition or subtraction and Binary2BCD converts the Binary back to BCD. Bit 6 of Hour register is defined as the 24-hour or 12-hour mode selection bit. When this bit is made high, 12hour mode is selected and Bit 5 will represent AM/PM (Logic High represents PM).

t2. } void write_ds1307(unsigned short address. // send byte (address of DS1307 location) I2C1_Wr(w_data).unsigned short w_data) { I2C1_Start(). sbit LCD_D4 at RB4_bit. sbit LCD_D7_Direction at TRISB7_bit. 1 for read) 0x68 followed by 0 --> 0xD0 I2C1_Wr(address). } unsigned char BCD2LowerCh(unsigned char bcd) { return ((bcd & 0x0F) + '0'). I2C1_Repeated_Start(). sbit LCD_D4_Direction at TRISB4_bit. I2C1_Stop(). sbit LCD_D7 at RB7_bit. } int Binary2BCD(int a) { int t1. 1 for read) 0x68 followed by 0 --> 0xD0 I2C1_Wr(0xD0). I2C1_Wr(0xD0). t1 = a%10. I2C1_Wr(0xD1). // End LCD module connections unsigned short read_ds1307(unsigned short address) { unsigned short r_data. sbit LCD_RS_Direction at TRISB2_bit. sbit LCD_D6_Direction at TRISB6_bit. return(r_data). sbit LCD_EN at RB3_bit. // send data (data to be written) I2C1_Stop(). // issue I2C start signal //address 0x68 followed by direction bit (0 for write. // issue I2C stop signal } unsigned char BCD2UpperCh(unsigned char bcd) { return ((bcd >> 4) + '0'). //address 0x68 followed by direction bit (0 for write. . sbit LCD_EN_Direction at TRISB3_bit. sbit LCD_D6 at RB6_bit. //0x68 followed by 1 --> 0xD1 r_data=I2C1_Rd(0).Code: // LCD module connections sbit LCD_RS at RB2_bit. I2C1_Start(). sbit LCD_D5_Direction at TRISB5_bit. sbit LCD_D5 at RB5_bit. // send byte via I2C (device address + W) I2C1_Wr(address).

unsigned short set_count = 0. t2 = 0xF0 & t2. int day. t1 = t1 | t2."Time:"). int hr. int ap. char time[] = "00:00:00 PM". int dday. . //DS1307 I2C is running at 100KHz CMCON = 0x07. short set. return r. t2 = a%10. // To turn off analog to digital converters TRISA = 0x07. PORTA = 0x00. t = a >> 4. t2 = 0x0F & t2. a = a/10. } int BCD2Binary(int a) { int r. int hour. int year. return t1. void main() { I2C1_Init(100000). // To turn off comparators ADCON1 = 0x06. // Initialize LCD Lcd_Cmd(_LCD_CLEAR). int minute. int month. // Clear display Lcd_Cmd(_LCD_CURSOR_OFF). t = a & 0x0F. t2 = t2 << 4. Lcd_Init().t.1. r = t. a = 0xF0 & a.t1 = t1 & 0x0F. r = t*10 + r. char date[] = "00-00-00". // Cursor off Lcd_out(1. t = 0x0F & t. } int second.

F0 == 0) { set_count++."Date:"). if((hour & 0x1F) >= 0x13) { hour = hour & 0b11100001. } } } if(set_count) { if(PORTA. if(PORTA.F2 == 0) { Delay_ms(100). } if(PORTA.F1 == 0) { Delay_ms(100). hour = Binary2BCD(hour). } else if((hour & 0x1F) <= 0x00) { hour = hour | 0b00010010. minute = minute + set. } write_ds1307(2.1. //write hour break.Lcd_out(2. hour = hour + set. if(PORTA. if(PORTA. do { set = 0. if(set_count >= 7) { set_count = 0. hour = hour ^ 0x20.F1 == 0) set = 1. hour = hour ^ 0x20.F2 == 0) set = -1.F0 == 0) { Delay_ms(100). } if(set_count && set) { switch(set_count) { case 1: hour = BCD2Binary(hour). if(PORTA. hour). case 2: minute = BCD2Binary(minute). .

day).0x00). minute = read_ds1307(1). // write date 17 break. hour = read_ds1307(2). if(month > 0x12) month = 1. minute). and start Oscillator break. month = Binary2BCD(month). if(day >= 0x32) day = 1. case 3: if(abs(set)) write_ds1307(0. // write month 6 June break.if(minute >= 60) minute = 0. ap = hour & 0b00100000. case 5: month = BCD2Binary(month). } } } second = read_ds1307(0). month = month + set. if(month <= 0) month = 0x12. day = Binary2BCD(day). year = read_ds1307(6). hr = hour & 0b00011111. //write min break. dday = read_ds1307(3). write_ds1307(5. if(minute < 0) minute = 59. year = year + set. //Reset second to 0 sec. day = day + set. if(year >= 0x50) year = 0. minute = Binary2BCD(minute). write_ds1307(6. month = read_ds1307(5).month). case 6: year = BCD2Binary(year). year = Binary2BCD(year). // write year break. day = read_ds1307(4). write_ds1307(4. case 4: day = BCD2Binary(day). if(day <= 0) day = 0x31. year). write_ds1307(1. . if(year <= -1) year = 0x99.

date[7] = BCD2LowerCh(year). time[4] = BCD2LowerCh(minute). date[0] = BCD2UpperCh(day). if(ap) { time[9] = 'P'. } else { time[9] = 'A'. date[4] = BCD2LowerCh(month). time[3] = BCD2UpperCh(minute). time[10] = 'M'. }while(1). time). time[10] = 'M'. } Lcd_out(1. date). time[1] = BCD2LowerCh(hr). time[7] = BCD2LowerCh(second). date[1] = BCD2LowerCh(day). } . time[6] = BCD2UpperCh(second). Delay_ms(50). Lcd_out(2. date[3] = BCD2UpperCh(month). 6.time[0] = BCD2UpperCh(hr). date[6] = BCD2UpperCh(year). 6.