DS1307 is a popular Real Time Clock (RTC) chip from MAXIM . Now, PIC16F877A is my favorite microcontroller. So, I was looking for information about interfacing DS1307 with PIC16F877A but I found only information in assembly language (assembly is not my cup of tea) and other C compilers. I use only mikroC. I adapted what I have found from the Internet. The source code is listed below:
//Sample code for
//DS1307 RTC Ineterfacing with PIC16F877A
//Coded by Pynn Pynn
//Compiler: mikroC 8.0.0
//http://picnote.blogspot.com
//07/06/2008
//Use with your own risk
unsigned short read_ds1307(unsigned short address );
unsigned short sec;
unsigned short minute;
unsigned short hour;
unsigned short day;
unsigned short date;
unsigned short month;
unsigned short year;
unsigned short data;
char time[9];
char ddate[11];
unsigned char BCD2UpperCh(unsigned char bcd);
unsigned char BCD2LowerCh(unsigned char bcd);
void main(){
I2C_Init(100000); //DS1307 I2C is running at 100KHzPORTB = 0;
TRISB = 0; // Configure PORTB as output
TRISC = 0xFF;
Lcd_Init(&PORTB); // Initialize LCD connected to PORTBLcd_Cmd(Lcd_CLEAR); // Clear displayLcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor offLcd_Out(1, 1, "TIME:");
Lcd_Out(2, 1, "DATE:");
while(1)
{
sec=read_ds1307(0); // read secondminute=read_ds1307(1); // read minutehour=read_ds1307(2); // read hourday=read_ds1307(3); // read daydate=read_ds1307(4); // read datemonth=read_ds1307(5); // read monthyear=read_ds1307(6); // read year
time[0] = BCD2UpperCh(hour);
time[1] = BCD2LowerCh(hour);
time[2] = ':';
time[3] = BCD2UpperCh(minute);
time[4] = BCD2LowerCh(minute);
time[5] = ':';
time[6] = BCD2UpperCh(sec);
time[7] = BCD2LowerCh(sec);
time[8] = '\0';
ddate[0] = BCD2UpperCh(date);
ddate[1] = BCD2LowerCh(date);
ddate[2] ='/';
ddate[3] = BCD2UpperCh(month);
ddate[4] = BCD2LowerCh(month);
ddate[5] ='/';
ddate[6] = '2';
ddate[7] = '0';
ddate[8] = BCD2UpperCh(year);
ddate[9] = BCD2LowerCh(year);
ddate[10] = '\0';
Lcd_Out(1,6,time);
Lcd_Out(2,6,ddate);
Delay_ms(500);
}
}
unsigned short read_ds1307(unsigned short address)
{
I2C_Start();
I2C_Wr(0xd0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0I2C_Wr(address);
I2C_Repeated_Start();
I2C_Wr(0xd1); //0x68 followed by 1 --> 0xD1
data=I2C_Rd(0);
I2C_Stop();
return(data);
}
unsigned char BCD2UpperCh(unsigned char bcd)
{
return ((bcd >> 4) + '0');
}
unsigned char BCD2LowerCh(unsigned char bcd)
{
return ((bcd & 0x0F) + '0');
}
As I don't have DS1307 in hand, so I test my code with Proteus ISIS simulator. The image shows the working clock. Click on the image for big image.
//Sample code for
//DS1307 RTC Ineterfacing with PIC16F877A
//Coded by Pynn Pynn
//Compiler: mikroC 8.0.0
//http://picnote.blogspot.com
//07/06/2008
//Use with your own risk
unsigned short read_ds1307(unsigned short address );
unsigned short sec;
unsigned short minute;
unsigned short hour;
unsigned short day;
unsigned short date;
unsigned short month;
unsigned short year;
unsigned short data;
char time[9];
char ddate[11];
unsigned char BCD2UpperCh(unsigned char bcd);
unsigned char BCD2LowerCh(unsigned char bcd);
void main(){
I2C_Init(100000); //DS1307 I2C is running at 100KHzPORTB = 0;
TRISB = 0; // Configure PORTB as output
TRISC = 0xFF;
Lcd_Init(&PORTB); // Initialize LCD connected to PORTBLcd_Cmd(Lcd_CLEAR); // Clear displayLcd_Cmd(Lcd_CURSOR_OFF); // Turn cursor offLcd_Out(1, 1, "TIME:");
Lcd_Out(2, 1, "DATE:");
while(1)
{
sec=read_ds1307(0); // read secondminute=read_ds1307(1); // read minutehour=read_ds1307(2); // read hourday=read_ds1307(3); // read daydate=read_ds1307(4); // read datemonth=read_ds1307(5); // read monthyear=read_ds1307(6); // read year
time[0] = BCD2UpperCh(hour);
time[1] = BCD2LowerCh(hour);
time[2] = ':';
time[3] = BCD2UpperCh(minute);
time[4] = BCD2LowerCh(minute);
time[5] = ':';
time[6] = BCD2UpperCh(sec);
time[7] = BCD2LowerCh(sec);
time[8] = '\0';
ddate[0] = BCD2UpperCh(date);
ddate[1] = BCD2LowerCh(date);
ddate[2] ='/';
ddate[3] = BCD2UpperCh(month);
ddate[4] = BCD2LowerCh(month);
ddate[5] ='/';
ddate[6] = '2';
ddate[7] = '0';
ddate[8] = BCD2UpperCh(year);
ddate[9] = BCD2LowerCh(year);
ddate[10] = '\0';
Lcd_Out(1,6,time);
Lcd_Out(2,6,ddate);
Delay_ms(500);
}
}
unsigned short read_ds1307(unsigned short address)
{
I2C_Start();
I2C_Wr(0xd0); //address 0x68 followed by direction bit (0 for write, 1 for read) 0x68 followed by 0 --> 0xD0I2C_Wr(address);
I2C_Repeated_Start();
I2C_Wr(0xd1); //0x68 followed by 1 --> 0xD1
data=I2C_Rd(0);
I2C_Stop();
return(data);
}
unsigned char BCD2UpperCh(unsigned char bcd)
{
return ((bcd >> 4) + '0');
}
unsigned char BCD2LowerCh(unsigned char bcd)
{
return ((bcd & 0x0F) + '0');
}
As I don't have DS1307 in hand, so I test my code with Proteus ISIS simulator. The image shows the working clock. Click on the image for big image.