0
\$\begingroup\$

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
    }
}
\$\endgroup\$
  • \$\begingroup\$ Your addresses are in the reserved range, I think. \$\endgroup\$ – TisteAndii Aug 20 '17 at 19:48
  • 1
    \$\begingroup\$ Does the hardware actually respect reserved addresses? \$\endgroup\$ – uhours Aug 20 '17 at 20:09
  • \$\begingroup\$ Is your "debug" flag declared volatile? You really need to include the complete code to replicate the problem. \$\endgroup\$ – Chris Stratton Aug 20 '17 at 20:18
  • \$\begingroup\$ @uhours It seemed to do so in this case: chat.stackexchange.com/rooms/37934/…. A long time spent debugging and it turned out to be merely because the Arduino slave was using a reserved address. But if the OP's problem gets solved by your answer, then I'll delete mine. \$\endgroup\$ – TisteAndii Aug 20 '17 at 20:53
  • \$\begingroup\$ @TisteAndii, I think that was the Pic doing something. The ATmega328 datasheet advertises 128 slave addresses. Either way, it's not the best idea to use those addresses. \$\endgroup\$ – uhours Aug 20 '17 at 21:02
2
\$\begingroup\$

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

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.