No response from Atmega328 with DS1307 RTC Chip

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I have this DS1307 chip and I was wondering if I can make a nice clock displayed on LCD. But it seems that it does not return anything. Here is the code I have used below. While debugging, I found that the program stops in "i2c_read" function at while(!(TWCR & (1 << TWINT))); and does not execute it.

 

My doubt is if something is wrong in the DS1307 chip. I do not have another space chip to test. But in any case, can anyone identify if there is something wrong with this code?

 

/*!
 * ************** ...- . . .-. --- -... --- - *************
 * Interfacing DS1307 RTC IC with Atmega328 uC
 * ************** ...- . . .-. --- -... --- - *************
 */
#include <avr/io.h>
#include "lcd.h"

void i2c_init(void){
    TWSR=0x00;
    TWBR=0x47;
    TWCR=0x04;
}

void i2c_start(void)
{
    TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while(!(TWCR & (1 << TWINT)));
}

void i2c_write(unsigned char data)
{
    TWDR=data;
    TWCR=(1<<TWINT)|(1<<TWEN);
    while(!(TWCR & (1 << TWINT)));
}

unsigned char i2c_read(unsigned char ackVal)
{
    TWCR=(1<<TWINT)|(1<<TWEN)|(ackVal<<TWEA);
    while(!(TWCR & (1 << TWINT)));             // Stops here. does not cross this line while debugging :(
    return TWDR;
}

