Forum: Mikrocontroller und Digitale Elektronik Wie muss ich die Timeout-Dauer in den Funktionen HAL_UART_Transmit, HAL_UART_Receive berechnen?


von Max M. (koeltrad)


Lesenswert?

Der vierte Parameter in diesen Funktionen.
Im Internet habe ich folgende Beschreibung dieses Timeouts gefunden:
>The UART Transmit and Receive functions use flag polling. These are "blocking" 
>functions, i.e. the processor cannot proceed until the event has been successful. 
>The timeout parameter is the maximum time the processor is allowed to wait while 
>polling a flag. Without this feature the CPU would be hung if the process was 
>never completed.

>In the case of the HAL_UART_Transmit( ) it is unlikely that the process would be 
>hung unless there was a catastrophic hardware failure (e.g. the UART clock 
>failed).

>In the case of the HAL_UART_Receive( ) it is very possible that the expected 
>number of characters was never received and hence the function would timeout and 
>return to the calling program.

Wie berechnet man die Timeout-Dauer beim senden von Daten 
HAL_UART_Transmit?
Wie in der Beschreibung geschrieben, sollte die Verzögerung so lang 
sein, dass sich der UART auf die Datenübertragung vorbereiten kann.

Beim Empfang HAL_UART_Receive, wie ich aus der Beschreibung verstanden 
habe, erforderlich ein solches Timeout, damit alle Zeichen mit der 
aktuellen UART-Geschwindigkeit übertragen werden.

Zum Beispiel, wenn ich eine UART-Geschwindigkeit von 115200 Bits / s 
habe und ich 1000 Bits bekommen muss.
Also (1/115200)*1000==0.0086 sollte das Timeout so lang sein?
Während dieser Zeit, 0,0086 Sekunden, empfängt der UART 1000 Bits mit 
einer Geschwindigkeit von 115200 Bits/s.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Blockierende Funktionen sind nur für sehr einfachen Programmen geeignet. 
Sollen die Programme komplexere Aufgaben ausführen, dann stören 
Blockierungen extrem.

Für die UART legt man Sende- und Empfangspuffer an, die eine Paket 
halten können. Das Senden braucht kein Timeout, es ist irgendwann 
erfolgt.
Das Empfangen braucht bei einem vernünftigen Protokoll auch kein 
Timeout. Man parst ein empfangenes Pakte einfach erst dann, wenn das 
Paketende erkannt wurde. In beiden Fällen macht die CPU einfach mit den 
anderen Aufgaben weiter, d.h. sie wird nicht blockiert.

Blockierende Funktionen findet man vorrangig in Beispielprogrammen, die 
zeigen, wie man es nicht machen sollte.

Die Gegenstelle muß auch nicht alle Daten am Stück senden, sondern kann 
das Senden für wichtigere Sachen unterbrechen. Pausen in einem 
Datenstrom können also normal sein und dürfen den Empfang nicht 
vorzeitig abbrechen. Es kann sogar sein, daß man zum Test Sendedaten per 
Hand in ein Terminalprogramm eingibt.

: Bearbeitet durch User
von Bauform B. (bauformb)


Lesenswert?

Max M. schrieb:
> Zum Beispiel, wenn ich eine UART-Geschwindigkeit von 115200 Bits / s
> habe und ich 1000 Bits bekommen muss.
> Also (1/115200)*1000==0.0086 sollte das Timeout so lang sein?

Für Modbus muss der viel kürzer sein (ca. 35 Bits?). Aber normalerweise 
eher viel länger, weil:

Peter D. schrieb:
> Pausen in einem Datenstrom können also normal sein und dürfen
> den Empfang nicht vorzeitig abbrechen.


> Das Senden braucht kein Timeout, es ist irgendwann erfolgt.
außer:
- jemand schaltet den UART-Takt ab oder garnicht erst ein
- man verwendet den Hardware-Handshake
- die Baudrate ist 0 oder für die Anwendung viel zu niedrig
- TE ist 0
- Interrupts sind ggf. nicht eingeschaltet (NVIC & UART)

