Forum: Mikrocontroller und Digitale Elektronik I2C Master STM32 L0 und F3 Verständnisfrage zum Referenzhandbuch


von Stefan F. (Gast)



Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.)

von Stefan F. (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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