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\$
6
  • \$\begingroup\$ Your addresses are in the reserved range, I think. \$\endgroup\$ Commented Aug 20, 2017 at 19:48
  • 1
    \$\begingroup\$ Does the hardware actually respect reserved addresses? \$\endgroup\$ Commented Aug 20, 2017 at 20:09
  • \$\begingroup\$ Is your "debug" flag declared volatile? You really need to include the complete code to replicate the problem. \$\endgroup\$ Commented Aug 20, 2017 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\$ Commented Aug 20, 2017 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\$ Commented Aug 20, 2017 at 21:02

1 Answer 1

4
\$\begingroup\$

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

\$\endgroup\$
0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.