Forum: Mikrocontroller und Digitale Elektronik STM32F4xx UART-State während des Empfangs zurücksetzen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Folgende Frage:

Wie kann man den HW-UART-Empangsstatus eines STM32F4xx zurücksetzen, 
während er gerade ein Byte empfängt? Er soll dabei den nächsten 
Low-Pegel wieder als Startbit (und nicht als x-tes Datenbit) erkennen.

Ich arbeite nicht mit HAL, sondern mit SPL/CMSIS. Leider habe ich habe 
da selbst erstmal keinen passenden Ansatz gefunden.

: Bearbeitet durch Moderator
von Bauform B. (bauformb)


Lesenswert?

Jetzt brauchen wir einen Rechtsanwalt. Wenn da "SHOULD" statt "should" 
stände, wäre klar, dass es nicht verboten ist ;) Aber Versuch mach 
kluch...
1
The RE bit should not be reset while receiving data.
2
If the RE bit is disabled during reception, the reception
3
of the current byte will be aborted.

RM0383, 19.3.3 Receiver

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Bauform B. schrieb:
> Versuch mach kluch...

Vielen Dank!

Also, wenn ich das richtig verstanden habe, geht der harte Abbruch mit:
1
  UARTx->CR1 &= ~USART_CR1_RE;

Und dann das Wiederaufnahmen des Empfangs mit:
1
  UARTx->CR1 |= USART_CR1_RE;

Ich werde das ausprobieren und dann berichten.

: Bearbeitet durch Moderator
von Bauform B. (bauformb)


Lesenswert?

Naja, so verstehe ich die Bemerkung im Reference Manual. Wahrscheinlich 
braucht man noch ungefähr 1 Bit-Zeit Pause zwischen aus- und 
einschalten. Das meiste im UART läuft ja mit dem Baud-Clock und der Bus 
ist viel schneller.

von Harald K. (kirnbichler)


Lesenswert?

Frank M. schrieb:
> Wie kann man den HW-UART-Empangsstatus eines STM32F4xx zurücksetzen,
> während er gerade ein Byte empfängt?

Hmm. Aus irgendeinem Grund muss ich an die ACIA 6551 denken, die bei 
Aktivieren der Handshakeleitung mitten im gerade gesendeten Byte 
angehalten hat ... aber das ist natürlich was anderes als Du willst.

Nur: Wozu braucht man so etwas? Was für eine Art von 
Kommunikationsgegenstelle lässt so etwas zu, und woran erkennst Du, wann 
Du Deine Schnittstelle zurücksetzen willst?

von Mi N. (msx)


Lesenswert?

Frank M. schrieb:
> Ich arbeite nicht mit HAL, sondern mit SPL/CMSIS.

Sehr vernünftig.
Kurz das passende Bit in RCC->APB2RSTR setzen und wieder löschen und 
anschließend neu konfigurieren.

von Frank O. (frank_o)


Lesenswert?

Ich kann da nichts zu sagen, schreibe aber mal einen Satz, damit ich den 
Beitrag behalte.
Ist sehr interessant.

von Frank M. (ukw) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

Harald K. schrieb:
> Wozu braucht man so etwas?

RailCom, das ist UART auf Schienen mit 250000Bd mit 1 Startbit, 8 
Datenbits und einem Stoppbit. Ein Byte benötigt hier also rechnerisch 
40µs.

Gesendet werden RailCom-Daten von DCC-Lokdecodern in Austastlücken, wenn 
der Booster auf der Modellanlage nach jedem DCC-Kommando-Frame für knapp 
490µs offline geht. Im Kanal 1 senden alle railcom-fähigen 
Lokdecoder-Decoder 2 Bytes - und zwar gleichzeitig. Im Kanal 2 sendet 
nur die im DCC-Kommando adressierte Lok - und zwar bis zu 6 Bytes.

Steht nur eine Lok im Abschnitt, ist alles gut. Es werden im Zeitfenster 
von TTS1 bis TTC1 exakt zwei Bytes empfangen und anhand der 
Hamming-Codierung für gültig befunden.