> Blockierende Funktionen findet man vorrangig in Beispielprogrammen, die
> zeigen, wie man es nicht machen sollte.

Wenn man mehrere Tasks laufen lässt, stört es allerdings überhaupt nicht 
;)

von Max M. (koeltrad)


Lesenswert?

Im Internet habe ich solche Beispiele gefunden:
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);
---------------------
HAL_MAX_DELAY==0xFFFFFFFFU==4 294 967 295
Sind das 4 294 967 295 Millisekunden?
4 294 967 295 Millisekunden sind 49 Tage.
49 Tage Timeout?

von Peter D. (peda)


Lesenswert?

Max M. schrieb:
> Im Internet habe ich solche Beispiele gefunden:

Schön.
Sinnvoller wäre allerdings, Du sagst uns auch wo (Link), für welches 
Target überhaupt und welche IDE/Compiler.

HAL_MAX_DELAY ist dem Namen nach der maximal mögliche Wert.

: Bearbeitet durch User
von Max M. (koeltrad)


Lesenswert?


von W.S. (Gast)


Lesenswert?

Max M. schrieb:
> Zum Beispiel, wenn ich eine UART-Geschwindigkeit von 115200 Bits / s
> habe und ich 1000 Bits bekommen muss.
> Also (1/115200)*1000==0.0086 sollte das Timeout so lang sein?
> Während dieser Zeit, 0,0086 Sekunden, empfängt der UART 1000 Bits mit
> einer Geschwindigkeit von 115200 Bits/s.

Deine komische Rechnung zeigt das Grundproblem: Die Leute denken wie 
Rumpelstilzchen. Heute back ich, morgen krieg ich 1000 Zeichen mit 
115000 Baud, übermorgen...

Nein, schon der Name des UART sollte hinreichend Grund sein, sich mehr 
Gedanken zu machen. Die Betonung liegt hier auf ASYNCHRON. Die Zeichen 
werden zu unbestimmten Zeiten gesendet und empfangen. Irgendeine 
Berechnung irgendeiner "Timeout-Zeit" ist also ne recht müßige 
Angelegenheit.

Mein Rat: mach es so, wie Peter es geschrieben hat und ignoriere deine 
komischen Funktionen "HAL_UART_Transmit( )" und "HAL_UART_Receive( )".

Je mehr ich hier von derartigem HAL-Zeugs lesen muß, desto klarer wird, 
daß das alles halbgarer Mumpitz ist und den Leuten nur mehr Probleme 
macht als ohne HAL.

W.S.

von Max M. (koeltrad)


Lesenswert?

>morgen krieg ich 1000 Zeichen mit
>115000 Baud
Keine Zeichen, sondern Bits.
Genau wie ich geschrieben habe:
>1000 Bits bekommen müssen.
115000 bps sind für mich 115000 bps.
Genau wie die Geschwindigkeit von 100 km/h bleibt die Geschwindigkeit 
von 100 km/h und ich habe die Berechnungen auf der Grundlage dieser 
Geschwindigkeit durchgeführt.

Möglicherweise führt der UART gleichzeitig mit der Datenübertragung 
andere Berechnungen durch, sodass die Datenübertragungszeit verlängert 
wird.
Das ist genau die Information, die ich suche. Denn das Timeout sollte 
wohl von diesen Prozessen abhängen.
Ja, es wurde mir schon geschrieben, dass sich der UART darauf 
vorbereiten muss, Daten zu senden bzw. zu empfangen, aber was genau 
bestimmt die benötigte Dauer für den Timeout.

von Bauform B. (bauformb)


Lesenswert?

Max M. schrieb:
> Möglicherweise führt der UART gleichzeitig mit der Datenübertragung
> andere Berechnungen durch, sodass die Datenübertragungszeit verlängert
> wird