void i2c_stop()
{
    TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

void rtc_init(){
    i2c_init();			// Initialize i2c module
    i2c_start();		// transmit START condition
    i2c_write(0xD0);	// address DS1307 for write
    i2c_write(0x07);	// set register pointer to 7
    i2c_write(0x00);	// set value of location from 7 to 0
    i2c_stop();			// transmit STOP condition
}

void rtc_setTime(unsigned char h, unsigned char m, unsigned char s){
    i2c_start();		// transmit START condition
    i2c_write(0xD0);	// address DS1307 for write
    i2c_write(0);		// set register pointer to 0
    i2c_write(s);		// set seconds
    i2c_write(m);		// set minutes
    i2c_write(h);		// set hours
    i2c_stop();			// transmit STOP condition
}

void rtc_setDate(unsigned char y, unsigned char m, unsigned char d){
    i2c_start();		// transmit START condition
    i2c_write(0xD0);	// address DS1307 for write
    i2c_write(0x04);	// set register pointer to 4
    i2c_write(d);		// set seconds
    i2c_write(m);		// set minutes
    i2c_write(y);		// set hours
    i2c_stop();			// transmit STOP condition
}

void rtc_getTime(unsigned char *h, unsigned char *m, unsigned char *s){

    i2c_start();		// transmit START condition
    i2c_write(0xD0);	// address DS1307 for write
    i2c_write(0);		// set register pointer to 0
    i2c_stop();			// transmit STOP condition

    i2c_start();		// transmit START condition
    i2c_write(0xD1);	// address DS1307 for read

    *s = i2c_read(1);	// read second, return ACK
    *m = i2c_read(1);	// read minute, return ACK
    *h = i2c_read(0);	// read hour, return ACK
    i2c_stop();			// transmit STOP condition
}

void rtc_getDate(unsigned char *y, unsigned char *m, unsigned char *d){
    i2c_start();		// transmit START condition
    i2c_write(0xD0);	// address DS1307 for write
    i2c_write(0x04);	// set register pointer to 0
    i2c_stop();			// transmit STOP condition

    i2c_start();		// transmit START condition
    i2c_write(0xD1);	// address DS1307 for read
    *d = i2c_read(1);	// read day, return ACK
    *m = i2c_read(1);	// read month, return ACK
    *y = i2c_read(0);	// read year, return ACK
    i2c_stop();			// transmit STOP condition
}

int main(){
    unsigned char i,j,k;
    lcd_init(LCD_DISP_ON);
    lcd_clrscr();
    while(1){
        lcd_puts("Time is");
        rtc_init();
        rtc_setTime(0x19,0x45,0x30);	//19:45:30 (hh:mm:ss)
        rtc_setDate(0x09,0x01,0x10);	//09:01:10 (dd:mm:yy)
        rtc_getTime(&i,&j,&k);
        lcd_putc(i);
        lcd_putc(':');
        lcd_putc(j);
        lcd_putc(':');
        lcd_putc(k);
        lcd_putc('\n');
        rtc_getDate(&i,&j,&k);
        lcd_putc(i);
        lcd_putc(':');
        lcd_putc(j);
        lcd_putc(':');
        lcd_putc(k);
    }
    return 0;
}

BTW, is there a way to change the color of code from all green to something nice and cool. All green on white seems to hurt.

Robot building is all about sharing & learning
-----------------------------------
www.robotplatform.com

Last Edited: Thu. Oct 2, 2014 - 12:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code 'looks' as if it might work.

But your functions are all void.    So how do you know if i2c_start() or i2c_write() has been successful?

 

Compare your code with say Fleury.

 

Incidentally,   look at your main loop().

Do you really want to read the same time and date?

A stopped watch is correct twice a day.

A stopped calendar is only correct once in a century.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Compare your code with say Fleury.

I tried fleury's code but was not able to work with it as it seems too complex. Hence preferred this.

 

Do you really want to read the same time and date?

I would have been happy if I was able to achieve that and later correct it. But still stuck with nothing displayed. Will plug this into an arduino and verify with existing code tonight. If that too fails, it should be a hardware issue.

Robot building is all about sharing & learning
-----------------------------------
www.robotplatform.com

Last Edited: Thu. Oct 2, 2014 - 12:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In your get time function you need to do a restart instead of a stop/start! 

 

i2c_start();		// transmit START condition
    i2c_write(0xD0);	// address DS1307 for write
    i2c_write(0x04);	// set register pointer to 0
    i2c_stop();			// transmit STOP condition
                                                                  <-- replace stop / start with "restart" I2C command
    i2c_start();		// transmit START condition
    i2c_write(0xD1);	// address DS1307 for read
    *d = i2c_read(1);	// read day, return ACK
    *m = i2c_read(1);	// read month, return ACK
    *y = i2c_read(0);	// read year, return ACK
    i2c_stop();			// transmit STOP condition

 

 

JC

 

 

FF = PI > S.E.T

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

praveen_khm wrote:

I tried fleury's code but was not able to work with it as it seems too complex. Hence preferred this.

Rubbish.    The twimaster.c are 'almost' identical.    It is your job to investigate the differences.

 

It makes absolutely no difference with a DS1307 if you do a stop-start or a restart.

However,   you do have to wait for the stop() to complete.

 

Really,   your time is better spent by studying proven code.     By all means ask questions about anything that you don't understand.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

praveen_khm wrote:
BTW, is there a way to change the color of code from all green to something nice and cool.
If you're running Firefox, Chrome, or Safari as your browser, just use the 'Stylish' add-on.

 

Regards,

Bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A simple reality check.  Do you have external pull-up (to Vcc, usually +5V) resistors (3K ohms to @10K ohms) on the SDA and SCL lines? 

The I2C (or TWI) interface does not operate by writing logic high and low to the lines.  The lines are either asserted (pulled to ground) or released (allowed to float up to Vcc).  Using the AVR internal pull-ups can cause the lines to release too slowly, especially if there is more than one I2C device on the bus.

 

Another thing, try setting the TWBR register to 0x20 instead of 0x47.  If your system clock is running at the factory default of 1MHz, the TWBR value of 0x47 causes the I2C to run at 6.5KHz (TWI clock  == cpu clock / (16 + (2*TWBR) * prescale (value = 1 when TWSR is 0x00 ).  This might be too slow for the DS1307.

Try to get the TWI clock to be about 100KHz for the DS1307 and 400KHz for serial EEPROMs.

 

Last Edited: Thu. Oct 2, 2014 - 11:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you're running Firefox, Chrome, or Safari as your browser, just use the 'Stylish' add-on.

Thanks, will have a look at it :)

 

Really,   your time is better spent by studying proven code.     By all means ask questions about anything that you don't understand.

I am using his code for LCD and it is really easy, but guess I did not spend time with this code. Will check it out if you are suggesting that it is worth.

 

A simple reality check.  Do you have external pull-up (to Vcc, usually +5V) resistors (3K ohms to @10K ohms) on the SDA and SCL lines? 

Yes. 6.8K on both lines.

 

Another thing, try setting the TWBR register to 0x20 instead of 0x47.  If your system clock is running at the factory default of 1MHz...

I guess I need to check. Have ordered couple of more IC's as I am still not sure about the hardware. Once I get it, will check again. I tried this on an arduino board with another tested code, but seems to not respond.

Robot building is all about sharing & learning
-----------------------------------
www.robotplatform.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried this on an arduino board with another tested code, but seems to not respond.

 

That is an excellent strategy.     If the chip does not work with proven software on proven hardware,    you know that the chip is wrong.

From memory,   the Arduino <Wire.h> will tell you if something fails but not much more.

 

If you make your I2C functions non-void,    you will discover exactly where the problem is.     (e.g. try it with Fleury)

 

Oh,   a DS1307 will run at the standard 100kHz but not at 400kHz.     It should work at any low speed.

 

DAvid.