Forum: Mikrocontroller und Digitale Elektronik STM32 UART HAL


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Studi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Heyho,

Ich versuche einen Chararray über UART an mein HTerm zu senden. 
Außerhalb der while schleife funktioniert es auch, in der while schleife 
scheint der UART bei dem senden fest zu stecken. Um genau zu sein bei
1
HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
2
{
3
  /* Wait until flag is set */
4
  while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status)
5
  {
6
    /* Check for the Timeout */
7
    if(Timeout != HAL_MAX_DELAY)
8
    {
9
      if((Timeout == 0U) || ((HAL_GetTick()-Tickstart) > Timeout))
10
      {
11
        /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
12
        CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE));
13
        CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
14
15
        huart->gState  = HAL_UART_STATE_READY;
16
        huart->RxState = HAL_UART_STATE_READY;
17
18
        /* Process Unlocked */
19
        __HAL_UNLOCK(huart);
20
        return HAL_TIMEOUT;
21
      }
22
    }
23
  }
24
  return HAL_OK;
25
}

Sitze seit ein paar Tagen an dem Problem. Weis nicht mehr weiter. Wieso 
wird kein Flag gesetzt?

von Studi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Meine Einstellungen für den USART2:
1
UART_HandleTypeDef huart2;
2
3
void MX_USART2_UART_Init(void)
4
{
5
  huart2.Instance = USART2;
6
  huart2.Init.BaudRate = 9600;
7
  huart2.Init.WordLength = UART_WORDLENGTH_7B;
8
  huart2.Init.StopBits = UART_STOPBITS_1;
9
  huart2.Init.Parity = UART_PARITY_NONE;
10
  huart2.Init.Mode = UART_MODE_TX_RX;
11
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
12
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
13
  HAL_UART_Init(&huart2);
14
15
16
}

Meine while schleife:
1
while(1)
2
  {
3
     scale(i);
4
     HAL_UART_Transmit(&huart2, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY);
5
     HAL_Delay(1000);
6
  }