Der UART nicht, höchstens das "halbgare HAL-Zeugs".

> Das ist genau die Information, die ich suche. Denn das Timeout sollte
> wohl von diesen Prozessen abhängen.

Nein.

> Ja, es wurde mir schon geschrieben, dass sich der UART darauf
> vorbereiten muss, Daten zu senden bzw. zu empfangen

Das dauert vor dem Senden des allerersten Datenbyte
 1 Startbit
 + die eingestellte Anzahl der Datenbits
 + die eingestellte Anzahl der Stoppbits
 + das Startbit des ersten Bytes.
Bei allen folgenden kostet es nur noch das Startbit. Zusätzlich gibt es 
zwischen zwei Datenbytes immer eine Pause von 1 oder 2 Stoppbits.

> aber was genau bestimmt die benötigte Dauer für den Timeout.

Die Anwendung, nicht die UART-Hardware, lies nochmal dieses:

Peter D. schrieb:
> Die Gegenstelle muß auch nicht alle Daten am Stück senden, sondern kann
> das Senden für wichtigere Sachen unterbrechen. Pausen in einem
> Datenstrom können also normal sein und dürfen den Empfang nicht
> vorzeitig abbrechen. Es kann sogar sein, daß man zum Test Sendedaten per
> Hand in ein Terminalprogramm eingibt.

von W.S. (Gast)


Lesenswert?

Max M. schrieb:
> Möglicherweise führt der UART gleichzeitig mit der Datenübertragung
> andere Berechnungen durch,...

Der UART führt gar keine Berechnungen durch. Jedes Zeichen wird mit 
einem Startbit begonnen und mit 1 oder 1,5 oder 2 Stopbits beendet. Und 
so werden die Zeichen auch empfangen.

Aber das Erbsenzählen bei den Bits ist komplett die falsche Baustelle. 
Denke lieber daran, daß dein UART die Zeichen kriegt von einer anderen 
Instanz und daß er eben deshalb nicht selbst die Zeitspanne bestimmen 
kann, wann denn die Zeichen bei ihm eintrudeln. Genau deshalb ist die 
gesamte Denke hinter einer Funktion, die Zeichen zu einem bestimmten 
Zeitpunkt haben will und sonst das Warten mit einem Timeout beendet, 
grundfalsch. Ganz gleich, wie du deinen Timeout-Wert berechnen willst.

Verstehe du mal die Grundprinzipien.

W.S.

von c-hater (Gast)


Lesenswert?

W.S. schrieb:

> Nein, schon der Name des UART sollte hinreichend Grund sein, sich mehr
> Gedanken zu machen. Die Betonung liegt hier auf ASYNCHRON. Die Zeichen
> werden zu unbestimmten Zeiten gesendet und empfangen.

Ähem, nö.

Das "asynchron" in UART hat rein garnix mit den Versandzeitpunkt 
einzelner Datenwörter zu schaffen. Es kennzeichnet einfach nur die 
Tatsache, dass die UART-Kommunikation keine Taktleitung benötigt.

Deswegen gibt es z.B. bei den AVR auch eine "USART", denn die kann 
sowohl mit als auch ohne Taktleitung arbeiten, also sowohl synchron als 
auch asynchron. Auf die Möglichkeit, Datenwörter im Prinzip zu 
beliebigen Zeitpunkten zu transferieren hat das exakt Null Einfluss.

von Max M. (koeltrad)


Lesenswert?

> 1 Startbit
> + die eingestellte Anzahl der Datenbits
> + die eingestellte Anzahl der Stoppbits
> + das Startbit des ersten Bytes.

Das weiß ich.
+ Paritätsbit.
>Pausen in einem Datenstrom können also normal sein
+ Mögliche Pausen.

