Hallo zusammen,
ich versuche gerade ein bzw. mehrere Zeichen über die rs232 zu senden
und das im Interruptmodus. Das funktioniert auch schon mehr oder weniger
gut. Ich verwende dazu CooCox und die HAL library.
Controller: stm32f429ni
Was ich aber nicht verstehe ist folgender Befehl:
HAL_UART_Receive_IT(&UartHandle, rx_data, 1);
Muss der "Befehl" in der while(1) schleife stehen?? Dann ist das ja kein
richtiger Interrupt oder??
Außerdem muss man vorher die Anzahl der Zeichen angeben, die weiß ich ja
vorher noch nicht. Wie wäre denn das zu lösen.
Vielen Dank schonmal und schöne Grüße
So viele Fragen auf einmal :-)
Fangen wir mal an...
Stell erst mal bitte den Code vor. Also deine Routine +
HAL_UART_Receive_IT. Dann kann man schon mal sagen, wie diese
zusammenarbeiten.
"Normal" wäre: uC bekommt ein Zeichen per UART-Rx - Interrupt wird
ausgelöst - im INT_Handler wird das empfangene Byte "weggeschrieben"
(z.B. in ein Struct oder Buffer oder was auch immer)- in der
Haupschleife verarbeitet man das Byte
Thema String empfangen: entweder per DMA (einfache Lösung, wenn die
Länge des Strings vorher bekannt ist) oder Interruptgesteuert (dann muss
man die Routinen dafür aber selbst schreiben). Schau dir mal als erstes
das hier an, damit du mal eine Idee bekommst wie man sowas macht:
https://www.mikrocontroller.net/articles/FIFO
Die Funktion HAL_UART_Receive_IT sieht für mich aus, als ob hier eine
grosse und definierte Anzahl an Bytes empfangen werden soll. Der
Interrupt selber wird erst ausgeführt, wenn die x Bytes auch wirklich
empfangen wurden. Also Timeout und solches Zeugs müsstest du selber
handhaben.
Wenn du aber nicht weisst, wieviel Übertragen wird, dann würde ich
wieder "altmodisch" direkt den IRQ-Hanlder verwenden. Da hast du die
volle Kontrolle.
Vielen Dank für die Antworten aber leider bekomme ich das Ding nicht
richtig zu laufen.
Was ich immer noch nicht verstehe folgender Befehl:
HAL_UART_Receive_IT(&uart_config, rx_byte, 1);
Der muss scheinbar in der Hauptschleife stehen, sonst funktioniert
nichts. Das ist aber meiner Meinung nach dann keine Interruptsteuerung,
wenn ich das jedes mal aufrufen muss, oder?? Kann mir das jemand
erklären??
Hat vielleicht jemand ein simples Beispielprogramm mit der HAL library,
welches er posten kann!?
Danke schonmal.
elektro01 schrieb:> Was ich immer noch nicht verstehe folgender Befehl:> HAL_UART_Receive_IT(&uart_config, rx_byte, 1);>> Der muss scheinbar in der Hauptschleife stehen, sonst funktioniert> nichts. Das ist aber meiner Meinung nach dann keine Interruptsteuerung,> wenn ich das jedes mal aufrufen muss, oder?? Kann mir das jemand> erklären??
Der Thread ist zwar schon alt, wurde aber gerade in
Beitrag "Re: STM32 HAL Tutorial" referenziert und da
passt die Antwort besser hierhin.
Die Funktion HAL_UART_Receive_IT(&uart_config, rx_byte, 1); liefert
einen Status zurück der ausgwertet werden sollte. Wenn ein Receive
gestartet und noch nichts empfangen wurde wird die beim erneuten Aufruf
Busy zurückliefern. Im HAL_UART_RxCpltCallback() kann man ein Flag
setzen wenn der Empfang fertig ist (weil z.B. ein Endezeichen empfangen
wurde) und im Hauptprogramm kann man andere Sachen erledigen und
gelegentlich das Empfangsflag abfragen.
Aus dem anderen Thread:
technikus schrieb:> HAL_UART_Receive_IT(&UartHandle, rx_data, 10);>> Füllt fleißig den Puffer bis 10 Bytes empfangen wurden und beginnt dann> wieder von vorne - alles Interrupt gesteuert.>> Was ist aber, wenn ich in der Hauptschleife auslese ob schon was da ist> und dann den Startzeiger vom Puffer neu initialisieren möchte?> Qick and dirty kriege ich das hin, geht aber irgendwie am HAL Gedanken> vorbei...
Das halte ich für keine gute Strategie, das behandelt man besser in
einer Statemachine. Wenn das Protokoll über die Schnittstelle z.B. mit
fixem Header+Daten aufgebaut ist startest du einen Receive mit Anzahl
Headergrösse und setzt den Status auf 'STATE_RECEIVE_HEADER'. Im
RxCpltCallback wird dann nur der Status auf Header empfangen gesetzt.
Wenn das Hauptprogramm diesen Status erkennt startet es dann den Receive
mit der nötigen Anzahl Daten.
Danke für den konstruktiven Beitrag!
Nur was mache ich, wenn der Empfangspuffer mit z.B. 10 Zeichen definiert
ist, 9 empfangen werden und das Endzeichen nicht empfangen wird?
Dann müsste die Funktion ja nach einem Timeout den Puffer von vorne
füllen ?!
ja, timeout ist das Stichwort nachdem ich auch suchen würde. Im User
Manual ist ein Kapitel 'Timeout and error management'. Das wird für
mehrere Funktionen benutzt ist damit übergeordnet.
Im Kapitel UART ist noch ein 'how to use' da findest du schonmal eine
kurze Erklärung zum nötigen Ablauf. Und die Interrupt und DMA
(non-blocking) Funktionen können mit den Abort Funktionen abgebrochen
werden, damit muss man dann etwas spielen.
Wenn man ein Protokoll ohne Endezeichen hat kann man auch Blockweise mit
Timeout lesen, solche Protokolle finde ich aber weniger gut. Ansonsten
ist die Nutzung von Timeouts sehr zu empfehlen. Weil das mehr Aufwand
ist spart man sich das gerne, aber wenn der HAL das schon bietet sollte
man das auch mitnehmen.
Für mich macht das den Unterschied zwischen funktionierenden und
robusten Programmen aus: es gibt viele die tun was sie sollen, aber
einmal Stecker raus-rein und das Programm hängt und muss neugestartet
werden. Programmiere industrielle Steuerungen und du weisst was das
kostet...