如何编写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
我已经为 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