Moin, Ich versuche aktuell eine Kommunikation zwischen einem AtMega32 (Master) und einem AtxMega256A3B (Slave) über I²C herzustellen. Für den AtMega32 nutze ich die Bibliothek von Peter Fleurry. Diese scheint soweit auch korrekt implementiert zu sein, die Kommunikation mit einem PCF8574 funktioniert einwandfrei. Ich habe es bereits hinbekommen, dass der Master Daten an den Slave sendet. Allerdings scheitere ich daran, dass der Master Daten vom Slave liest. Ich initialisiere I2C auf dem XMega: >TWIE.SLAVE.ADDR = I2C_ADDRESS; >TWIE.SLAVE.CTRLA = 0b11111000; >TWIE.SLAVE.CTRLB = 0b00000000; >PORTA.DIR |= I2C_INT_PIN; Beim Setzen des Interrupt-Pins wird gleichzeitig ein Interrupt-Impuls gesendet. Ein Interrupt beim Mega32 setzt I2C_Interrupt auf 1, wodurch in der Hauptschleife die I2C Kommunikation vom Master (Atmega) gestartet wird: >while (1) >{ > if (I2C_Interrupt) > { > lcd_string("Interrupt!"); > I2C_Interrupt = 0; > > // Try logged in devices > > for (int i = 0; i < i2c_addresses_loggedin_amount; i++) > check_i2c_device(i, i2c_addresses_loggedin[i], 1); > } >} >uint8_t check_i2c_device(uint8_t i, uint8_t address, uint8_t loggedin) >{ > uint8_t x; > if (x = i2c_start_wait(address | I2C_READ)) // Address not reach -> log off > { > if (loggedin) > Remove_I2C_Address(i); > return 0; > } > > if ((I2C_Int_PIN & I2C_Int_PIN_N) == I2C_Int_PIN_N) // Interrupt cleared > { > uint8_t answer = i2c_read(0); > > if (address == Handsteuerung_Address) > { > if (answer == HS_LOGIN) > HS_Online = 1; > else if (answer == HS_LOGOFF) > Remove_I2C_Address_by_Address(Handsteuerung_Address); > } > return 1; > } > return 0; >} In i2c_addresses_loggedin stehen alle aktuell eingeloggten Geräte. Also alle I2C-Geräte, die dem Master bekannt sind, dass sie sich aktuell am Bus befinden. Die Funktion prüft nun, ob die Adresse erreichbar ist, wenn dem nicht so ist, wird das Gerät mit der Funktion Remove_I2C_Address aus der Eingeloggten-Liste gelöscht, da es offensichtlicherweise nicht mehr online ist. Sollte das Gerät ein Ack senden, überprüft die Funktion, ob der Interrupt Pin wieder freigegeben ist. Dies geschieht, sobald das richtige Gerät angesprochen wurde. In diesem Fall wird ausgewertet, was der Slave zurückgegeben hat. Der Code des xMegas nach dem Initialisieren: >uint8_t reg = ~TWIE.SLAVE.STATUS; >int am = 0; >while(1) >{ > if (reg != TWIE.SLAVE.STATUS) > {// Print Slave-Status-Reg > reg = TWIE.SLAVE.STATUS; > char* buffer = (char*)malloc(sizeof(char) * 11); > sprintf(buffer, "0x%02x", reg); > Print_String(buffer, 180, 4 + am++ * 16, WHITE); > } > if (TWIE.SLAVE.STATUS & (1 << 6)) > { // Apif set -> send ack, clear interrupt > TWIE.SLAVE.CTRLB = 0b00000011; > I2C_INT_PORT.OUT |= I2C_INT_PIN; > } > else if (TWIE.SLAVE.STATUS & (1 << 7)) > { // Dif set -> set data, send ack > TWIE.SLAVE.DATA = 2; > } >} Um den Code zu schreiben, habe ich den Chart "Slave operation" auf Seite 9 genommen: http://www.atmel.com/images/doc8054.pdf So wie ich das verstehe, sendet der Master das Start-Signal und die Adresse inkl. Read-Bit. Beim Slave wird APIF gesetzt und mit TWIE.SLAVE.CTRLB = 0b00000011; sende ich das geforderte ACK. Anschließend schreibe ich mit TWIE.SLAVE.DATA = 2; die Daten ins "data register". Mit dem Setzen des Data-Registers wird die Clock wieder freigegeben und der Master kann das Byte empfangen. Nach dem Schemata müsste damit die Kommunikation beendet sein, da ich mit i2c_read(0) ein NACK nach dem Lesen eines Bytes zurückgeben lasse. Stattdessen hält der Slave die Clock auf GND und blockiert somit weitere Kommunikation. Der Slave registriert die folgenden Status-Werte vom TWIE.SLAVE.STATUS-Register: 0x00 = 0b0000 0000 0x63 = 0b0110 0011 0x03 = 0b0000 0011 0xa3 = 0b1010 0011 Wo liegt da mein Fehler? Füge ich an der Stelle, wo ich die zu übertragenden Daten ins Register schreibe noch folgende Zeile hinzu: TWIE.SLAVE.CTRLB = 0b11; Dann wird die Clock wieder freigegeben. Allerdings bricht i2c_start_wait() bei if( (TW_STATUS & 0xF8) != TW_MT_SLA_ACK) ab. Der Slave gibt folgende Status-Werte aus: 0x00 = 0b0000 0000 0x63 = 0b0110 0011 0x03 = 0b0000 0011 0x02 = 0b0000 0010 0x03 = 0b0000 0011 0x02 = 0b0000 0010 Mein Master erkennt die Verbindung als gescheitert an und löscht das Gerät aus der Eingeloggten-Liste. Ich habe das Gefühl, ich drehe mich hier ein wenig im Kreis und habe irgendwo einen entscheidenen Punkt übersehen... Wäre daher klasse, wenn mir da jemand mit Ahnung einen Tipp geben könnte, wo mein Fehler steckt.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.