Ich muss eine Zahl in die Funktionen HAL_UART_Transmit und 
HAL_UART_Receive schreiben
Welche Zahl soll ich schreiben, wenn ich das Wort "Hallo" senden oder 
empfangen möchte?
>Das Senden braucht kein Timeout, es ist irgendwann
>erfolgt.
>Das Empfangen braucht bei einem vernünftigen Protokoll auch kein
> Timeout.
Wenn die Funktion einen solchen Parameter hat, muss ich ihn eingeben.
Ich kann den Mindestparameter eingeben und hoffen, dass alles korrekt 
funktioniert.
Aber ich möchte nicht den minimalen Parameter eingeben, sondern den 
korrekt berechneten Parameter.

von W.S. (Gast)


Lesenswert?

c-hater schrieb:
> Das "asynchron" in UART hat rein garnix mit den Versandzeitpunkt
> einzelner Datenwörter zu schaffen.

Eigentlich doch: Das Format, in dem gesendet wird, ist dazu ausgelegt, 
daß die Zeichen zu beliebigen, vom Empfänger nicht voraussehbaren Zeiten 
hereinkommen, weswegen jedes Byte mit einem Synchronisations-Konstrukt 
umgeben sein muß, damit man es überhaupt richtig empfangen kann.

W.S.

von c-hater (Gast)


Lesenswert?

W.S. schrieb:

> Das Format, in dem gesendet wird, ist dazu ausgelegt,
> daß die Zeichen zu beliebigen, vom Empfänger nicht voraussehbaren Zeiten
> hereinkommen, weswegen jedes Byte mit einem Synchronisations-Konstrukt
> umgeben sein muß, damit man es überhaupt richtig empfangen kann.

Das stimmt natürlich, es gibt einen Wordframe, das wir wohl niemand 
abstreiten. Aber das ist eben nicht der Anlass für das "A" in "UART". 
Nur die logische Folge für eine praktisch brauchbare Schnittstelle.

von W.S. (Gast)


Lesenswert?

Max M. schrieb:
> Ich muss eine Zahl in die Funktionen HAL_UART_Transmit und
> HAL_UART_Receive schreiben
> Welche Zahl soll ich schreiben, wenn ich das Wort "Hallo" senden oder
> empfangen möchte?

Also, da du offensichtlich bereits damit deine Probleme hast: Setze die 
Zeit auf so etwa 5 Minuten oder mehr. Da hast du genug Zeit, alle Kabel 
zurechtzulegen, den PC einzuschalten und dein PC-Programm zu starten.

Aber wenn du es irgendwann mal richtig machen willst, dann lerne, deinen 
eigenen Weg zu gehen und dir ordentliche Treiber für deinen µC und 
dessen UARTs zu schreiben. Ohne solche blockierenden Funktionen.

W.S.

von Peter D. (peda)


Lesenswert?

Max M. schrieb:
> Welcher Compiler ist mir nicht bekannt.

Quatsch.
Du mußt doch wissen, welchen Chip Du nehmen willst und wie die IDE 
heißt, in der Du programmierst.
Die HAL-Namen sind allgemein gebräuchlich, die sagen nichts darüber aus.

von Peter D. (peda)


Lesenswert?

Max M. schrieb:
> Wenn die Funktion einen solchen Parameter hat, muss ich ihn eingeben.

Du kannst aber nicht blockierende Funktionen nehmen, die es in Deiner 
unbekannten IDE bestimmt auch gibt.
Blockierende Funktionen kann man nur unter Multitasking sinnvoll nutzen, 
wo dann das OS die CPU-Zeit an andere Tasks aufteilt.

von Vincent H. (vinci)


Lesenswert?

Peter D. schrieb:
> Max M. schrieb:
>> Wenn die Funktion einen solchen Parameter hat, muss ich ihn eingeben.
>
> Du kannst aber nicht blockierende Funktionen nehmen, die es in Deiner
> unbekannten IDE bestimmt auch gibt.
> Blockierende Funktionen kann man nur unter Multitasking sinnvoll nutzen,
> wo dann das OS die CPU-Zeit an andere Tasks aufteilt.