Stehen mehrere Loks im Abschnitt und senden sie alle gleichzeitig - auch 
gut. Anhand der verwendeten Hamming-Codierung werden Kollisionen 
inhaltlich erkannt und rausgefiltert.

Stehen mehrere Loks im Abschnitt und sendet ein Lokdecoder davon etwas 
versetzt, zum Beispiel 20µs später: sehr schlecht. In dem Fall werden 
die ersten beiden empfangenen Bytes zwar eingelesen und dann wegen 
fehlerhafter Hammingcodierung wieder ignoriert. Bis dahin nicht schlimm, 
aber der Empfänger (STM32-Uart) in der Zentrale meint dann aber, hinter 
den 2 Bytes ein übriggebliebenes Datenbit des Nachzügler-Decoders als 
weiteres Startbit zu erkennen. Dem ist aber nicht so: Hier handelt es 
sich schlicht um übriggebliebenen Datensalat.

Das Blöde an der Situation ist, dass der UART im letzten Fall wegen dem 
vermeintlichen Startbit dann losrennt und oft dann noch das folgende 
Startbit und das erste Datenbit im Kanal 2 als 2 Datenbits mit einliest 
und damit "wegfrisst". Folge: Die Daten im Kanal 2 gehen auch noch 
kaputt, weil der UART aus dem Takt ist.

Vermeiden will ich das, indem ich zum Zeitpunkt TTC1 den Empfang 
weiterer Bits aus dem vermeintlichen 3. Datenbyte hart abbreche und den 
Empfänger zum Zeitpunkt TTS2 wieder einschalte. Dabei muss der UART 
bereits empfangene Bits verwerfen und damit seine interne Statemachine 
zurücksetzen.

: Bearbeitet durch Moderator
von Harald K. (kirnbichler)


Lesenswert?

OK. Das klingt ... eklig. Danke für die Erklärung, viel Glück damit.

von Walter T. (nicolas)


Lesenswert?

Frank M. schrieb:
> 250000Bd

Frank M. schrieb:
> STM32F4xx

Interessantes Thema. Im Notfall, wenn es die UART-Hardware nicht 
hergeben sollte, kannst Du ja immer noch direkt abtasten.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Bauform B. schrieb:
> If the RE bit is disabled during reception, the reception
> of the current byte will be aborted.

Ich habe das eingebaut und getestet. Das war erfolgreich. Eventuell 
übriggebliebener Schrott im Kanal 1 wird damit zuverlässig verworfen. 
Vielen Dank!

Mi N. schrieb:
> Kurz das passende Bit in RCC->APB2RSTR setzen und wieder löschen und
> anschließend neu konfigurieren.

Das habe ich wegen dem erfolgreichen Togglen des RE-Bits nicht weiter 
verfolgt. Klingt auch wesentlich aufwendiger, da der UART dann offenbar 
wieder neu initialisiert werden muss. Trotzdem Danke für den Tipp.

Harald K. schrieb:
> Das klingt ... eklig.

Ja, das ist es auch. Leider halten sich nicht alle Lokdecoder-Hersteller 
an die vorgegebenen Spezifikationen. Der Decoder, der hier die Probleme 
macht, hält sich hier nicht an die vorgegebenen Zeitbereiche. Leider 
sind Decoder dieses Herstellers aber weit verbreitet.

Walter T. schrieb:
> Interessantes Thema. Im Notfall, wenn es die UART-Hardware nicht
> hergeben sollte, kannst Du ja immer noch direkt abtasten.

Das habe ich auch schon in Erwägung gezogen, falls alle Stricke reissen 
und ich es mit dem HW-UART nicht hinbekomme. Dann gibts einfach einen 
SW-UART.  Dann muss man aber wegen der erforderlichen Baudrate und 
mindestens 3 Abtastungen pro Bit (1 Bit = 4µs) in den 
Mikrosekunden-Bereich runter. Eigentlich für einen STM32F4xx auch kein 
Problem, leider macht der "nebenbei" noch so einiges anderes, nämlich 
als Steuerzentrale zu fungieren. Glücklicherweise musste ich nicht zu 
diesem letzten Mittel greifen.

