Skip to main content
Visitor II
May 24, 2022
Solved

How do I change the Baud rate of a UART/USART whilst running?

  • May 24, 2022
  • 6 replies
  • 12151 views

I've followed some answers from a post here:

https://stackoverflow.com/questions/57283327/how-to-change-the-uart-baud-rate-after-running-on-stm32-board

But still can't seem to get the baud rate to change. Has anyone had any luck trying to dynamically change the baud rate of the UART?

/****************************************************/

USART6 -> CR1 &= ~(USART_CR1_UE);

USART6 -> BRR = NEWVALUE;

USART6 -> CR1 |= USART_CR1_UE;

/****************************************************/

huart.Instance->BRR = UART_BRR_SAMPLING8(HAL_RCC_GetPCLK2Freq(), new_baudrate);

/****************************************************/

HAL_UART_DeInit(instance[bus].handle);

instance[bus].handle->Init.BaudRate = baud;

HAL_UART_Init(instance[bus].handle);

    This topic has been closed for replies.
    Best answer by C.East2

    Here is a follow up and answer to the problem.

    The issue was that The UART was part way through a interrupt transmission while I was changing the Baud rate. Having a static variable that keeps track of a message being sent has solved this issue.

    6 replies

    C.East2Author
    Visitor II
    May 24, 2022

    I've also tried running the MX code again like below. The HAL_UART_Init doesn't show any errors, but the program seems to crash after this. 

    huart4.Instance = UART4;

     huart4.Init.BaudRate = baud;

     huart4.Init.WordLength = UART_WORDLENGTH_8B;

     huart4.Init.StopBits = UART_STOPBITS_1;

     huart4.Init.Parity = UART_PARITY_NONE;

     huart4.Init.Mode = UART_MODE_TX_RX;

     huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;

     huart4.Init.OverSampling = UART_OVERSAMPLING_16;

     if (HAL_UART_Init(&huart4) != HAL_OK)

     {

      Error_Handler();

     }

    Super User
    May 24, 2022

    @C.East2​  "the program seems to crash"

    What, exactly, do you mean by that?

    • Hard Fault?
    • Stuck in a loop somewhere?
    • other?

    as @Javier Muñoz​ suggests, if the instance[bus].handle is wrong, that could cause such issues...

    0693W000008xsqBQAQ.png@C.East2

    C.East2Author
    Visitor II
    May 24, 2022

    Sorry about that.

    It doesn't hard fault. I'm not sure if it's in a loop somewhere. It's not in syscalls.

    Graduate II
    May 24, 2022

    How sure are you that instance[bus].handle is what you want it to be?

    C.East2Author
    Visitor II
    May 24, 2022

    Certain with the instance[bus].handle. This is correct.

    ST Employee
    May 24, 2022

    Hi @C.East2​ 

    If your UART (example UART4), if working properly with baudrate X, you could change baudrate to Y by using the methods you mentioned, especially :

    UART_HandleTypeDef huart4; 
    ...
    huart4.Instance = UART4
    huart4.Init.BaudRate = X;
    HAL_UART_Init(&huart4);
    ...
    HAL_UART_DeInit(&huart4);
    huart4.Init.BaudRate = Y;
    HAL_UART_Init(&huart4);
    ...

    Please make sure that you provide required content for HAL_UART_MspInit() and HAL_UART_MspDeInit() functions to handle HW resources associated to this UART, as clock source, GPIOs, ...

    By default, weak functions are defined with empty bodies for these HAL_UART_MspInit() and HAL_UART_MspDeInit() functions. Please define your owns (it is normally done if you are using STM32CubeMx).

    Regards.

    Super User
    May 24, 2022

    @C.East2​ After write to the UART register : USART6 -> CR1 &= ~(USART_CR1_UE);

    add read-back to let the write propagate all way to the device (TL;DR this is complicated).

    Barrier instructions after write won't harm too :

    USART6 -> CR1 &= ~(USART_CR1_UE);
    __DSB(); // barrier
    (void)(USART6 -> CR1); // read-back
    __DMB(); 
     
    USART6 -> BRR = NEWVALUE;
    __DSB();
    (void)(USART6 -> BRR);
    __DMB(); 
     
    USART6 -> CR1 |= USART_CR1_UE;
    __DSB();

    Graduate II
    May 24, 2022

    Yeah, I don't know it that's necessary

    It's suppose to complete the reads/writes in order, and the read should force the pending writes to complete. The _IO (or volatile) nature of the registers means the compilers not going to fold things.

    Where it becomes an issue is the clock cycles between enabling the peripheral (gating the synchronous clock into it), and it being functional. And secondarily when clearing an interrupt state at a peripheral level, and that completing, and then propagating thru the NVIC at the point where the tail-chaining do it or don't do it decision is made.

    C.East2AuthorAnswer
    Visitor II
    May 30, 2022

    Here is a follow up and answer to the problem.

    The issue was that The UART was part way through a interrupt transmission while I was changing the Baud rate. Having a static variable that keeps track of a message being sent has solved this issue.

    Visitor II
    June 4, 2024

    Hi,

    I meet the same problem as you, Have you change baud rate successful?

     

    Thanks and brgs