Electrical – I2C communication ATmega328P slave: answer to general call but not to own address

atmega328pavri2c

I have the following problem:

I want to make two AVR Atmega 328P-Pu communicating together with I2C

  • No1 is Master (I2C address :0x01)
  • No2 is Slave (I2C address :0x02)

On slave answer to general call is enabled (address 0x00) and it works. Or, at least I can see that it enters the ISR(TWI_vect) on the slave with the code further below.

However when trying to call the salve with it's own address (0x02) it won't respond. Everything else remains the same (circuit, pull-up resistors etc.)

Moreover, trying to bomb the bus with calls to all possible address up to 128 does not yield response from slave.

I am sure it is a silly mistake somewhere but running out of idea as of why it is like that.
Any help welcome.

On Master

I2C communication is initiated like that

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;
}

In the Master's main call is made like that

uint8_t address=1;
addr=address<<1;
i2c_start(addr|I2C_WRITE);   // I2C_WRITE =0x00

On slave

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);
}

The main on the slave looks like that

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

Best Answer

You're setting the slave address to 0x00 (7-bits) when you enable the general call. Use TWAR |= (1<<TWGCE); instead.