Du kennst doch die Anforderungen gar nicht? Ich find es ja prinzipiell 
gut Nutzer auf solche Dinge hinzuweisen aber du hast es jetzt geschafft 
4x Postings mit zwar sinnvollen Infos zu schreiben die aber die 
Eingangsfrage überhaupt nicht beantworten.

@Max M.
Ich glaub das Verständnisproblem besteht darin, dass du denkst das 
Timeout sei eine Grundeigenschaft der UART Peripherie. Tatsächlich hat 
dieser Wert mit der Schnittstelle aber überhaupt nichts zu tun. Im 
Gegenteil, das Timeout wird mit Hilfe des SysTicks des CPU Cores 
berechnet und dient lediglich dazu im Fehlerfall der Schnittstelle den 
Sende- oder Empfangsversuch abzubrechen. Die HAL Library versucht hier 
einfach etwas defensiv zu sein um nicht bei jeder Kleinigkeit das 
komplette Programm zum Stillstand zu bringen. Eine Analogie dazu wäre 
etwa ein Timeout beim Besuchen einer Website. Dort käme auch niemand auf 
die Idee den Wert auf Grund der Bandbreite und Latenz zu berechnen...

von Peter D. (peda)


Lesenswert?

Vincent H. schrieb:
> aber die
> Eingangsfrage überhaupt nicht beantworten.

Weil ich mich nicht in die Nesseln setzen will, wenn es doch nicht 
klappt.
Die Berechnung rein nach der maximal möglichen Datenrate ist viel zu 
kurz gedacht.
Ein Timeout müßte vorrangig den unbekannten Sender berücksichtigen, d.h. 
wie lange der maximal braucht, um noch andere Tasks abzuschließen, die 
Anfrage zu parsen, die Antwort zu basteln und schließlich die Antwort 
abzusenden.

Um eine Übertragung zuverlässig zu machen, benutze ich daher keine 
zeitgesteuerten, sondern nur zustandsgesteuerten Protokolle, d.h. allein 
der Inhalt des Datenstromes ist entscheidend. Damit lassen sich Daten 
auch bequem über andere Schnittstellen (CAN, Ethernet, Funk usw.) 
tunneln.
Erst in höheren Protokollschichten wird ausgewertet, ob ein Paket 
unvollständig, fehlerhaft oder ganz ausgefallen ist.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Peter D. schrieb:
> Du mußt doch wissen, welchen Chip Du nehmen willst und wie die IDE
> heißt, in der Du programmierst.

Ich vermute mal, daß der Max das tatsächlich nicht weiß. Die Leute hier 
schreiben immer etwa sowas:
"Ich will mit Mikrocontroller anfangen, welche IDE soll ich am besten 
nehmen?"
Daß der eigentliche Job des Übersetzens von einem Bündel aus Assembler, 
Linker, Compiler usw. nebst Laufzeitbibliotheken für den Compiler 
erledigt wird und eine IDE eigentlich das Nebensächlichste ist, das 
begreifen sie nicht.

Obendrein fehlt auch das Grundverständnis für den Chip, für den man eine 
Firmware zu machen gedenkt. Dann kommen wilde Vermutungen auf wie z.B. 
ob und was für Berechnungen ein UART wohl macht. Selbst DU bist da mit 
Verständnisproblemen dabei:

Peter D. schrieb:
> Du kannst aber nicht blockierende Funktionen nehmen, die es in Deiner
> unbekannten IDE bestimmt auch gibt.

Also, in einer IDE gibt es z.B. einen Texteditor und eine 
Projektverwaltung, aber keine "blockierenden Funktionen".

W.S.

von Peter D. (peda)


Lesenswert?

W.S. schrieb:
> Also, in einer IDE gibt es z.B. einen Texteditor und eine
> Projektverwaltung, aber keine "blockierenden Funktionen".

In einer IDE gibt es in der Regel aber eine Hilfe (Wizard), die z.B. die 
HAL-Funktionen aus den Includes auflisten kann.

