在ATmega16中通过I2C访问RTC(DS1307)

时间:2013-04-03 03:46:47

标签: embedded microcontroller i2c avr-gcc real-time-clock

我编写了一个使用ATmega16通过I2C访问RTC(DS1307)的代码,我使用的是编译器AVR Studio 4.

代码如下: -

#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);
}
}

我已经成功构建了上面的代码。当我在PROTEUS模拟器上运行此代码时,我没有得到任何输出,但在代码中轮询正常工作以应用延迟。

我想知道我做错了什么以及如何解决它。

1 个答案:

答案 0 :(得分:1)

我认为你没有正确地生成开始条件等等。从数据表(第183页):

  

TWI传输的第一步是发送START条件。   这是通过将特定值写入TWCR,指示   用于传输START条件的TWI硬件。要写的是哪个值   稍后描述。但是,设置TWINT位很重要   在写的价值。向TWINT写一个清除标志。 TWI   只要TWCR中的TWINT位置1,就不会启动任何操作。   应用程序清除TWINT后,TWI将立即执行   启动START条件的传输。

数据表中有一个详细的C示例,如下所示:

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

这与您的代码非常不同。我从数据表中的样本开始,然后从那里开始。