Hi,
Ich möchte gerne über die UART Schnittstelle Daten empfangen und dazu
die HAL Libraries verwenden. Nun kann man ja in CubeMX den UART
aktivieren und mit HAL_UART_Receive_DMA(u, &rx_buff, BUFFSIZE_RX)
aktiviert man den DMA. Ich habe den Circular Mode aktiviert, damit es
den vollen Buffer wieder überschreibt. Jetzt löst mir void
DMA1_Channel5_IRQHandler(void){...} nur aus, wenn der Buffer auch voll
ist und sonst nicht. Was ich möchte ist, dass ich jedes mal, wenn ich
einen String über den UART sende, ich den ganzen in den rx_buff bekomme
und dann ein Interrupt aktiviert wird, so dass ich die Daten verwenden
kann. Die gesendeten Daten sind nicht alle gleicher Länge. Doch wie
mache ich das genau?
@Bert Siegfried (kautschuck)
>den vollen Buffer wieder überschreibt. Jetzt löst mir void>DMA1_Channel5_IRQHandler(void){...} nur aus, wenn der Buffer auch voll>ist und sonst nicht.
Logisch.
> Was ich möchte ist, dass ich jedes mal, wenn ich>einen String über den UART sende,
Empfange.
> ich den ganzen in den rx_buff bekomme>und dann ein Interrupt aktiviert wird, so dass ich die Daten verwenden>kann.
Dafür brauchst du einen IRQ-Handler, der bei jedem ankommenden Zeichen
prüft, ob das Stringende erreicht ist, meist mit '\r'. Für diese Art des
Datenempfangs kann man keinen DMA nutzen.
> Die gesendeten Daten sind nicht alle gleicher Länge.
Vom PC bzw. der Gegenstelle gesendet.
> Doch wie> mache ich das genau?
Siehe oben.
Bert S. schrieb:> Aber irgend eine Möglichkeit muss es ja> geben
Ja die gibt es.
Wenn man DMA für den Empfang nutzt, kann man einfach nicht wissen wie
lang die zu Empfangenen Daten sind - daür gibt es in der USART/UART die
"Receiver timeout" Funktion (Interrupt).
Näheres müsstest du deinem Datenblatt entnehmen.
Funktionsweise:
- DMA für Empfang initialisieren
- Timeout Funktion so konfigurieren, dass sie bei jedem empfangenen Byte
neustartet,
Wird nun nichts mehr empfangen, schlägt der Interrupt nach der
gewünschten Timeout-Zeit zu und dan kannst die Daten aus deinem DMA
Buffer verwenden.
Ich habe jetzt mal den Interrupt Ansatz probiert, doch auch hier wirkt
wieder der Ringbuffer. Sagen wir ich empfange jetzt ein Wort und dann
ein /0, dann möchte ich ja eine Funktion aufrufen, dort den Befehl
abarbeiten und anschließend rx_data zurücksetzen. Doch wie genau
bewerkstellige ich das zurücksetzen des Pointers von rx_data?
Bert S. schrieb:> doch auch hier wirkt> wieder der Ringbuffer
Dies wird auch immer so bleiben, wenn du die Funktion für den
Empfangs-Timeout deiner USART nicht konfigurierst.
Beachte: Nicht jede USART bestitzt diese Funktion (siehe Datenblatt).
Welcher STM32 ist bei dir verbaut?
Hab auf Github eine "stm32f0xx_hal_usart.h" gefunden, in dieser Datei
(HAL) ist die Funktion des "Empfangs-Timeouts" gar nicht implementiert,
obwohl der µC diese unterstützt.
Du würdest zwei Interrupts behandeln müssen, bzw. beide Zustände
betrachten.
- Interrupt für: gewünscht DMA Datenlänge empfangen
- Interrupt für: Empfangs-Timeout (Register: USART_ISR / Bit 11: RTOF)
Den globalen UASRT_IRQHandler zu nutzen ist gut. Darin müsstest du
prüfen welcher von beiden Fällen aufgetretten ist.
Im Vorfeld musst du natürlich die USART richtig konfigurieren (inkl.
Timeout), sollten in deiner HAL keine Funktionen für den Timeout
vorhanden sein, musst du entweder direkt die Register beschreiben oder
die HAL erweitern.
Hast du dir mal den Abschnitt "Universal synchronous asynchronous
receiver
transmitter (USART)" im Datenblatt überhaupt mal durchgelesen?
Dort ist nämlich beschrieben wie dieser Timeout funkioniert.
Nebenbei:
Weiterhin sollte dir klar sein, dass du den Empfang, Verarbeitung und
Versenden nicht alles in deinem Interrupt abarbeiten solltest.
Wenn ich auf einem STM32 mit den HAL Libraries einen UART Interrupt
auslöse, dann wird für tx und rx die gleiche Callback Funktion
aufgerufen, nämlich USART1_IRQHandler(). Doch welche Flags muss ich nun
überprüfen, ob es sich um rx oder tx handelt?
Warum nutzt du nicht dein Beitrag von gestern? Es handelt sich ja wohl
immer noch um gleiches Problem.
Da kommt es drauf an was du wissen möchtest.
RX und TX haben viel mehr Unterteilungen:
(siehe Datenblatt - Register: USART_ISR)
Danke, ich werde mir den Abschnitt "Universal synchronous asynchronous
receiver transmitter (USART)" mal genau durchlesen.
Vebraut ist eine STM32F303K8T6.
Also ich hab mir grad mal das HAL Paket "STM32Cube_FW_F3_V1.9.0"
heruntergeladen und da ist die Timeout Funktion nicht implementiert.
Wirst nicht drum herum kommen, es zu verstehen und selbst zu
implementieren.
Aber so ein Hexenwerk ist es auch wieder nicht.
Wenn du dein DMA RX Interrupt schon hast, kommt das mit dem Timeout
eigentlich nur noch hinzu.
Wenn er richtig konfiguriert ist und läuft - und du dann nur ein Zeichen
sendest obwohl du per DMA auf 10 wartest, wird nach kurzer Zeit dein
Timeout Interrupt zuschlagen.
Je nach dem wie die Datenübertragung geartet ist könnte man evtl. bei
jedem Systick an der letzten beschriebenen Position des Ringpuffers
nachschauen ob das Schlußzeichen empfangen wurde und die Verarbeitung
auslösen.
Das wird dir aber bei deinem DMA und Timeout nicht weiterhelfen, aber
vllt. kommst du ja jetzt drauf wie und welche Interrupts du benötigst.
Nett, jetzt lerne ich auch noch nebenbei ST µC zu programmieren und die
Library :-D
Wo der Interrupt herkommt verrät dir das Interrupt Status Register (ISR)
des jeweiligen UART und um ein Bit in einem Register abzufragen benötigt
es meiner Meinung nach auch keiner Library und erst recht nicht zwei
Libraries.
1
if(UART1->ISR&UART_ISR_TXE){
2
// TX(-Buffer) empty, d.h. es wurde etwas versendet
3
}
4
5
if(UART1->ISR&UART_ISR_RXNE){
6
// RX(-Buffer) not empty, d.h. es wurde etwas empfangen
7
}
Der Interrupt feuert aber grundsätzlich nur dann wenn die entsprechenden
Bits im Configuration Register 1 des jeweiligen UARTs gesetzt sind
(siehe 29.7 in RM0360 bzw. 29.8.1 und 29.8.8 für CR1 und ISR).
Auch für STs HAL gibt es ein User-Manual. Für die F3-Familie wäre das
z.B. www.st.com/resource/en/user_manual/dm00122016.pdf
Siehe dort Kapitel 54.2 "UART Firmware Driver API Description"
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang