I2C-Kommunikation ATmega328P-Slave: Antwort auf allgemeinen Anruf, aber nicht auf eigene Adresse

Ich habe folgendes Problem:

Ich möchte zwei AVR Atmega 328P-Pu dazu bringen, miteinander mit I2C zu kommunizieren

  • No1 ist Master (I2C-Adresse: 0x01)
  • No2 ist Slave (I2C-Adresse: 0x02)

Beim Slave ist die Antwort auf den Generalruf aktiviert (Adresse 0x00) und es funktioniert. Oder zumindest kann ich sehen, dass es die ISR (TWI_vect) auf dem Slave mit dem Code weiter unten eingibt.

Wenn Sie jedoch versuchen, den Salve mit seiner eigenen Adresse (0x02) anzurufen, antwortet er nicht. Alles andere bleibt gleich (Schaltung, Pull-up-Widerstände etc.)

Darüber hinaus führt der Versuch, den Bus mit Anrufen an alle möglichen Adressen bis zu 128 zu bombardieren, zu keiner Antwort vom Slave.

Ich bin mir sicher, dass es irgendwo ein dummer Fehler ist, aber mir geht die Idee aus, warum es so ist. Jede Hilfe willkommen.

Auf Meister

Die I2C-Kommunikation wird so initiiert

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

Im Hauptruf des Meisters wird so gesprochen

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

Auf Sklave

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

So sieht die Hauptsache am Sklaven aus

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
    }
}
Ihre Adressen sind im reservierten Bereich, denke ich.
Respektiert die Hardware tatsächlich reservierte Adressen?
Ist Ihr "Debug"-Flag als flüchtig deklariert? Sie müssen wirklich den vollständigen Code einfügen, um das Problem zu replizieren.
@uhours In diesem Fall schien es so zu sein: chat.stackexchange.com/rooms/37934/… . Lange Zeit mit dem Debuggen verbracht und es stellte sich heraus, dass es nur daran lag, dass der Arduino-Slave eine reservierte Adresse verwendete. Aber wenn das Problem des OP durch Ihre Antwort gelöst wird, werde ich meins löschen.
@TisteAndii, ich denke, das war das Bild, das etwas getan hat. Das ATmega328-Datenblatt bewirbt 128 Slave-Adressen. In jedem Fall ist es nicht die beste Idee, diese Adressen zu verwenden.
Verdammt, das war ein wirklich dummer Fehler. Danke an uhours und TisteAndii

Antworten (1)

Sie setzen die Slave-Adresse auf 0x00 (7 Bit), wenn Sie den allgemeinen Anruf aktivieren. Verwenden Sie TWAR |= (1<<TWGCE);stattdessen.