Hi, ich befasse mich gerade mit I2C und versuche mich an einer eigenen Implementierung einer Bibliothek für Atmel AVRs. Nun kann es ja dazu kommen, dass der Bus "verstopft" ist, wenn z.B. der Master inmitten eines Transfers neugestartet wird und so vergisst, dass er eigentlich noch SCL clocken müsste. Dies wird z.B. hier (http://www.analog.com/static/imported-files/application_notes/54305147357414AN686_0.pdf) beschrieben. Dort wird auch gleichzeitig eine Lösung vorgestellt, die da lautet: > The procedure is as follows: > 1) Master tries to assert a Logic 1 on the SDA line > 2) Master still sees a Logic 0 and then generates a clock > pulse on SCL (1-0-1 transition) > 3) Master examines SDA. If SDA = 0, go to Step 2; if > SDA = 1, go to Step 4 > 4) Generate a STOP condition Soweit auch alles klar. Allerdings verstehe ich den nächsten Satz nicht: > Note that this process may need to be repeated because > the cleared SDA line may have been cleared for the next > bit, which was a 1. Kann mir das jemand erklären? Anscheinend fehlt es mir hier an Vorstellungsvermögen, aber was genau ist hier das nächste "bit"? Vielleicht könnt ihr mir auf die Sprünge helfen. Wie handhabt ihr das Ganze? Vielen Dank!
Ich verstehe den Text so, dass beim Senden der STOP-condition der Slave noch ein Datenbit 0 ausgibt, wodurch die STOP-condition nicht am Bus durchkommt. Ich mache das immer so, dass ich einfach nach beim Initialisieren des I2C 9 mal eine 1 sende (z.B: I2C Receive) und danch ein STOP ausgebe. Damit bekommt der Slave sicher ein NAK geschickt und sollte danach eigentlich schweigen. Die STOP-condition setzt dann den Bus zurück. Das wird in folgendem Beitrag ausführlicher diskutiert: http://www.microchip.com/forums/m175368-print.aspx Gruss Mike
Irgendwie scheint es da mehrere Ansätze zu geben. Interessanterweise heißt es in der offiziellen Spezifikation in Punkt 3.1.16: > If the data line (SDA) is stuck LOW, the master should send nine clock > pulses. The device that held the bus LOW should release it sometime within > those nine clocks. If not, then use the HW reset or cycle power to clear > the bus. Das erscheint mir am Einfachsten in der Implementierung. Gibt es Probleme, die damit nicht gelöst werden?
I2C schrieb: > Irgendwie scheint es da mehrere Ansätze zu geben. Die oben genannte Prozedur ist doch eigentlich das Gleiche. Sie versucht nur ein paar Pulse zu sparen, sollten weniger als 9 nötig sein. Ob das der Bringer ist? MfG Klaus
Klaus schrieb: > Die oben genannte Prozedur ist doch eigentlich das Gleiche. Sie versucht > nur ein paar Pulse zu sparen, sollten weniger als 9 nötig sein. Ob das > der Bringer ist? Naja, nicht unbedingt, da sie auf das Senden der STOP Condition verzichtet. Je nach Implementierung der State Machine kann das ja durchaus etwas ausmachen. Ich verstehe nur nicht wie ich eine STOP Condition generieren kann, wenn SDA schon high ist. Eine STOP Condition ist ja definiert als Low-High Übergang von SDA während SCL high bleibt. Wenn aber SDA schon high ist, sehe ich nicht wie ich einen Low-High Übergang hinbekommen soll, ohne vorhergehenden High-Low Übergang, was ja einer START Condition entspräche. Übersehe ich hier etwas?
> Ich verstehe nur nicht wie ich eine STOP Condition generieren kann, wenn > SDA schon high ist. Eine STOP Condition ist ja definiert als Low-High > Übergang von SDA während SCL high bleibt. Wenn aber SDA schon high ist, > sehe ich nicht wie ich einen Low-High Übergang hinbekommen soll, ohne > vorhergehenden High-Low Übergang, was ja einer START Condition > entspräche. > > Übersehe ich hier etwas? Ja, der Master muss den Bus natürlich aktiv ansteuern. In folgender Reihenfolge: 1. 0->SCL, 1->SDA 2. 0->SCL, 0->SDA 3. 1->SCL, 0->SDA 4. 1->SCL, 1->SDA Der Schritt von 3 nach 4 ist die STOP-condition. START-condition wäre SDA von 1 auf 0 bei gleichzeitig SCL High. Ein Pegelwechsel auf SDA bei SCL Low löst kein START aus.
Mike schrieb: > 1. 0->SCL, 1->SDA > 2. 0->SCL, 0->SDA > 3. 1->SCL, 0->SDA > 4. 1->SCL, 1->SDA Könntest du das eben nochmal etwas ausführen? Worauf genau war das bezogen?
I2C schrieb: > Mike schrieb: >> 1. 0->SCL, 1->SDA >> 2. 0->SCL, 0->SDA >> 3. 1->SCL, 0->SDA >> 4. 1->SCL, 1->SDA > > Könntest du das eben nochmal etwas ausführen? Worauf genau war das > bezogen? Auf Deine Frage: wie erzeuge ich eine STOP-Condition, wenn SCL und SDA high sind, ohne vorher eine START-Condition zu erzeugen. Ganz einfach: im ersten Schritt (1.) SCL von High nach Low bringen. Ist der Bus IDLE, so hat dies keine Bedeutung (ist insbesondere keine START-Condition). Ist der Bus belegt, so ist das einfach das Ende eines Bits. Solange nun SCL auf Low ist, darf ich mit SDA machen, was ich will - in diesem Fall also SDA auf Low (2.) bringen. Und kann jetzt die STOP-Condition problemlos erzeugen: SCL auf High gehen lassen (3.), danach SDA von Low auf High umschalten (4.)
Hallo Thomas, danke für Deine Erklärung. Sie hat mir heute sehr geholfen. Viele Grüße W.T.
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.