我在使用Atmega168作为I2C器件时遇到了一些问题。基本设置是物理I2C总线连接到其他从器件,但Atmel本身未启用I2C。Atmega168 I2C as master
总线上还有一个基于Linux的TI DM365 SoC。 DM365可以毫无问题地与从属设备进行通信。所以基本上,这将是一个多主设置。
重要的atmel代码粘贴在下面。在这种情况下,USART_Transmit与printf相同。在main()中调用TWIinit(),并且通过命令(从串口)读取总线。
我不断收到“错误:0x18”,这是当设备地址不传输时表明总线繁忙。但是当我使用电压表(抱歉,没有示波器)时,它保持在3.3V的高电平,这意味着总线可以自由使用。我也尝试过通过物理切割DM365,但即使这样也行不通。
任何帮助或想法表示赞赏。
编辑:道歉的可怕的调试方法。当我得到'错误:0x18'这意味着我从来没有得到0x18,这只是意味着我被卡住了。我得到的实际值是0x06,我不知道它来自哪里。
uint8_t u8ebyte;
uint8_t u8erbyte;
uint16_t u16eaddress = 0x0002;
#define EEDEVADR 0x36
void TWInit (void)
{
TWSR = 0x00; // prescaler 1
TWBR = 0xFF; //0xFF; //smallest TWBR value possible is 0x10
TWCR = (1<<TWEN); // Enable TWI-interface and release TWI pins.
}
void TWIStart(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while ((TWCR & (1<<TWINT)) == 0);
}
//send stop signal
void TWIStop(void)
{
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}
void TWIWrite(uint8_t u8data)
{
TWDR = u8data;
TWCR = (1<<TWINT)|(1<<TWEN);
while ((TWCR & (1<<TWINT)) == 0);
}
uint8_t TWIReadACK(void)
{
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
while ((TWCR & (1<<TWINT)) == 0);
return TWDR;
}
//read byte with NACK
uint8_t TWIReadNACK(void)
{
TWCR = (1<<TWINT)|(1<<TWEN);
while ((TWCR & (1<<TWINT)) == 0);
return TWDR;
}
uint8_t TWIGetStatus(void)
{
uint8_t status;
//mask status
status = TWSR & 0xF8;
return status;
}
uint8_t I2CReadByte(uint16_t u16addr, uint8_t *u8data)
{
//uint8_t databyte;
TWIStart();
if (TWIGetStatus() != 0x08){
USART_Transmit_string("ERR:0x08");
TWIStop();
return -1;
}
//select device
TWIWrite((EEDEVADR)|((uint8_t)((u16addr& 0x0700)>>7)));
//TWIWrite(((EEDEVADR)<<1|0));
if (TWIGetStatus() != 0x18){
USART_Transmit_string("ERR:0x18");
return -1;
}
//send the rest of address
TWIWrite((uint8_t)(u16addr));
if (TWIGetStatus() != 0x28){
USART_Transmit_string("ERR:0x28");
return -1;
}
//send repeated- start
TWIStart();
if (TWIGetStatus() != 0x10){
USART_Transmit_string("ERR:0x10");
return -1;
}
//select devise and send read bit
TWIWrite((EEDEVADR)|((uint8_t)((u16addr & 0x0700)>>7))|1);
if (TWIGetStatus() != 0x40){
USART_Transmit_string("ERR:0x40");
return -1;
}
*u8data = TWIReadNACK();
if (TWIGetStatus() != 0x58){
USART_Transmit_string("ERR:0x58");
return -1;
}
TWIStop();
USART_Transmit_string("MADE IT!!");
return 1;
}
TWIGetStatus()!= 0x18,检查状态是否为0x18或其他。 如果你想调试这个问题,你应该通过uart发送当前状态。 0x18表示:已发送SLA + W。 http://www.atmel.com/images/doc2545.pdf表22.2 – 2014-10-30 22:38:32
更新了我的问题。我得到的当前状态是0x06。 – tsf144 2014-10-31 15:32:55