cancel
Showing results for 
Search instead for 
Did you mean: 

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

C.East2
Associate III

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);

1 ACCEPTED SOLUTION

Accepted Solutions
C.East2
Associate III

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.

View solution in original post

11 REPLIES 11
C.East2
Associate III

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();

 }

Javier1
Principal

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

we dont need to firmware by ourselves, lets talk

@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

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

Sorry about that.

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

I'm less worried about the instance where i've deinitialised it (though I do understand it may be part of the problem) but more confused as to how I would properly go about changing the Baud rate dynamically. Are you suggesting that I HAVE done it correctly in one of my examples?

Guenael Cadier
ST Employee

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.

Pavel A.
Evangelist III

@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();

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..