Frei nach dem Sprichwort: Wenn alle Stricke reissen, häng ich mich auf! 
;-)

von Frank O. (frank_o)


Lesenswert?

Frank M. schrieb:
> Frei nach dem Sprichwort: Wenn alle Stricke reissen, häng ich mich auf!
> ;-)

Der ist gut!

Mal ne blöde Frage: Aus der Modemzeit habe ich noch im Kopf, dass das 
doch verschiedene Modi bietet. Da war doch auch X-on/X-off. Da hat die 
andere Seite dann immer erst reagiert, wenn ein Signal dieser Art kam.
Wäre das noch eine Option.
Ist lange her, weiß das alles nicht mehr genau. War nur so eine Idee.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Frank O. schrieb:
> Aus der Modemzeit habe ich noch im Kopf, dass das doch verschiedene Modi
> bietet. Da war doch auch X-on/X-off.

Das nennt sich Software-Handshake:

Mit Xoff (^S) kannst Du einen sendenden UART anhalten, wenn Dir es als 
Empfänger zu schnell geht. Mit Xon (^Q) kannst Du ihn weitersenden 
lassen. Übliche Anwendung waren in den 80er Jahren serielle Terminals, 
wo der User den Output des Hosts durch Tippen von CTRL-S ausbremsen 
konnte. Wenn er den Output gelesen hatte, lies er den Output 
weiterlaufen duch Drücken von CTRL-Q. Das benutzten damals aber auch die 
Terminals selbst, wenn es denen schon bei 9600Bd zu flott ging. Das geht 
übrigens heute immer noch in einer Terminal-Sitzung eines Linux-Hosts. 
Einfach mal im PuTTY oder im X-Terminal "ls -lR /" eingeben und 
anschließend CTRL-S / CTRL-Q drücken.

Sonst sind SW-Handshake Anwendungen eher die Seltenheit geworden, da 
heutzutage die UART-Hardware wesentlich effizienter als damals arbeiten 
kann.

Das SW-Handshake hat auch nichts mit dem RailCom-Protokoll zu tun. Die 
Lokdecoder senden ohne Rücksicht auf Software-Handshakes (Xon/Xoff) oder 
etwaige Hardware-Handshakes. CTS/RTS-Signale kann es schon 
prinzipbedingt nicht geben, da nur eine 2polige Schiene vorhanden ist.

: Bearbeitet durch Moderator
von Frank O. (frank_o)


Lesenswert?

Danke! Genauso war es. Von RailCom-Protokoll habe ich hier zum ersten 
Mal gehört.

von Hans-Georg L. (h-g-l)


Lesenswert?

Frank M. schrieb:
> Bauform B. schrieb:
>> If the RE bit is disabled during reception, the reception
>> of the current byte will be aborted.
>
> Ich habe das eingebaut und getestet. Das war erfolgreich. Eventuell
> übriggebliebener Schrott im Kanal 1 wird damit zuverlässig verworfen.
> Vielen Dank!

Du darfst das RE erst wieder setzen wenn alles unerwünschte durch ist. 
Den direkt danach sucht er wieder nach Startbit. Aber ich denke das ist 
klar ...

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hans-Georg L. schrieb:
> Aber ich denke das ist klar ...

Jepp, ist klar. Zum Zeitpunkt TTC1 setze ich RE zurück, zum Zeitpunkt 
TTS2 setze ich es wieder.

von Harald K. (kirnbichler)


Lesenswert?

Frank M. schrieb:
> Leider halten sich nicht alle Lokdecoder-Hersteller
> an die vorgegebenen Spezifikationen.

Als ich mich das letzte Mal mit Loks beschäftigt hatte, war der 
"Decoder" darin ein Stromstoßrelais zur Fahrtrichtungsumschaltung ... 
Und die beiden geerbten Loks hatten einen kleinen von außen zugänglichen 
Hebel, mit dem man das Relais von Hand bedienen konnte, wofür auch 
immer.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Harald K. schrieb:
> Als ich mich das letzte Mal mit Loks beschäftigt hatte, war der
> "Decoder" darin ein Stromstoßrelais zur Fahrtrichtungsumschaltung ...