Anscheinend wir das UART_FLAG_TXE nicht auf Reset gesetzt. Genau da 
hänge ich in der obrigen Schleife fest.
1
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
2
{
3
  uint16_t* tmp;
4
  uint32_t tickstart = 0U;
5
6
  /* Check that a Tx process is not already ongoing */
7
  if(huart->gState == HAL_UART_STATE_READY)
8
  {
9
    if((pData == NULL ) || (Size == 0U))
10
    {
11
      return  HAL_ERROR;
12
    }
13
14
    /* Process Locked */
15
    __HAL_LOCK(huart);
16
17
    huart->ErrorCode = HAL_UART_ERROR_NONE;
18
    huart->gState = HAL_UART_STATE_BUSY_TX;
19
20
    /* Init tickstart for timeout managment*/
21
    tickstart = HAL_GetTick();
22
23
    huart->TxXferSize = Size;
24
    huart->TxXferCount = Size;
25
    while(huart->TxXferCount > 0U)
26
    {
27
      huart->TxXferCount--;
28
      
29
      if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
30
      {
31
        return HAL_TIMEOUT;
32
      }

Außerhalb der while Schleife kann ich mit dem Befehl Transmit Daten 
schicken. Habe bis jetzt auch nichts auf Google gefunden.

von W.S. (Gast)


Bewertung
-4 lesenswert
nicht lesenswert
Studi schrieb:
> Heyho,

Alo-Ahe, Freddy.


Studi schrieb:
> Sitze seit ein paar Tagen an dem Problem. Weis nicht mehr weiter.

Also, wenn du weiter so mit diesem Zeugs:
1
while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status)
herummurkst, dann wirst du auch noch weitere Tage am Problem sitzen und 
weiterhin nicht weis sein.

Ich hatte hier schon des öfteren diverses auch zu den STM32 gepostet, 
unter anderem auch eine Art "Starter-Kit" für den STM32F103, wo eben 
auch ein funktionabler Lowlevel-Treiber für die UART's dabei war. Sowas 
brauchst du - und nicht ein Herumackern auf irgendwelchen 
Hal-Uart-Blabla-Funktionen und obendrein auch noch solch abenteuerliche 
Formulierungen wie oben gezeigt.

Bei mir heißt sowas schlicht
1
String_Out("Studi muß dazulernen", toUART0);
und das funktioniert (mit meinen I/O-Funktionen). Such einfach mal nach 
"STM32F103C8T6.ZIP"

W.S.

von Ruediger A. (Firma: keine) (rac)


Bewertung
0 lesenswert
nicht lesenswert
Hast Du die peripheral clock für den UART enabled?

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Bewertung
0 lesenswert
nicht lesenswert
W.S. schrieb:
> Ich hatte hier schon des öfteren diverses auch zu den STM32 gepostet,
> unter anderem auch eine Art "Starter-Kit" für den STM32F103, wo eben
> auch ein funktionabler Lowlevel-Treiber für die UART's dabei war.

Ja, mit Magic Numbers beim init.
Wenn also wer gaaaaanz leise sein sollte dann du!

von Apollo M. (Firma: @home) (majortom)


Bewertung
0 lesenswert
nicht lesenswert
W.S. schrieb:
> Such einfach mal nach
> "STM32F103C8T6.ZIP"

schlaumann poste hier mal bitte den link zu dem zip, mercy!


mt

von W.S. (Gast)


Bewertung
-2 lesenswert
nicht lesenswert
Mw E. schrieb:
> Ja, mit Magic Numbers beim init.
> Wenn also wer gaaaaanz leise sein sollte dann du!

Ich schätze mal, daß du derjenige bist, der ganz leise sein sollte und 
währenddessen mal ganz gründlich nachdenken sollte über den Zweck von 
Zahlen in einem Programm.

Also nicht gedankenlos nachplappern von allem, was dir mal jemand 
eingebleut hat, sondern kritisch hinterfragen. Und da ist meine Methode, 
sich auf so wenig Abhängigkeiten wie sinnvoll möglich einzulassen, 
allemal die weitaus bessere. Abgesehen davon hast du offensichtlich 
den eigentlichen Sinn der Konfigurations-C-Quelldatei nicht im 
geringsten kapiert.


Apollo M. schrieb:
> schlaumann poste hier mal bitte den link zu dem zip

Darf ich dir dann auch noch deine Firmware für lau schreiben? Ja?

W.S.

von Harry L. (mysth)


Bewertung
0 lesenswert
nicht lesenswert
Was ein Gefummel...

Versuchs mal so:
1
#define TIMEOUT 500 // Timeout in ms
2
3
uint8_t mystring[] = "Hello World!";
4
5
  HAL_UART_Transmit(&huart2, &mystring, sizeof(mystring), TIMEOUT);

HAL_UART_Transmit ist blockierend, und wartet max. TIMEOUT ms.

von pegel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Harry L. schrieb:
> Was ein Gefummel...

Würde ich auch sagen. Schien mir dann aber zu einfach gedacht.
Eigentlich versucht er nur die HAL_UART_Transmit Funktion nachzubauen.

Allerdings würde ich mystring vom Typ char nehmen und strlen() benutzen 
um flexibel zu sein in der Anzahl der Zeichen.

von Harry L. (mysth)


Bewertung
-1 lesenswert
nicht lesenswert
pegel schrieb:
> Allerdings würde ich mystring vom Typ char nehmen und strlen() benutzen
> um flexibel zu sein in der Anzahl der Zeichen.

HAL_UART_Transmit erwartet an der Stelle einen uint8_t *.

Aber mit strlen() hast du natürlich recht! (geht auch mit uint8_t *)
Bei meinem Beispiel würde er das \0 mitsenden...sorry - my fault.

Dann eben so:
1
HAL_UART_Transmit(&huart2, &mystring, strlen((char *)mystring), TIMEOUT);

Kann man so oder so machen - in jedem Fall muß man an einer Stelle 
casten.

: Bearbeitet durch User
von Studi (Gast)


Bewertung
0 lesenswert
nicht lesenswert
pegel schrieb:
> Würde ich auch sagen. Schien mir dann aber zu einfach gedacht.
> Eigentlich versucht er nur die HAL_UART_Transmit Funktion nachzubauen.

Nein wollte sie nur posten zur info.

Mein Problem ist, dass ich die Transmit-Funktion einmal in einer 
Dauerschleife aufrufen kann, das char einmal übermittelt wird und die 
Funktion dann fest steckt bei dem "waitonflag". Wenn ich zyklisch Daten 
auf den UART ausgeben möchte, ist es besser dies über Interrupt zu 
realisieren?

von Harry L. (mysth)


Bewertung
-1 lesenswert
nicht lesenswert
Studi schrieb:
> pegel schrieb:
>> Würde ich auch sagen. Schien mir dann aber zu einfach gedacht.
>> Eigentlich versucht er nur die HAL_UART_Transmit Funktion nachzubauen.
>
> Nein wollte sie nur posten zur info.
>
> Mein Problem ist, dass ich die Transmit-Funktion einmal in einer
> Dauerschleife aufrufen kann, das char einmal übermittelt wird und die
> Funktion dann fest steckt bei dem "waitonflag". Wenn ich zyklisch Daten
> auf den UART ausgeben möchte, ist es besser dies über Interrupt zu
> realisieren?

Wozu das ganze Gefummel?

Hit HAL_UART_Transmit() kannst du problemlos in einer Dauerschleife 
senden ohne selbst irgendwelche Flags berücksichtigen zu müssen.
Die Funktion kehrt erst zurück, wenn alle Daten übertragen wurden.

Natürlich ist es besser, sowas mit Interrupts zu machen, aber dann musst 
du dir auch dezu passende FIFOs bauen, und mir scheint, deine Probleme 
liegen im Moment noch auf einer ganz anderen Ebene.

Antwort schreiben

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

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.