I2C comunicación ATmega328P esclavo: responde a la llamada general pero no a la propia dirección

0

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
    }
}
    
pregunta user198530

1 respuesta

2

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

    
respondido por el uhours

Lea otras preguntas en las etiquetas