Forum: Mikrocontroller und Digitale Elektronik LPC2378 sporadisches Problem mit I2C stop


von Peter (Gast)


Lesenswert?

Hallo Forum,

ich arbeite mit einem LPC2378 und am I2C0 (im master mode) ist ein 
EEPROM angeschlossen.
Sporadisch hat sich mein Programm komplett aufgehängt.
Anhand von Terminalausgaben habe ich die Stelle auf das Senden der Stop 
Condition eingegrenzt.
Dann habe ich in der i2c_stop() Funktion noch ein while() Schleife ohne 
Timeout gefunden.

Nun habe ich einen Timeout in der while() Schleife und bei Ablauf des 
Timeouts wird der I2C Bus neu initialisiert.
Damit scheint es zu laufen.

Ich frage mich aber, warum die Stop Condition manchmal fehlschlägt...
Momentan bombadiere ich den Controller mit Leseanfragen ans EEPROM. Und 
da sehe ich nun ab und zu, dass der Timeout abläuft.
Das Programm läuft aber jetzt weiter.

Beim Schreiben ins EEPROM wird mit der Stop Condition die interne 
Übernahme des EEPROM Buffers getriggert. Ob das jetzt so auch 
funktioniert, habe ich noch nicht getestet.

Ob die Stop Condition richtig auf dem Bus landet konnte ich mangels 
Triggermöglichkeit nicht richtig überprüfen.

Habt ihr eine Idee woran das liegen kann?

Unten meine i2c_stop() mit der besagten while() Schleife.
Das Datenblatt sagt zu STO:
1
STO is the STOP flag. Setting this bit causes the I2C interface to transmit a STOP
2
condition in master mode, or recover from an error condition in slave mode. When STO is
3
1 in master mode, a STOP condition is transmitted on the I2C bus. When the bus detects
4
the STOP condition, STO is cleared automatically.
1
//Send "STOP" condition
2
u08 i2c_stop(void) {
3
  u08 timeout = 40; //typically goes on after 5 loops
4
5
  I2C0CONCLR = SIC;     //  clear SI
6
  I2C0CONSET = STO;     //  set STO
7
  
8
  while(--timeout && (I2C0CONSET&STO)); //  check for STO cleared with timeout
9
  xprintf("i2c_stop(): timeout %d\n" ,timeout); //debug
10
  if (timeout==0) {
11
    i2c0_init();
12
    return 1;
13
  }
14
  return 0;
15
}

von Peter (Gast)


Lesenswert?

Ich könnte auch noch probieren, anstelle der Neuinitialisierung ein 
neues Stop zu senden...

von Peter (Gast)


Lesenswert?

Ich habe mir nun einen Pin als Trigger gesetzt und mit einem 
Logicanalyzer gesehen, dass die Stop Condition nicht auf dem Bus zu 
sehen ist.

Kann es sein, dass diese Befehle zu nah hintereinander stehen?
1
I2C0CONCLR = SIC;     //  clear SI
2
I2C0CONSET = STO;     //  set STO

von Peter (Gast)


Lesenswert?

Ein erneutes
1
I2C0CONSET = STO;     //  set STO
nach dem Timeout scheint auch nicht rauszukommen...

von Peter (Gast)


Lesenswert?

Ich habe jetzt die Vermutung, dass die Befehle in anderer Reihenfolge 
kommen müssen.
Zumindest scheint es bisher damit zu funktionieren und so habe ich es in 
anderem Beispielcode gesehen. Aber einen Beleg im Datenblatt habe ich 
nicht gefunden.

Also so:
1
I2C0CONSET = STO;     //  set STO
2
I2C0CONCLR = SIC;     //  clear SI

von Peter (Gast)


Lesenswert?

So scheint es jetzt zu funktionieren!

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
Noch kein Account? Hier anmelden.