Ja, das sind/waren analoge Märklin Loks. Das Relais wurde mittels einer 
Überspannung zur Umschaltung der Fahrtrichtung betätigt.

> Und die beiden geerbten Loks hatten einen kleinen von außen zugänglichen
> Hebel, mit dem man das Relais von Hand bedienen konnte, wofür auch
> immer.

Diese Hebel zur manuellen Umschaltung der Fahrtrichtung wurden 
irgendwann in den 1960er Jahren abgeschafft. Die Loks dürften daher aus 
den 50er oder 60er Jahren sein. Bei gutem Erhaltenszustand könntest Du 
dafür sogar noch einen Erlös erzielen. Nein, ich will sie nicht ;-)

von Dieter S. (ds1)


Lesenswert?

Frank M. schrieb:
>
> Ja, das sind/waren analoge Märklin Loks. Das Relais wurde mittels einer
> Überspannung zur Umschaltung der Fahrtrichtung betätigt.

Ja, bei den alten Märklin Trafos hat man den Stellknopf von der 
Nullstellung ein paar Millimeter nach links gedreht, dann waren es ca. 
24 Volt AC anstelle der normalen Fahrspannung die bis etwas 16 Volt AC 
ging.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Dieter S. schrieb:
> Ja, bei den alten Märklin Trafos hat man den Stellknopf von der
> Nullstellung ein paar Millimeter nach link gedreht, dann waren es ca. 24
> Volt AC anstelle der normalen Fahrspannung die bis etwas 16 Volt AC
> ging.

Das waren schon die moderneren Märklin Trafos. Bei den Vorläufern musste 
man den Knopf einfach nur runterdrücken. Das ging bei jeder gerade 
eingestellten Geschwindigkeit und hat dazu geführt, dass die Loks dann 
einen richtigen Satz machten.

Bei dem von Dir beschriebenen Nachfolger musste man die Geschwindigkeit 
tatsächlich erst nach links drehen. Man hat halt aus Fehlern gelernt ;-)

Aber das wird hier langsam offtopic...

von Mi N. (msx)


Lesenswert?

Frank M. schrieb:
> Aber das wird hier langsam offtopic...

Dann stoppe ich das mal, allein schon, weil ich keine Eisenbahn habe :-(

Frank M. schrieb:
> Mi N. schrieb:
>> Kurz das passende Bit in RCC->APB2RSTR setzen und wieder löschen und
>> anschließend neu konfigurieren.
>
> Das habe ich wegen dem erfolgreichen Togglen des RE-Bits nicht weiter
> verfolgt. Klingt auch wesentlich aufwendiger, da der UART dann offenbar
> wieder neu initialisiert werden muss. Trotzdem Danke für den Tipp.

Für ein 8N1 USART muß doch überhaupt nicht viel initialisiert werden, da 
die default-Werte nach einem Reset meist schon passend sind. Typisch 
sind das CR-Register und Baudrate. Dazu noch Portpins und RCC-Takt.
Bei einem F4xx mit 100 MHz dauert das < 1 µs und, wenn man es geschickt 
anstellt, macht man diesen Reset gleich an den Anfang der 
init_usartx()-Routine. Ein erneuter Aufruf setzt alles auf Anfang, egal 
welcher 'Müll' dort vorher stand. Nützlich ist das insbesondere, wenn 
das RESET-Signal von SWD nicht angeschlossen ist. (Stichwort RP2040.)

Aber schön und einfach, wenn es mit dem RE-Bit funktioniert.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mi N. schrieb:
> Für ein 8N1 USART muß doch überhaupt nicht viel initialisiert werden,

Prinzipiell hast Du natürlich recht, aber ein RE-Pin-Toggle ist auch 
damit einfach nicht zu schlagen - gerade wenn ich das in einer Timer-ISR 
mache.

Ich habe mir Deinen Hinweis aber gemerkt - für ähnliche Situationen. 
Danke.

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.