Als ich 1989 mit Turbo-C unter MS-DOS angefangen habe, habe ich auch 
noch nichts auswendig gekannt. F1 gedrückt und los gings. Hilfe in einer 
IDE ist also schon steinalt.

von J. S. (jojos)


Lesenswert?

Das Timeout in den Routinen ist sehr praktisch. Man muss aber auch nicht 
eine Message in einem Rutsch empfangen/senden, Man kann auch erstmal auf 
ein Zeichen mit kurzem oder ohne Timeout warten. Wenn das angekommen 
ist, dann den Rest mit Timeout für Messagelänge * x lesen, wobei x wie 
PeDa schrieb auch vom Gegner abhängt. Wenn es um kurze Messages geht, 
dann werden die typisch in einem Rutsch gesendet und man braucht nicht 
immer eine Statemachine für die Auswertung. Das ist auch robust, ich 
habe über 20 Jahre mit verschienen SPS nach diesem Prinzip geredet und 
das geht.
Und Suspekt sind mir vor allem Leute die immer noch das alberne HAL 
Bashing betreiben und das einfache Schmema der HAL nicht durchblickt 
haben:
es gibt die Treiber in 3 Geschmacksrichtungen: ohne Suffix für 
Blockieren mit Timeout, mit Suffix _IT für Interruptgetrieben und mit 
Suffix _DMA für tadaaa: mit DMA. Und das sehr konsequent für die meisten 
Schnittstellen.

von Max M. (koeltrad)


Lesenswert?

Peter D. schrieb:
> Quatsch.
> Du mußt doch wissen, welchen Chip Du nehmen willst und wie die IDE
> heißt, in der Du programmierst.
Ich meinte, dass ich nicht weiß, welcher Compiler hier verwendet wurde
https://cpp.hotexamples.com/de/examples/-/-/HAL_UART_Transmit/cpp-hal_uart_transmit-function-examples.html
Ich habe diesen Code nicht verwendet, also spielt es keine Rolle, 
welchen Compiler ich habe.
Bei mir: IAR, Cube-IDE, Keil.
Vincent H. schrieb:
> Ich glaub das Verständnisproblem besteht darin, dass du denkst das
> Timeout sei eine Grundeigenschaft der UART Peripherie.
Vielen Dank für den Versuch zu verstehen, was ich nicht verstehe, aber 
ich verstehe, dass der UART selbst das Timeout nicht steuert.
Ja, ich drücke mich wahrscheinlich falsch aus, da ich das Thema nicht 
vollständig kenne.
J. S. schrieb:
> Man kann auch erstmal auf
> ein Zeichen mit kurzem oder ohne Timeout warten. Wenn das angekommen
> ist, dann den Rest mit Timeout für Messagelänge * x lesen, wobei x wie
> PeDa schrieb auch vom Gegner abhängt.
Am Anfang suchte ich nach einer genauen Antwort auf das, was Sie hier 
beschrieben haben. Mit Zahlen.
Leider kann ich mit dieser Formel Messagelänge * x lesen nichts 
berechnen.
J. S. schrieb:
> es gibt die Treiber in 3 Geschmacksrichtungen: ohne Suffix für
> Blockieren mit Timeout, mit Suffix _IT für Interruptgetrieben und mit
> Suffix _DMA für tadaaa: mit DMA. Und das sehr konsequent für die meisten
> Schnittstellen.
Aber ich muss diese Frage wahrscheinlich zuerst studieren. Vielen Dank.

von J. S. (jojos)


Lesenswert?

Max M. schrieb:
> Leider kann ich mit dieser Formel Messagelänge * x lesen nichts
> berechnen.

