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
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
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 ;)
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?
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
Welcher Compiler ist mir nicht bekannt. https://cpp.hotexamples.com/de/examples/-/-/HAL_UART_Transmit/cpp-hal_uart_transmit-function-examples.html
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.
>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.
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.
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.
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.
> 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.
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.
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.
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.
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.
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.
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...
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
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.
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.
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.
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.
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.
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.
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.
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.