Comunicación I2C ATmega328P esclavo: respuesta a llamada general pero no a dirección propia

Tengo el siguiente problema:

Quiero hacer dos AVR Atmega 328P-Pu comunicándose juntos con I2C

  • No1 es maestro (dirección I2C: 0x01)
  • No2 es esclavo (dirección I2C: 0x02)

En el esclavo se habilita la respuesta a llamada general (dirección 0x00) y funciona. O, al menos, puedo ver que ingresa el ISR (TWI_vect) en el esclavo con el código más abajo.

Sin embargo, cuando intente llamar al salve con su propia dirección (0x02), no responderá. Todo lo demás permanece igual (circuito, resistencias pull-up, etc.)

Además, intentar bombardear el bus con llamadas a todas las direcciones posibles hasta 128 no produce respuesta del esclavo.

Estoy seguro de que es un error tonto en alguna parte, pero me estoy quedando sin idea de por qué es así. Cualquier ayuda es bienvenida.

en maestro

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 llamado principal del Maestro 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 principal 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
    }
}
Sus direcciones están en el rango reservado, creo.
¿El hardware realmente respeta las direcciones reservadas?
¿Se declara volátil su indicador de "depuración"? Realmente necesita incluir el código completo para replicar el problema.
@uhours Parecía hacerlo en este caso: chat.stackexchange.com/rooms/37934/… . Pasó mucho tiempo depurando y resultó ser simplemente porque el esclavo Arduino estaba usando una dirección reservada. Pero si el problema del OP se resuelve con su respuesta, eliminaré el mío.
@TisteAndii, creo que era el Pic haciendo algo. La hoja de datos de ATmega328 anuncia 128 direcciones esclavas. De cualquier manera, no es la mejor idea usar esas direcciones.
Maldición, eso fue un error realmente tonto. Gracias a uhours y TisteAndii

Respuestas (1)

Está configurando la dirección esclava en 0x00 (7 bits) cuando habilita la llamada general. Utilice TWAR |= (1<<TWGCE);en su lugar.