Hi Leute, Brauche mal wieder eure Hilfe. Bei der benutzung der TWI meines mega32 stüzt ständig das Programm ab. Weiß nicht warum?! Dies Programm soll eigentlich dazu dienen die Temperatur aus dem DS1621 auszulesen. Tut es auch, 10mal oder so. #include "lcd.h" void sendi2c(uint8_t add, uint8_t data) { TWBR=11; TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN); while(!(TWCR & (1<<TWINT))); //start i2C TWDR=add; TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))); //adress + write trasmitt TWDR=data; TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))); //data transmitt TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); } uint8_t readi2c(uint8_t add, uint8_t comm) { TWBR=11; TWCR=(1<<TWEN)|(1<<TWSTA)|(1<<TWINT); while(!(TWCR & (1<<TWINT))); //start TWDR=add; TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))); //adress + write transmitt TWDR=comm; TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))); //command transmitt TWCR=(1<<TWEN)|(1<<TWSTA)|(1<<TWINT); while(!(TWCR & (1<<TWINT))); //repared start TWDR=add+1; TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))); //adress + read transmitt TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))); //data read TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); //stop return(TWDR); } int main(void) { lcd_init(LCD_DISP_ON); uint8_t high; while(1) { sendi2c(144,0xEE); //start messung sendi2c(144,0x22); //stop messung high = readi2c(144,0xAA); //Temp auslesen lcd_puti2(high); lcd_home(); } return(0); }
Dein Programm "stuertzt" nicht ab sonder hängt in einer der While-Schleifen endlos. Gib doch mal vor jeder While-Schleife ein eindeutiges Signal an LED's/Ports aus und mess mal. Du gehst davon aus, das dein Gerät (Temperaturmesser) ständig unter allen Umständen über die gesammte Laufzeit (Endlos) ohne Fehler sofort sich per I2C meldet. => keine Endlosschleifen verwenden, besser Timeout oder Watchdog-Reset Gruss
Ich kämpfe auch gerade mit dem Hardware-I2C. Für zuverlässiges Arbeiten brauchst du einen Interrupthandler, der erstmal das TWSR auswertet und bei jedem unerwarteten Zustand das TWSTO setzt um die interne Zustandsmaschine zurückzusetzen. Außerdem noch ein Errorflag, damit Du die mißglückte Übertragung nochmal starten kannst. Trotzdem kann es sein, daß sich die interne Zustandsmaschine total verhakt. Ich habe deshalb noch einen Timeoutinterrupt, der testet, ob ein Stop innerhalb 5ms ausgeführt werden konnte. Wenn nicht, wird mit TWCR = 0; das I2C komplett abgeschaltet und nochmal neu initialisiert. Ich muß das Hardware-I2C benutzen, da ich die Multimaster Funktion benötige. Ich muß auch absichern, daß Störungen auf dem I2C-Bus in jedem Fall behoben werden. Für Single-Master Anwendungen ist deshalb ein Software-I2C wesentlich einfacher (weniger Code) und stabiler. Peter
Ja stimmt, daran hab ich gar nicht gedacht. Hab jetzt ein Timeout eingabaut, jetzt geht es. Danke! mfg
Hallo Peter! Ich hatte gerade ein ähnliches Problem: Ich steuere mit einem ATMEGA128 einen PCF8574 an. Ab und zu kam es vor, dass die Stopp-Routine nicht beendet werden konnte, nachdem ich Daten vom Baustein las. (Nach dem Schreiben auf den Baustein gab es nie Probleme) - Trat das Problem auf, blieb die Datenleitung unerbittlich auf low. Erst mit deiner beschriebenen Neuinitialisierung funktionierte es. TWCR = 0; TWCR = Initwert; I2C-Start(); Die Datenleitung war nach dem Start plötzlich wieder frei. Ich kam dahinter das dieses Problem aber nicht vom ATMEGA128 kam, sondern vom PCF8574, der die Datenleitung plötzlich nicht mehr freigab. Eine Genaue Untersuchung des Problems ergab, dass ich das Acknowledge-Bit "TWEA" eingeschaltet hatte. Wenn der ATMEGA128 nun Daten vom Baustein bekam, sendete der µC ein Ack. zurück an den PCF8574 und das mag er anscheinend nicht. Jetzt funktioniert es super. Verrat uns bitte, ob du dein Problem auf diese Weise lösen konntest. Tschüss Martin
@Martin: Dein Problem ist hausgemacht. Laut I²C-Spezifikation muß der Master, wenn er Daten liest, beim letzten Datenbyte ein nACk senden. Denn sonst legt der Slave beim nächsten Takt, wenn eigentlich das Stop-Bit gesendet werden soll, das erste Bit schon auf den Bus. Wenn das 0 ist, dann hängt die Übertragung, weil ja der Master eigentlich ein Stop senden will, dies aber nicht kann. Nur das nAck kann dies verhindern. Liest Du nur ein einziges Datenbyte vom 8574, dann mußt Du bereits beim ersten Datenbyte nAck senden. Ist alles ganz logisch. Man kann sich die komplette I²C-Spezifikation bei Philips herunterladen, würde ich sehr empfehlen, das dürfte einige Unklarheiten beseitigen.
Hallo Ich möchte noch eine Anmerkung machen, obwohl der Thread nicht mehr ganz aktuell ist. Hatte vor kurzem dasselbe Problem und die Hinweise oben haben mir sehr geholfen. Meines Erachtens haben die AVRs einen Hardwarefehler in der State-Machine, funktionieren jedoch im Multi-Master-Mode einwandfrei, wenn man folgendes beachtet: Das letzte Datenbyte muss (wie von thkais angemerkt) mit NACK bestätigt werden. Der Slave bekommt dann keinen Interrupt mit Status TW_SR_STOP (0xA0) mehr, sondern die Kommunikation ist mit TW_SR_DATA_NACK (0x58) bzw. TW_SR_GEN_NACK (0x98) beendet. Dass das allerdings laut Standard so sein soll, kann ich nach dem Durchlesen der Philips-I2C-Spezifikation nicht nachvollziehen. Der Slave kann zwar mit einem NACK beim letzten Datenbyte dem Master mitteilen, dass er keine weiteren Daten empfangen möchte, wenn die Anzahl der Datenbytes aber feststeht, muss er das aber nicht machen. In den Beispielen sind jedenfalls beim letzten Datenbyte beide Möglichkeiten ACK/NACK angeführt. Andreas
@Andreas: "If a master-receiver is involved in a transfer, it must signal the end of data to the slave- transmitter by not generating an acknowledge on the last byte that was clocked out of the slave. The slave-transmitter must release the data line to allow the master to generate a STOP or repeated START condition." Seite 10 der I²C-Spezifikationen von Philips (rechts unten) Version 2.1 vom Januar 2000. Gruß Thomas
An Thomas: Danke für den Hinweis. Hab ich nicht gesehen. Allerdings verwende ich den Slave-Transmitter-Modus gar nicht. IMHO sollte als Slave-Receiver ein ACK beim letzten Byte möglich sein. Scheint mir auch sinnvoll, damit der Master weiss, dass der Slave das Byte bekommen hat. Der ATmega128 hängt sich da in einer Multi-Master-Umgebung jedenfalls auf. Wenn das letzte Byte ein NACK bekommt, läuft es zuverlässig. Wenn nur ein Master vorhanden ist, scheint es auch mit ACK zu funktionieren. Schöne Grüße, Andreas
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.