Hallo Leute,
ich programmiere zur Zeit ein STM32F4 Discovery Board, mit CubeMX und
HAL Treibern.
Folgendes Problem:
Ich sende im Sekunden-Takt zyklisch Daten über HAL_UART_TRANSMIT().
Empfangen tue ich mittels eines Interrupts. Jetzt folgendes Problem:
Wenn ich am senden bin und gleichzeitig was empfange, dann hängt sich
der Uart auf. Also die Senderichtung geht noch, aber Empfangen tue ich
nichts mehr.
Ich habe bereits rausgefunden das im Treiber selber ein HAL_LOCK
stattfindet, der den Uart daran hindert, sachen über den Interrupt
Eingang zu empfangen.
Ich bekomme es nicht hin dieses Problem zu lösen. Hat jemand einen
Ansatz oder dieses Problem auch schon gehabt?
Einfach schrecklich dieses HAL Zeugs, ich wills mir gar nicht
anschauen.
Ewig lange Bezeichner für Typen und Aufrufe, Overhead an
allen Ecken und Enden.
Meine selbstgeschriebenen Sourcen für interrupt-betriebenen
UART funktionieren ohne Probleme, und das ganz ohne HAL.
Marcus schrieb:> hilft mir aber zunächst leider nicht.
War mir schon klar, aber vielleicht hilft es für die
Zukunft zu der Einsicht einen anderen Ansatz zu wählen.
Das stimmt wohl :). Ich hänge nur leider schon etwas länger an dem
Problem, und bin auch kein Profi, was das Programmieren angeht. Wäre
nett, wenn sich jemand meiner Annehmen könnte.
Gruß Marcus
Hi, wie sieht denn deine Rx IRS aus.
Was hat du in der Funktion "void USART2_IRQHandler(void)" drinnenstehen?
Ich benutze auch den STM32F4 seit kurzem allerdings erst.
Ich sende und empfange ebenfalls, allerdings nicht gleichzeitig.
Es wird bei mir gesendet, Gegenstelle antwortet darauf und so weiter.
Bisher läuft das soweit ohne Probleme.
> Ich bekomme es nicht hin dieses Problem zu lösen. Hat jemand einen
Ansatz oder dieses Problem auch schon gehabt?
HAL_UART_Receive_IT ist eindeutig für den Aufruf aus main() gedacht und
funktioniert so nicht im UART Interrupt.
Entweder Du baust Dein Programm um, so das HAL_UART_Receive_IT nicht
mehr im Interrupt benutzt wird oder Du musst Dir eine Receive Funktion
passen selbst schreiben.
Ich überblicke jetzt nicht ob es ausreicht die __HAL_LOCK/__HAL_UNLOCK
zu entfernen.
Marcus schrieb:> Ich hänge nur leider schon etwas länger an dem> Problem, und bin auch kein Profi, was das Programmieren angeht. Wäre> nett, wenn sich jemand meiner Annehmen könnte.
Und wie stellst du dir das vor? Dir nen fertigen Code zu liefern, über
den du nicht nachzudenken brauchst?
Also erstens: Denke nach.. und zwar, wie man das gleichzeitige Senden
und Empfangen denn organisieren könnte - Hinweis: zwei Ringpuffer.
Zweitens: suche hier im Forum mal nach einschlägigen Beiträgen von mir
und deren Anhängen. Da ist nämlich öfters mal was fertiges dabei -
allerdings nicht exakt für deinen Controller. Aus sowas kannst du aber
lernen, wie man sowas macht.
Drittens: gib dir Mühe.
W.S.
me schrieb:> HAL_UART_Receive_IT>> Passt da meiner Meinung nach schon.
Das glaube ich eher weniger.
me schrieb:> Das musste ich da auch rein nehmen, ansonsten wird einmal empfangen und> dann nicht mehr.
Das ist das typische Trial-and-Error, was ab und an dazu führt, das
etwas in 95% der Fälle funktioniert.
Mein Gott, man muss doch nur in den Quelltext schauen
(stm32fxxx_hal_uart.c):
1
/*
2
...
3
(#) Non-Blocking mode API's with Interrupt are :
4
(++) HAL_UART_Transmit_IT()
5
(++) HAL_UART_Receive_IT()
6
(++) HAL_UART_IRQHandler()
7
8
...
9
(#) Non-Blocking mode transfers could be aborted using Abort API's :
10
(++) HAL_UART_Abort()
11
(++) HAL_UART_AbortTransmit()
12
(++) HAL_UART_AbortReceive()
13
(++) HAL_UART_Abort_IT()
14
(++) HAL_UART_AbortTransmit_IT()
15
(++) HAL_UART_AbortReceive_IT()
16
...
17
*/
Sowie einen Blick in den Header stm32fxxx_hal_uart.h:
Schaut man dann noch in den Code von HAL_UART_IRQHandler() stellt man
fest, dass von dort aus die Funktionen UART_Receive_IT() und
UART_Transmit_IT() (jeweils ohne HAL_-Präfix !) aufgerufen werden und
dafür sorgen das die Daten in bzw. aus pData (d.h. RX- bzw. TX-Buffer)
empfangen bzw. gesendet werden. Logischerweise sollte der RX-Buffer
größer sein als die Menge an Daten die man erwartet. Ist der RX-Buffer
aber nicht voll, kann man per HAL_UART_Receive_IT keine neue Transaktion
starten. Man muss zunächst die bestehende Transaktion per
HAL_UART_AbortReceive_IT() anhalten. Die Antwort warum das so ist findet
sich direkt in der ersten Zeile der HAL_UART_Receive_IT():
/* Check that a Rx process is not already ongoing */
4
if(huart->RxState==HAL_UART_STATE_READY)
5
{
6
//... Setup von Receive-Buffer, etc.
7
}
8
else
9
{
10
returnHAL_BUSY;
11
}
12
}
Also zusammengefasst:
HAL_UART_Receive_IT(), HAL_UART_Transmit_IT() sowie
HAL_UART_AbortReceive() gehören in deine main(). HAL_UART_IRQHandler()
dagegen gehört in die ISR und sorgt dafür, dass HAL_UART_Receive_IT()
sowie HAL_UART_Transmit_IT() überhaupt funktionieren können.
HAL_UART_Receive_IT() funktioniert aber nur einmal, wenn der Buffer
nicht vor dem zweiten Aufruf voll war oder es durch
HAL_UART_AbortReceive() händisch gestoppt wurde.
Danke Christopher!
@W.S. schreib einfach nichts wenn du nicht helfen willst. Gerade weil
man was lernen will schreibt man in dieses Forum. Bei jedem 2. Thread
findet man solche Internet Helden wie dich. Hauptsache du gibst deinen
Senf dazu.