Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

RTC DS1307 Backup battery

Status
Not open for further replies.

micropad

Member
Dear All,

I wrote a program to read DS1307 and put the result on the LCD using PIC16f877a via I2C protocol. It is working properly and I connected backup battery also. only problem is when I removed the main power the RTC does not update, and it is counting only five seconds when remove the main power

Please Advice
 
Dear All,

I wrote a program to read DS1307 and put the result on the LCD using PIC16f877a via I2C protocol. It is working properly and I connected backup battery also. only problem is when I removed the main power the RTC does not update, and it is counting only five seconds when remove the main power

Please Advice

Hi,
What are the details of the back up battery.?
 
Dear ericgibbs
Thank you so much for reply

Details of back up battery

CR2030 3v directly connected to Vbat pin and GND

Please help
 
That battery should be OK, are you sure its still in good condition at around 3V when its powering the DS1307.??

Does it still measure 3V when the main power is off.??

The problem maybe in your program.? If you post it, we could look it over.
 
Dear ericgibbs,
Thanks for the reply

battery voltage is correct and I replaced new battery too and thanks your advice

Now i am out of my home computer, therefore I will update source code when i reach home
Thanks in advance
 
Dear ericgbbs,

Please find the source codes for TRC reading
Code:
#include <htc.h>
#define _XTAL_FREQ 4000000 // 4 MHz clock 
__CONFIG(0X3F39);
#define LCD_EN RB0
#define	LCD_RS RB1
#define	LCD_RW RB4
#define LCD_DATA	PORTD
#define	LCD_STROBE  LCD_EN = 1; __delay_ms(1); LCD_EN=0;
unsigned char time [6] = {"Time:"};
unsigned char date [6] = {"Date:"};
unsigned char I2CData[]= {0x00,0x01,0x40,0x03,0x04,0x05,0x06,0x07};
unsigned I2CInitval  []= {0x57,0x59,0x8,0x29,0x29,0x20,0x12,0x20};
unsigned char tmp;
unsigned char i;

void I2CWait(){
        while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );		/* wait for any pending transfer */

}

void I2CInit(void){
        TRISC3 = 1;      	/* SDA and SCL as input pin */
        TRISC4 = 1;      	/* these pins can be configured either i/p or o/p */
        SSPSTAT |= 0x80; 	/* Slew rate disabled */
        SSPCON = 0x28;   	/* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
        SSPADD = 0x28;    	/* 100Khz @ 4Mhz Fosc */
}

void I2CStart(){
		I2CWait(); 
        SEN = 1;         	
        while(SEN);      	
                    	
}

void I2CStop(){
        PEN = 1;         	/* Stop condition enabled */
        while(PEN);      	/* Wait for stop condition to finish */
                     		/* PEN automatically cleared by hardware */
}

void I2CRestart(){
        RSEN = 1;        	/* Repeated start enabled */
        while(RSEN);     	/* wait for condition to finish */
}

void I2CAck(){
        ACKDT = 0;       	/* Acknowledge data bit, 0 = ACK */
        ACKEN = 1;       	/* Ack data enabled */
        while(ACKEN);    	/* wait for ack data to send on bus */
}

void I2CNak(){
        ACKDT = 1;       			/* Acknowledge data bit, 1 = NAK */
        ACKEN = 1;       			/* Ack data enabled */
        while(ACKEN);    			/* wait for ack data to send on bus */
}



void I2CSend(unsigned char dat){
	
        SSPBUF = dat;    			/* Move data to SSPBUF */
        while(BF);       			/* wait till complete data is sent from buffer */
        I2CWait();       			/* wait for any pending transfer */
}

unsigned char I2CRead(void){
        unsigned char temp;
		I2CWait(); 					/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        			/* Enable data reception */
        while(!BF);      			/* wait for buffer full */
        temp = SSPBUF;   			/* Read serial buffer and store in temp register */
        	     					/* wait to check any pending transfer */	     
}

void lcddata(unsigned char value)
	{
LCD_RS = 1; 
LCD_DATA= (value&0xf0);
LCD_STROBE;
LCD_DATA = ((value<<4)&0xf0);
LCD_STROBE;
__delay_ms(10);
	}

void lcdcmd(unsigned char value)
	{
LCD_RS = 0;
LCD_DATA= (value&0xf0);
LCD_STROBE;
LCD_DATA = ((value<<4)&0xf0);
LCD_STROBE;
__delay_ms(10);
	}
