Forum: Mikrocontroller und Digitale Elektronik STM32 UART HAL


von Studi (Gast)


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)


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)


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)


Lesenswert?

Hast Du die peripheral clock für den UART enabled?

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


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)


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)


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)


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)


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)


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)


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)


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.

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
Noch kein Account? Hier anmelden.