我在使用Atmega168作为I2C设备时遇到了一些问题。基本设置是物理I2C总线连接到其他从设备,但Atmel本身未启用I2C。
总线上还有一个基于linux的TI DM365 SoC。 DM365可以毫无问题地与从设备通信。从本质上讲,它将是一个多主设置。
下面粘贴了重要的atmel代码。在这种情况下,USART_Transmit与printf相同。在main()中调用TWIinit(),并在命令(从串行)上读取总线。
我一直收到“错误:0x18”,这是指未发送设备地址表示总线忙。但是当我使用电压表(抱歉,没有示波器)时,它保持在3.3V的高电平,这意味着总线可以自由使用。我也通过实际切断DM365来尝试这一点,但即使这样也行不通。
感谢任何帮助或想法。
编辑:为可怕的调试方法道歉。当我得到'Err: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;
}
答案 0 :(得分:0)
可能是由于这些问题:
硬件
可能是由于线路上拉不当造成的,这取决于总线上的处理器/微控制器或传感器。
软件
检查协议的速度(100Khz或400KHz)。主设备和从设备通信应该相同。
尝试重写TWI Start的代码,如下所示:
void TWI_start(void){
// Clear TWI interrupt flag, Put start condition on SDA, Enable TWI
TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while(!(TWCR & (1<<TWINT))); // Wait till start condition is transmitted
while((TWSR & 0xF8)!= 0x08);// Check for the acknowledgement
}
这里的代码等到TWSR&amp; 0xF8变为0x08。同样重写代码并尝试!