Die Berechnung im ersten Post war ja richtig, nur das man dem Sender 
etwas mehr Zeit geben muss. Es kann sein das der zwischen den Zeichen 
etwas Zeit braucht oder beim Senden unterbrochen werden kann. Damit muss 
das Timeout mindestens so lang sein wie die Übertragungszeit, maximal so 
lange wie man sich ein blockieren erlauben möchte. Wenn das Programm 
(oder die Task beim RTOS) nichts anderes machen muss, dann kann man auch 
unendlich auf die Anz. Zeichen warten.

Zum Empfang mit Interrupt mit STM HAL gibt es viele Tutorials. Da muss 
der µC die Zeit nicht totschlagen, man lässt sich benachrichtigen wenn 
die Anzahl Zeichen angekommen sind.

von foobar (Gast)


Lesenswert?

Diese Timeouts dienen in den meisten Fällen der Fehlererkennung.  Sie 
sind eine Festlegung des Programms.  Beispielsweise schickst du ein 
Kommando an ein Modem und erwartest eine Antwort.  Das ganze (Senden und 
Empfangen) läuft normalerweise in 0.1s.  Als Limit definierst du 1s. 
Falls das Modem nicht reagiert, willst du dann eine Fehlerbehandlung 
durchführen.  Also setzt du bei jedem TX und RX ein Timeout für die 
verbliebene Restzeit.

Es gibt auch mal den Fall, wo Timeouts als lose Entscheidungshilfe 
benutzt werden.  Beispielsweise bei einem Terminal die Unterscheidung, 
ob die Escape- (^[) oder eine Cursor-Taste (^[ [ x) gedrückt wurde. 
Wenn nach dem ^[ nicht innerhalb von z.B. 0.1s ein [ kommt, war es die 
Escape-Taste (Menschen tippen nicht so schnell), ansonsten eine 
Cursor-Taste.  Normales RX mit Timeout unendlich, nach Empfang eines ^[ 
ein Timeout von 0.1s.  Auch hier eine Festlegung deines Programms.

Oder du willst was zu einem bestimmten Zeitpunkt durchführen (z.B. 
Cursor blinken lassen) - dann kannst du dem RX/TX ein Timeout mitgeben, 
so dass er zum passenden Zeitpunkt zurückkommt.  Du musst natürlich 
schon darauf aufpassen, dass dabei keine Daten verloren gehen.

Und dann gibt es Protokolle, die Zeitvorgaben fest eingebaut haben 
(end-of-packet-marker etc).  Bei denen sind die Zeiten fest vorgegeben 
und du musst dich an die Vorgaben halten.  Dabei kann es dann auch 
wichtig werden, ob die Genauigkeit deines Timeouts überhaupt ausreichend 
ist (z.B. 15-Bitlängen Idle erkennen könnte schwierig werden) - solche 
Protokolle werden deshalb oft in HW implementiert.

Du merkst, außer im letzten Fall spielt die Baudrate meist keine Rolle - 
es geht da nicht im Bitzählerei sondern um Anforderungen deines 
Programms.

von Peter D. (peda)


Lesenswert?

Ein Timeout ist immer eine Krücke.
Will man Daten zuverlässig empfangen, muß man das Protokoll 
implementieren. Dazu nimmt man eine Task, die das Zeichen in einen 
Puffer schreibt, sobald die UART >= 1 Zeichen empfangen hat. Dazu 
benötigt man eine HAL-Funktion, die das meldet, ohne zu blockieren. 
Lesen kann man es dann mit HAL_UART_Receive(..., 0).
Danach überprüft man lt. Protokoll, ob es das Ende eines Paketes war und 
parst es dann. Ansonsten terminiert die Task bis zum nächsten Byte.
Damit ist es egal, wie lange das Empfangen dauert.

von foobar (Gast)


Lesenswert?

> Ein Timeout ist immer eine Krücke.

Solche Timeout-Basierenden APIs sind Krücken, ja (nicht Timeouts an 
sich).  Aber auch Krücken dürfen Bedienungsanleitungen haben ;-)  Und es 
ist erstaunlich, wie weit man mit denen kommen kann.

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.