Tengo el siguiente problema:
Quiero hacer dos AVR Atmega 328P-Pu que se comunican junto con I2C
- No1 es Master (dirección I2C: 0x01)
- No2 es esclavo (dirección I2C: 0x02)
La respuesta de esclavo a la llamada general está habilitada (dirección 0x00) y funciona. O, al menos puedo ver que ingresa el ISR (TWI_vect) en el esclavo con el código que se encuentra más abajo.
Sin embargo, cuando se intenta llamar a la salve con su propia dirección (0x02) no responde. Todo lo demás sigue siendo el mismo (circuito, resistencias pull-up, etc.)
Además, intentar bombardear el autobús con llamadas a todas las direcciones posibles hasta 128 no produce respuesta del esclavo.
Estoy seguro de que es un error tonto en algún lugar, pero se me está acabando la idea de por qué es así. Cualquier ayuda bienvenida.
En Master
La comunicación I2C se inicia así
uint8_t i2c_start(uint8_t address)
{
// reset TWI control register
TWCR = 0;
// transmit START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait for end of transmission
while( !(TWCR & (1<<TWINT)) );
// check if the start condition was successfully transmitted
if((TWSR & 0xF8) != TW_START){ return 1; }
// load slave address into data register
TWDR = address;
// start transmission of address
TWCR = (1<<TWINT) | (1<<TWEN);
// wait for end of transmission
while( !(TWCR & (1<<TWINT)) );
// check if the device has acknowledged the READ / WRITE mode
uint8_t twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 2;
return 0;
}
En el Master main la llamada se hace así
uint8_t address=1;
addr=address<<1;
i2c_start(addr|I2C_WRITE); // I2C_WRITE =0x00
En esclavo
void I2C_init(uint8_t address){
// load address into TWI address register
TWAR = (address << 1);
TWAR = (1<<TWGCE); //respond to general call ! WARNING
// set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
TWCR=0x0; //WARNING
TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
}
El main en el esclavo se ve así
I2C_init(slaveaddress);
sei();
LED_PORT_DDR |= _BV(LED_BIT);
for(;;){
wdt_reset();
if(debug==1) //Debug is set to 1 in the ISR(TWI_vect)
{
LED_PORT_OUTPUT |= _BV(LED_BIT); //set to 1 e.g
}
}