void bcdToascii(unsigned char value){

	tmp = value;
	tmp = tmp & 0xf0;
	tmp = tmp >> 4;
	tmp = tmp | 0x30;
	lcddata(tmp);
	tmp = value;
	tmp = tmp & 0x0f;
	tmp = tmp | 0x30;
	lcddata(tmp);

}

void display (){
lcdcmd(0x80);
for (char i=0;i<5;i++)
			{
		lcddata(time[i]);
			}
	bcdToascii(I2CData[2]);
	lcddata('-');
	bcdToascii(I2CData[1]);
	lcddata('-');
	bcdToascii(I2CData[0]);
	
	lcdcmd(0xc0);
for (char j=0;j<5;j++)
			{
		lcddata(date[j]);
			}
	bcdToascii(I2CData[3]);
	lcddata('-');
	bcdToascii(I2CData[4]);
	lcddata('-');	
	bcdToascii(I2CData[5]);
	bcdToascii(I2CData[6]);
}
void lcd_init(){

TRISD	= 0;
TRISB	= 0;
TRISC6  = 0;
TRISC5  = 0;
LCD_EN =0;
 __delay_us(10);  
	LCD_DATA =0X30;
     	LCD_STROBE;
       	__delay_ms(2);

       LCD_RS=0;
       __delay_us(10);  
	LCD_DATA =0X30;
     	LCD_STROBE;
	__delay_ms(2);

        LCD_RS=0;
       __delay_us(10);  
	LCD_DATA =0X30;
       	LCD_STROBE;
	__delay_ms(2);

       LCD_RS=0;
       __delay_us(10);  
	LCD_DATA =0X20;
     	LCD_STROBE;
	__delay_ms(2);

lcdcmd(0x28);
__delay_ms(15);
lcdcmd(0x01);
__delay_ms(10);
lcdcmd(0x06);
__delay_ms(10);
lcdcmd(0x80);
__delay_ms(10);
lcdcmd(0x0c);
__delay_ms(10);
				}


void I2Cwrite(){
												/* Initialize I2C Port */
 		I2CStart();								/* Send Start condition */
        I2CSend(0xD0);							/* Send DS1307 slave address with write operation */
        I2CSend(0x00);							/* Send subaddress 0x00, we are writing to this location */
			for(i=0;i<8;i++) {					/* Loop to write 8 bytes */
            	I2CSend(I2CInitval[i]);							/* send I2C data one by one */			
        }
			I2CStop();							/* Send a stop condition - as transfer finishes */
}

void I2Cread(){
		for(i=0;i<8;i++){
        I2CStart();
		I2CSend(0xD0);							/* Send slave address with write */ /* Send address for dummy write operation *//* this address is actually where we are going to read from */					       						       
        I2CSend(0x00);							/* Send a repeated start, after a dummy write to start reading */
        I2CRestart();
        I2CSend(0xD1);							/* send slave address with read bit set */
  
			//	for(i=0;i<8;i++) {
      			I2CData[i] = I2CRead();			/* read a byte */								/* ACK if its not the last byte to read */             	 
				
        }
		 	I2CStop();							/* Send stop */
}

void main(){        
        I2CInit();
        lcd_init();       
		I2Cwrite();
		
while(1){
		
        I2Cread();			
		display();
	
}
}

Please advice
 
Last edited:
The I2Cread(); function isn't reading the RTC properly.

C:
void I2Cread()
	{
        I2CStart();
		I2CSend(0xD0);							/* Send slave address with write */ /* Send address for dummy write operation *//* this address is actually where we are going to read from */					       						       
        I2CSend(0x00);							/* Send a repeated start, after a dummy write to start reading */
        I2CRestart();
        I2CSend(0xD1);							/* send slave address with read bit set */
 
		for(i=0;i<7;i++) 
			{
      			I2CData[i] = I2CRead();			/* read a byte */								/* ACK if its not the last byte to read */             	 
 				I2CAck();
        	}
		I2CData[i] = I2CRead();	
		I2CNak();
	 	I2CStop();							/* Send stop */
	}

The read RTC routine should be like this...

Also... I forgot to mention this routine doesn't return the value as temp isn't used in the main function
C:
unsigned char I2CRead(void){
        unsigned char temp;
	I2CWait(); 					/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        			/* Enable data reception */
        while(!BF);      			/* wait for buffer full */
        temp = SSPBUF;   			/* Read serial buffer and store in temp register */
        	     					/* wait to check any pending transfer */	     
}

Change to.
C:
unsigned char I2CRead(void){
        I2CWait(); 					/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        			/* Enable data reception */
        while(!BF);      			/* wait for buffer full */
        return SSPBUF;   			/* Read serial buffer and store in temp register */
        	     					/* wait to check any pending transfer */	     
}
 
