如何编写avr I2C主控读函数

how to write avr I2C master read function

我已经为 ATmega168 编写了一些配置函数来从与 DS1307 的 TWI 通信中读取数据。但我可以写入 DS1307 而不是读取。谁能帮帮我。

这是我的职能:

void TW_init(void)  
{
    TWBR = 2;
    TWSR = (1 << TWPS1);
    TWCR = (1 << TWEN);
}

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

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

void TW_write(uint8_t data)
{
    TWDR = data;
    TWCR = (1 << TWEN)|(1 << TWINT);
    while(!(TWCR & (1 << TWINT)));
}

uint8_t TW_read(void)
{
    TWCR = (1<<TWINT)|(1<<TWEN);
    while(!(TWCR & (1 << TWINT)));

    return TWDR;
}

uint8_t DS1307_Read(uint8_t address)
{

    unsigned short r_data;

    TW_start();
    TW_write(DS1307);
    TW_write(address);
    TW_start();
    TW_write(DS1307 + 1);
    r_data = TW_read();
    TW_stop();

    return r_data;

}

uint8_t DS1307_Write(uint8_t address, uint8_t w_data)
{
    TW_start();
    TW_write(DS1307);
    TW_write(address);
    TW_write(w_data);
    TW_stop();

}

我尝试了很多来纠正我的配置功能,但我找不到错误或缺少什么,所以也许有人可以帮助我纠正它。我正在 Proteus 中对其进行测试,它显示时钟已设置。

如果需要更多详细信息,我会 post 他们。

DS1307_Read() 中,您需要在选择地址后断言 "STOP" 信号:

uint8_t DS1307_Read(uint8_t address)
{    
    unsigned short r_data;

    TW_start();
    TW_write(DS1307);
    TW_write(address);
    TW_stop();         // <-- STOP

    TW_start();
    TW_write(DS1307 + 1);
    r_data = TW_read();
    TW_stop();

    return r_data;
}

由于这是一个 DS1307 特定接口而不是通用 I2C 读取,因此对整个 time/date 数据执行顺序 read/write 会更有效,如 this example