Saad Rafey
Saad Rafey

Reputation: 551

Accessing RTC(DS1307) through I2C in ATmega16

I have written a code to access RTC(DS1307) through I2C using ATmega16 and I am using compiler AVR Studio 4.

Code is given below:-

#include<avr/io.h>
#include<util/delay.h>
#define F_CPU 1000000UL

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

}

void rtc_start(void)
{
TWCR=(1<<TWEN)|(1<<TWSTA)|(1<<TWINT);

while(TWCR & (1<<TWINT)==0);

}


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

void rtc_write(unsigned char data)
{
TWDR=data;// sending address
TWCR=(1<<TWINT)|(1<<TWEN);
while(TWCR & (1<<TWINT)==0);
}

void rtc_stop()
{
TWCR=(1<<TWINT)|(TWSTO)|(1<<TWEN);
while(TWCR & (1<<TWINT)==0);

}

main()
{
unsigned char sec,min,hr;
DDRA=0xFF;
DDRB=0xFF;


rtc_init();
_delay_ms(1000);

rtc_start();

rtc_write(0b11010000);   // 1101000=adress of ds1307 and bit 0= write   
rtc_write(0x00);  // pointing address location 00 i.e seconds
rtc_write(0x00);// set sec=0
rtc_write(0x00);// set min=0
rtc_write(0x00);// set hr=0

rtc_stop();


while(1)
{

rtc_start();
rtc_write(0b11010001);   // 1101000=adress of ds1307 and bit 1= read   
rtc_write(0x00);  // pointing address location 00 i.e seconds
sec=rtc_read();
rtc_stop();
PORTA=sec;
PORTB=0x01;
_delay_ms(5000);
rtc_start();
rtc_write(0b11010001);   // 1101000=adress of ds1307 and bit 1= read   
rtc_write(0x01);  // pointing address location 00 i.e seconds
min=rtc_read();
rtc_stop();
PORTA=min;
PORTB=0x02;
_delay_ms(5000);
rtc_start();
rtc_write(0b11010001);   // 1101000=adress of ds1307 and bit 1= read   

hr=rtc_read();
rtc_stop();
PORTA=hr;
PORTB=0b00000100;
_delay_ms(5000);
}
}

I have successfully build the above code. When I am running this code on PROTEUS simulator I am not getting any output, but polling in the code working properly for applying delay.

I want to know where I have done wrong and how to resolve it.

Upvotes: 0

Views: 5345

Answers (1)

angelatlarge
angelatlarge

Reputation: 4150

I don't think you are generating the start condition correctly, among other things. From the datasheet (page 183):

The first step in a TWI transmission is to transmit a START condition. This is done by writing a specific value into TWCR, instructing the TWI hardware to transmit a START condition. Which value to write is described later on. However, it is important that the TWINT bit is set in the value written. Writing a one to TWINT clears the flag. The TWI will not start any operation as long as the TWINT bit in TWCR is set. Immediately after the application has cleared TWINT, the TWI will initiate transmission of the START condition.

There is a detailed C example in the datasheet that looks like this:

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)  //Send START condition
while (!(TWCR & (1<<TWINT)));           // Wait for TWINT Flag set. This indicates
                                        // that the START condition has been transmitted
if ((TWSR & 0xF8) != START)             // Check value of TWI Status Register. Mask
    ERROR();                            // prescaler bits. If status different from
                                        // START go to ERROR
TWDR = SLA_W;                           // Load SLA_W into TWDR Register. Clear
TWCR = (1<<TWINT) | (1<<TWEN);          // TWINT bit in TWCR to start transmission
                                        // of address
while (!(TWCR & (1<<TWINT)));           // Wait for TWINT Flag set. This indicates
                                        // that the SLA+W has been transmitted,
                                        // and ACK/NACK has been received.
if ((TWSR & 0xF8) != MT_SLA_ACK)        // Check value of TWI Status Register. Mask
    ERROR();                            // prescaler bits. If status different from
                                        // MT_SLA_ACK go to ERROR
TWDR = DATA;                            // Load DATA into TWDR Register. Clear
TWCR = (1<<TWINT) | (1<<TWEN);          // TWINT bit in TWCR to start transmission
                                        // of data
while (!(TWCR & (1<<TWINT)));           // Wait for TWINT Flag set. This indicates
                                        // that the DATA has been transmitted, and
                                        // ACK/NACK has been received.
if ((TWSR & 0xF8) != MT_DATA_ACK)       // Check value of TWI Status Register. Mask
    ERROR();                            // prescaler bits. If status different from
                                        // MT_DATA_ACK go to ERROR
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // Transmit STOP condition

That is very different from your code. I'd start with the sample from the datasheet, and go from there.

Upvotes: 1

Related Questions