cancel
Showing results for 
Search instead for 
Did you mean: 

Ye Olde STM32F4 USART baud rate

Rob Meades
Senior

I'm having the same trouble as many on here in that I can't persuade USART1 of my STM32F4 to come out with the correct baud rate. My transmitted data appears as garbage when received at 115,200 and if I attach a Saleae logic probe to the Tx pin it measures the emitted baud rate at 172,890 bits/s, so a factor of 1.5 too large. I know the external clock on my board is 12 MHz (it is printed on the can) and my clock configuration code to run at 168 MHz is therefore:

    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
    // Configure the main internal regulator output voltage
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
 
    // Initialize the CPU, AHB and APB bus clocks
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 12;
    RCC_OscInitStruct.PLL.PLLN = 336;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 7;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        assert(false);
    }
 
    // Initialize the CPU, AHB and APB bus clocks
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 |
                                  RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
        assert(false);
    }

To configure the USART1 clock as 115,200 I'm calling LL_USART_Init() with the BaudRate field of the structure passed in set to 115200 and assuming that will just sort it out. I've tried different APB2CLKDivider values but the measured baud rate on the Tx pin remains unchanged, which implies that LL_USART_Init() is sorting it out but that something is wrong with the clock configuration code I have pasted in above.

Can anyone spot my mistake? Or is there somewhere else I should be looking for my mistake?

1 ACCEPTED SOLUTION

Accepted Solutions

Need to make sure HSE_VALUE is defined correctly for your 12 MHz source, and not 8 MHz

See stm32f4xx_hal_conf.h or "Find in Files"

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

View solution in original post

8 REPLIES 8

Look at the USART BRR register and divide into APB clock rate, try also +/- 1 value and see that with least error.

Run CPU/APB at some cleaner multiple of the baud rate, even if slightly derated.​

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

This attachment might help, its from Ye Olde bookstore. I would shy away from the low level libraries.

Ooo nice reference material. FYI I'm following the most excellent example here which uses the LL drivers:

https://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/

...and the author of which is very responsive to questions. So I think LL is worth a try. Can't use the HAL driver directly as it doesn't meet the API I need.

The debugger tells me that BRR is coming out at 243 and PeriphClock is 27,999,972 , my oversampling setting being 16. If the core clock really is 168 MHz then with my APB2 divider of 4 that makes APB2 42 MHz and 42 MHz / 243 is indeed 172 kbits/s. So it all adds/multiplies up. Question is, which of those numbers is 1.5 times too big? It must surely be PeriphClock. I'll go look at how it is calculated...

... yeah, that guy.... His libs are nice, but I prefer the HAL stuff, HAL works great with STM32CubeIDE and CubeMX (STM supports it pretty well too). Its a bear to figure out though, to each his own, best of luck.

Need to make sure HSE_VALUE is defined correctly for your 12 MHz source, and not 8 MHz

See stm32f4xx_hal_conf.h or "Find in Files"

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

Define HSE_VALUE=12000000 in your IDE compiler defines section or makefile CFLAGS).

Do not rely on it being defined in  stm32f4xx_hal_conf.h or any .h file.

-- pa

Ah, yes, of course, that's a bit tricksy. I had defined it in the existing spot in system_stm32f4xx.c:

#if !defined (HSE_VALUE) 
# define HSE_VALUE  ((uint32_t) 12000000) /*!< Default value of the External oscillator in Hz */
#endif /* HSE_VALUE */

But if I insert a #error in there it doesn't go off, it seems that the value in stm32f4xx_hal_conf.h is what I should be fiddling with: SystemCoreClock now comes out as 168 MHz, PeriphClock turns out to be 42000000, BRR 364 and the Saleae logic probe measures my transmit rate at 115,473 bits/s! Woohoo! I'll delete those values in my system_stm32f4xx.c to avoid confusion in future. Thanks guys.