Skip to main content
Graduate
February 23, 2024
Solved

UARTs Not Working On HSE Clock

  • February 23, 2024
  • 10 replies
  • 5148 views

Hi ,

I am using an STM32F205 for my project. We were using HSI as the clock source before and found out that HSI will not work very well with high temperatures for UARTs, So we added an External crystal clock (16Mhz) but I am unable to get Comms out of UARTs now (There are some random values coming through uart sometimes). This is my clock config

RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 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 = 14;
 RCC_OscInitStruct.PLL.PLLN = 240;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
 RCC_OscInitStruct.PLL.PLLQ = 4;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|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_DIV2;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
 {
 Error_Handler();
 }

 /** Enables the Clock Security System
 */
 HAL_RCC_EnableCSS();

 HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

I also updated the HSE value in stm32f2xx_hal_conf.h to 16Mhz.

I am using platformIO as the IDE for this project.
Am I missing any configuration?

    This topic has been closed for replies.
    Best answer by JThom.15

    Finally I found the issue,

    We Copied stm32f2xx_hal_conf.h from PlatformIO Library in to our project. And changed the HSE_VALUE in the copied file. But the code was still using the stm32f2xx_hal_conf.h from the PlatformIO library which has got HSE_VALUE 25Mhz.

    Thanks all for the Help

     

    10 replies

    Visitor II
    February 23, 2024

    Is it a real XTAL or a CMOS OSC?
    It differs on config, e.g. a CMOS OSC (just one signal on HSE pins used) needs a setting like "BYPASS".

    When you use an external HSE OSC - you had to make sure the PLL config is right. The PLL setting wants to see the clocks in a certain frequency range:
    Example: a 16 MHz external OSC (or XTAL) divided by 14 (PLLM) = 1.1142 MHz (maybe too low).
    And then you multiply again with 240 (PLLN) = 274.285 MHz (maybe too fast?)

    And all these resulting values look a "bit strange" (not a real integer clock ratio). Even the PLL would work, you might use a "strange" clock frequency for UART.
    My suggestion (what I do pretty often): use the STRM32CubeMX tool and play with the clock config: you get a pretty good clue how to configure all the PLLs. (no need to generate code, just play with PLL settings and use the values to update in your code).

     

    JThom.15Author
    Graduate
    February 23, 2024

    Thanks for the reply.

    I am using a real XTAL. I updated the clock config according to this 

    JThom15_0-1708663601289.png

    I updated my PLLM to 13 and PLLN to 195 as per the above config, but still I am not getting proper comms out of the UARTS

    Visitor II
    February 23, 2024

    OK, this looks good.

    But you have to check also which CLK is used for the UART peripheral, and how to you set a baud rate divider for the UART. Your UART can be completely off on clock frequency (and therefore a wrong baud rate).

    Add the UART as peripheral to this CubeMX, see the UART core clock and check the UART baud rate divider.

    And make sure, the resulting baud rate is pretty correct (not so much off): you cannot set "any" baud rate: just UART clock plus divider: any value in between (or your UART clock is "wrong") results in a wrong baud rate or a baud rate which is a bit off (with an "error" offset, resulting in wrong UART bits).

    Measure with a scope the UART bit frequency. Or go through the entire clock tree, including the UART clk selected, the divider set in order to see if it can result in a "reasonable" baud rate.
    If you change the PLLs - you have to change potentially also the CLK config for the UART (at least the baud rate divider).

    Super User
    February 23, 2024

    Read out and check/post/compare to working, content of UART and relevant RCC registers.

    JW

    Graduate II
    February 23, 2024

    Check HSE_VALUE 

    Scope 0x55 pattern for bit timing

    Scope MCO for HSE timing

     

    Graduate II
    February 23, 2024

    Also check the quartz' datasheet for recommended load capacitance and check your capacitors.
    You're not the first having trouble with that.

    BTW, is the STM32 HSE circuit that sensitive, or was I just lucky over the last 20 years with my AVRs and PICs?

     

    PS:

    And why these odd dividers and multipliers?

    That's for sure not the problem, but in my experience PLLs work better (stability, accuracy, jitter) with even values.

    So there should be some smoother settings to get from 16 MHz to 120 MHz. ;)

    JThom.15Author
    Graduate
    February 25, 2024

    Hi,

    I have measured the RCC_OSC_IN which is 16 MHz, 

    JThom15_0-1708903221043.png

    1.6055 MHz x 10  = 16MHz.

    Currently in our board PA8 and PC9 are used for i2c comms, So I cant enable MCO1 and MCO2 for measuring the clock output.

    JThom.15Author
    Graduate
    February 26, 2024

    Hi,

     

    This is my USART1 () and RCC regsiters

    with HSI 

    JThom15_1-1708905538030.png

    JThom15_2-1708905602191.png

    With HSE

    JThom15_4-1708905882871.png

     

    JThom15_3-1708905816549.png

     

     

    Visitor II
    February 26, 2024

    My five cents:

    When you change from HSI to HSE (with a 16 MHz OSN/XTAL) - you cannot have the same PPL settings:

    If HSI was based on 48 MHz (a guess) and you change to HSE with 16 MHz - the PLL config should look different, esp. to get the UART peripheral core clock as before,
    If you make sure the PLL config results in the same UART peripheral clock - it should work.

    JThom.15Author
    Graduate
    February 26, 2024

    But HSI on STM32F205 is 16MHz the same frequency as the external clock that I am using

    Super User
    February 26, 2024
    > This is my USART1 () and RCC regsiters

    I meant, in RCC all registers which determine APB clock (i.e. besides RCC_CR also RCC_PLLCFGR and RCC_CFGR); and in UART registers which determine its baudrate and general working setup (UART_BRR, UART_CR1, UART_CR2).

    My intention was to show you a way how *you* can find out, what's wrong, at the register level (which is how the microcontroller really works), and then work back into Cube/HAL to find out, where is the root of the problem - is it RCC/PLL setup, is it some other RCC setting, is it UART baudrate setup (and within that, is it a problem with the convoluted way how Cube/HAL determines the APB frequency from which UART's clock is derived), is it other UART setting, etc.

    In other words, check everything impacting the baudrate, which is probably different from the expectation. You can confirm this by observing UART_Tx pin by oscilloscope/logic analyzer.

    JW

    JThom.15Author
    Graduate
    February 26, 2024

    Thanks JW,

    I found its the UART->BRR register that changes when I use the HSE Clock. 

    On HSI (16MHZ) the UART->BRR is 0x186a. But on HSE(16Mhz) UART->BRR changes to 0x2626.

    If I manually update the BRR register (On HSE) with 0x186a then uart works fine at 9600 baudrate. 

    Can anyone please explain why the BRR register changes If I use HSE with same clock frequency and  clock config as the HSI?

    JThom.15Author
    Graduate
    February 27, 2024

    I was able to set the MCO from HSE and it measures 16MHZ 

    JThom15_0-1708994051292.png

    So I am not sure why the UART baudrate changes when I use the HSE clock source

    Graduate II
    February 27, 2024

     

     printf("%u\n", HSE_VALUE);
     printf("\n\nCore=%d, %d MHz\n", SystemCoreClock, SystemCoreClock / 1000000);
     {
     uint32_t clk;
     clk = HAL_RCC_GetHCLKFreq();
     printf("HCLK=%9d, %6.2lf MHz\n", clk, (double)clk*1e-6);
     clk = HAL_RCC_GetPCLK1Freq();
     printf("APB1=%9d, %6.2lf MHz\n", clk, (double)clk*1e-6);
     clk = HAL_RCC_GetPCLK2Freq();
     printf("APB2=%9d, %6.2lf MHz\n", clk, (double)clk*1e-6);
     }

     

    JThom.15AuthorAnswer
    Graduate
    February 27, 2024

    Finally I found the issue,

    We Copied stm32f2xx_hal_conf.h from PlatformIO Library in to our project. And changed the HSE_VALUE in the copied file. But the code was still using the stm32f2xx_hal_conf.h from the PlatformIO library which has got HSE_VALUE 25Mhz.

    Thanks all for the Help

     

    Visitor II
    February 27, 2024

    Great! Well done!

    So, the clock config was wrong. Obvious. Smart, that you have found the root cause.

    Yes, if one clock reference is wrong - the UART BRR has to be different (compared to what is expected to set).
    Clock config can be very "tricky".

    Enjoy your project now...

    JThom.15Author
    Graduate
    February 28, 2024

    Thanks JW,

    I am using a crystal oscillator.

    May be I will do a separate post for this