Last edited:
Dear Rojers,

Thank you so much for help

It is stranger, my program now working base on your advice. I changed the code as you advised. can you please explain this strange. I can not understand the theory behind this

Thanks in advance
 
First... When reading consecutive addresses from a I2C device you send an Ack to the device to initiate another read... When 7 values have been read, read the last value and end with a Nack to signal you are done reading... If you look at my C tutorial (based on Nigel's asm tutorials)... Tutorial 6_7. You'll find a generic read.. single, multiple and string. This will give you an idea of how this works.

Also I forgot to mention... You MUST place a 10 -- 20mS delay after the write ( chip housekeeping ) or the write will fail..
 
Dear Rogers,

Thank you so much for the reply, I need another help, now my program is working accurately, until main power is there( I checked 5 Hours ). then I removed main power and checked with it battery backup (about 10 hours )
unfortunately it was lagging around 40Minute. please advice on this

Thanks in advance
 
Dear Rogers,

Thank you so much for the reply, I need another help, now my program is working accurately, until main power is there( I checked 5 Hours ). then I removed main power and checked with it battery backup (about 10 hours )
unfortunately it was lagging around 40Minute. please advice on this

Thanks in advance
 
Last edited:
Dear Rogers,

when I use main power, It is working without lagging. only lagging effects without main power.
Therefore is it possible issue with clock crystal


Please advice
 
Last edited:
Dear Rogers,

Thanks for the reply
I need a another fever, hopes you will help on this.

As per my program. First I write some values to RTC, then I started read. As I know, It can not read without write to the RTC. So my problem is, every time I insert the main power, It is starting read where it wrote from. What I need is, it should continue without changing time even with main power or without main power.

Please advice
Thanks in advance
 
I don't understand the problem.... If you need a variable to remember where you are when power is off. when you write to the clock, add a small line of code that writes to the non volatile SRAM that is on the DS1307... There is 56 bytes of memory that can be used to keep some tracking variable.. ( its better than using internal EEprom )
 
Dear Rogers,
Thanks for the reply



Code:
unsigned I2CInitval  []= {0x57,0x59,0x8,0x29,0x29,0x20,0x12,0x20};

void I2Cwrite(){
												/* Initialize I2C Port */
 		I2CStart();								/* Send Start condition */
        I2CSend(0xD0);							/* Send DS1307 slave address with write operation */
        I2CSend(0x00);							/* Send subaddress 0x00, we are writing to this location */
			for(i=0;i<8;i++) {					/* Loop to write 8 bytes */
            	I2CSend(I2CInitval[i]);							/* send I2C data one by one */			
        }
			I2CStop();							/* Send a stop condition - as transfer finishes */
}

The above program code from my program. It writes to the RTC. So when I insert the main power or reset the PIC(MCLR), it is writing array value with out considering current time

Dear Rogers Hope you understand my problem
my problem will be solve, if we can directly read the RTC without write to it

every time we insert the main power or press reset (MCLR) PIC starts from zero vector, then execute write program in above then it change current time that is the problem i have to ignore

Please help
 
Last edited:
From post #9
Also I forgot to mention... You MUST place a 10 -- 20mS delay after the write ( chip housekeeping ) or the write will fail..

Code:
void I2Cwrite(){
												/* Initialize I2C Port */
 	I2CStart();								/* Send Start condition */
        I2CSend(0xD0);							/* Send DS1307 slave address with write operation */
        I2CSend(0x00);							/* Send subaddress 0x00, we are writing to this location */
	for(i=0;i<8;i++) {					    /* Loop to write 8 bytes */
            	I2CSend(I2CInitval[i]);	
                __delay_ms(10);						/* send I2C data one by one */			
        }
	I2CStop();							/* Send a stop condition - as transfer finishes */
}


Is this what you're talking about? Or something else...... If this code is running this every time you boot up, then you need a time changing routine.
OR... If you never need to tamper again...

Write the time to the DS1307 from a programmer to locations 0 to 8
and leave the routine out...
 
Last edited:
Dear Rogers ,
Thanks a lot for the reply and advice
I did it before write this thread, so it is working fine until backup battery there. Only thing is when we remove the backup battery, system never run, then we have to active the routine and reprogram the PIC. can I have the solution on the same

Please advice
Thanks in advnce
 
I'm really not sure what it is you need... The system hasn't got an interface? If you remove the back up battery, you can't set the time?

I really can't suggest a way to keep the time when the backup battery is removed... Most people just specify that when the backup battery is removed, the power MUST be on...
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top