Es geht um das angehängte Diagramm. Ich habe am vergangenen Wochenende Versucht, den I2C Port gemäß der Anleitung im Referenzhandbuch zu programmieren, also ohne HAL. Das hat überhaupt nicht richtig funktioniert. Er hat das Repeated-Start Signal nicht erzeugt und die Übertragung immer irgendwo abgebrochen. Offensichtlich habe ich die Diagramme völlig falsch verstanden. Dann habe ich eine Nacht drüber geschlafen, die Diagramme weg geschmissen und mir selbst einen Ablauf anhand des Textes zusammen gereimt. Dabei kam folgender auf Anhieb funktionierende Code heraus: http://stefanfrings.de/stm32/stm32f3.html#i2c Läuft also. Ich möchte trotzdem gerne klären, wo das Missverständnis lag. 1) Im ersten Diagramm teilt sich der Flow in zwei Threads auf. Links die Prüfung des NACK Flags, rechts das Übertragen der Nutzdaten. Das kann doch nicht so gemeint sein, dass ich beides wirklich in zwei Threads machen muss. Ich hatte daher in meiner Wiederholschleife zuerst das NACK Flag geprüft, und dann die Sachen auf der rechten Seite gemacht. War das falsch? 2) Wenn TXIS=1 ist, befülle ich TXDR mit dem nächsten Byte. Außerdem prüfe ich danach die Flags TC und TCR. Das kommt mir falsch vor. Sicher muss ich die anderen Flags auch prüfen, wenn TXIS nicht gesetzt ist. Denn nachdem ich z.B. das letzte Datenbyte an TXDR übergeben habe, geht weder das TC noch das TCR Flag auf High. Die brauchen dazu noch etwas mehr Zeit. Das dazu nötige Abwarten erkenne ich in dem Flow-Diagramm aber nicht. Da würde ich die Flags ja nur einmal sofort nach Übergabe eines Datenbytes prüfen. Weitere Datenbytes forder die Peripherie aber nicht ab (das letzte wurde ja bereits übergeben). 3) Die Rolle von AUTOEND ist mir unklar. In meinem Konkreten Fall sende ich zuerst viele Daten an einen I2C Slave und empfange danach viele Daten. Ich habe natürlich darauf geachtet, dass es mehr als 255 Bytes sind. Um die Variante für weniger als 255 Bytes wollte ich mich später kümmern. Jedenfalls habe ich erwartet, dass ich zuerst viele Daten mit AUTOEND=1 senden kann, dann folge ich dem zweiten Diagramm, wo ich START=1 setze (was einen Repeated-Start auslösen sollte) und dann viele Daten sende. Er hat aber stattdessen eine STOP + START Kombination auf dem Bus erzeugt. Außerdem hat er am Ende weder beim Senden noch beim Empfangen das TC Flag gesetzt. Mein Code hing daher in einer Endlosschleife fest, und zwar sowohl beim Senden als auch beim Empfangen. Ich musste eine Zusätzliche Abbruchbedingung einfügen (wenn alle bytes gesendet wurden). Nur war mir da dann nicht so ganz klar, wann genau alle Bytes gesendet wurden. jedenfalls offensichtlich nicht sofort nach der Übergabe an TXDR, bzw dem Lesen von RXDR. 4) Auch das TCD Signal verwirrt mich. Beim Senden geht es auf High, nachdem das Letzte Byte des Blockes (gemäß NBYTES) in TXDR geschrieben wurde. Aber beim Empfangen geht es viel zu früh auf High, nämlich schon nach dem ersten Byte - wenn ATOEND=1 ist. Wenn AUTOEND=0 ist, tritt das Problem nicht auf, dann geht es auch beim Empfang erst auf High, nachdem das letzte Byte (gemäß NBYTES) empfangen wurde. Anscheinen muss AUTOEND=0 sein, wenn man mehr als 255 Bytes empfangen will. Aber das Diagramm sagt (ganz unten) was anderes und ich habe dazu auch weder im Text noch im Errata einen relevanten Hinweis gefunden. 5) Laut Diagramm soll ich auf "End" gehen, wenn TCR nach dem Senden eines bytes nicht gesetzt ist. Das kann meiner Meinung nach nicht korrekt sein, denn TCR geht ja erst nach dem Senden des letzten Bytes auf High, um anzuzeigen, dass ich die Größe des nächsten Blockes festlegen muss. Das selbe Spiel auch beim Empfangen. 6) Verstehe ich es eigentlich richtig, dass "End" in dem Diagramm soviel wie "Abbrechen wegen Fehler" bedeutet? Wie ihr an dem verlinkten Artikel sehen könnte, habe ich inzwischen auf AUTOEND verzichtet. - Damit erzeugt er das Repeated-Start Signal korrekt. - TCR geht erst nach dem letzten Byte des Blockes auf High. - TC geht nach dem letzten Byte der Sendung (bzw. des Empfangs) auf High Mir ist bewusst, dass man das mit Interrupts und DMA eleganter machen kann. Damit möchte ich mich später befassen. Momentan reicht mir der blockierende Code, verbessern kann ich das später immer noch, wenn ich besser durchblicke. Falls jemand die Geduld hatte, diesen langen Text zu lesen und ihm sind dabei Fehler aufgefallen, bitte melden. Ich möchte nämlich gerne lernen, das Referenzhandbuch richtig zu lesen.
Stefanus F. schrieb: > Das kann doch nicht so gemeint sein, dass ich beides wirklich in zwei > Threads machen muss. Nein, du solltst beides parallel testen. Solange beide nicht gesetzt sind, wiederholst du diesen Test, bis eins von beiden gesetzt ist. Dann machst du an der entsprechenden Stelle weiter. (Den Rest habe ich mir jetzt noch nicht angesehen.)
Danke Jörg, damit ist schonmal ein Rätsel geklärt. Anders würde es für mich auch keinen Sinn ergeben. Die Test darunter sollten meiner Meinung nach auch alle quasi parallel stattfinden, nicht erst wenn und nachdem ein Byte übergeben wurde.
Ich hatte etwas mehr Feedback erhofft. Falls da jemand in den nächsten Tagen doch mal hereinschauen könnte, würde ich mich riesig drüber freuen.
Stefanus F. schrieb: > Ich hatte etwas mehr Feedback erhofft. Beim Rest kenne ich die STMs zu wenig, als dass ich sinnvoll was beitragen könnte, bspw. zu deiner Frage, warum man am Ende auf TC oder TCR warten soll, die in dem Moment noch nicht gesetzt sind.
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.

