About the problem of incorrect serial port baud rate when using 8M crystal oscillator on STM32F107RCT6

Publisher:创意驿站Latest update time:2018-08-28 Source: eefocusKeywords:STM32F107RCT6 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

problem found

I have been learning FreeRTOS recently. After the successful transplantation today, I wrote two tasks. One is the task of flashing the LED every 1s, and the other is the task of sending a string every 100ms using UART4. After the download was successful, I found that the interval between the LED flashing and the interval between the serial port printing were incorrect. I was very puzzled at the time: RCC was configured according to the example of the standard library, and the system beat of FreeRTOS was also configured correctly, so this problem could not occur. Later, after careful investigation, I used an oscilloscope to test the waveform of the serial port and found a problem: the program code was configured with a baud rate of 115200, but the actual output waveform was calculated to be 38400, a difference of 3 times. At this point, I began to doubt the RCC configuration. At this time, I turned on the MCO pin and asked it to display the SYSCLK clock. The oscilloscope reflected 72MH. Then I asked it to output the APB1CLK clock, which was a normal 36MHz. I felt confused when debugging here. Later, I carefully checked the RCC configuration code and found that the official example used a 25MHz crystal oscillator, so I changed it to 25Mhz and recalculated the division coefficient. After burning, it became normal. Here is the example template on the official website

problem solved

Clock tree of STM32F107

Write the picture description here
As can be seen from the figure, the SYSCLK clock of STM32F107 has two configuration routes. The first route can use an 8M external crystal to configure the system to 72MHz. The second route can use a 25M external crystal to configure the system to 72MHz. The first route is used, and the system clock is also correctly configured to 72MHz, but the serial port clock is incorrect (in fact, the HSE_VALUE value has not been modified). After changing to a 25MHz crystal and configuring according to the second route, the serial port is normal

Official RCC configuration example code


void RCC_Configuration(void)

{

 RCC_ClocksTypeDef RCC_ClockFreq;


   /* RCC system reset(for debug purpose) */

  RCC_DeInit();


  /* Enable HSE */

  RCC_HSEConfig(RCC_HSE_ON);


  /* Wait till HSE is ready */

  HSEStartUpStatus = RCC_WaitForHSEStartUp();


  if(HSEStartUpStatus != ERROR)

  {

    /* Enable Prefetch Buffer */

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


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

 /*      HSE=25MHz, HCLK=72MHz, PCLK2=72MHz, PCLK1=36MHz         */

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

    /* Flash 2 wait state */

    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */

    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK */

    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */

    RCC_PCLK1Config(RCC_HCLK_Div2);

    /*  ADCCLK = PCLK2/4 */

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);


    /* Configure PLLs *********************************************************/

    /* PPL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */

    RCC_PREDIV2Config(RCC_PREDIV2_Div5);

    RCC_PLL2Config(RCC_PLL2Mul_8);


    /* Enable PLL2 */

    RCC_PLL2Cmd(ENABLE);


    /* Wait till PLL2 is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET)

    {}


    /* PPL1 configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */

    RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5);

    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);


    /* Enable PLL */

    RCC_PLLCmd(ENABLE);


    /* Wait till PLL is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {}


    /* Select PLL as system clock source */

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);


    /* Wait till PLL is used as system clock source */

    while (RCC_GetSYSCLKSource() != 0x08)

    {}

  }


  RCC_GetClocksFreq(&RCC_ClockFreq);


  /* Enable USART2 clock */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);    



  /* Enable ETHERNET clock  */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx |

                        RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);


  /* Enable GPIOs clocks */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |

                         RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE| RCC_APB2Periph_AFIO, ENABLE);

  /* Enable ADC1 clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

}


It can be found that the official example code uses a 25MHz external crystal to configure the system clock. I modified my 8M crystal configuration based on the official code and it did not work properly.


My modified code


void bsp_RCC_Init(void)

{

 RCC_ClocksTypeDef RCC_ClockFreq;


   /* RCC system reset(for debug purpose) */

  RCC_DeInit();



  /* Enable HSE */

  RCC_HSEConfig(RCC_HSE_ON);


  /* Wait till HSE is ready */

  if(RCC_WaitForHSEStartUp() != ERROR)

  {

    /* Enable Prefetch Buffer */

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


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

 /*      HSE=8MHz, HCLK=72MHz, PCLK2=72MHz, PCLK1=36MHz         */

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

    /* Flash 2 wait state */

    FLASH_SetLatency(FLASH_Latency_2);

    /* HCLK = SYSCLK */

    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK */

    RCC_PCLK2Config(RCC_HCLK_Div1);

    /* PCLK1 = HCLK/2 */

    RCC_PCLK1Config(RCC_HCLK_Div2);

    /*  ADCCLK = PCLK2/4 */

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);


    /* Configure PLLs *********************************************************/

    /* PPL2 configuration: PLL2CLK = (HSE / 2) * 10 = 40 MHz */

    RCC_PREDIV2Config(RCC_PREDIV2_Div2);

    RCC_PLL2Config(RCC_PLL2Mul_10);


    /* Enable PLL2 */

    RCC_PLL2Cmd(ENABLE);


    /* Wait till PLL2 is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET)

    {}


    /* PPL1 configuration: PLLCLK = (HSE / 1) * 9 = 72 MHz */

    RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div1);

    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);


    /* Enable PLL */

    RCC_PLLCmd(ENABLE);


    /* Wait till PLL is ready */

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

    {}


    /* Select PLL as system clock source */

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);


    /* Wait till PLL is used as system clock source */

    while (RCC_GetSYSCLKSource() != 0x08)

    {}

  }

 }

After using the code I modified above, the serial port baud rate error problem occurred. When checking the registers in Keil debugging, I found that the value of UART->BRR was different from the theoretical calculation. Tracing back the configuration process of the USART_Init() function, I found that the obtained PCLK1 clock frequency was not 36MHz. After Write the picture description here
carefully checking the source code, I found that HSE_VALUE was defined as 25000000, which caused the PCLK1_Frequency value obtained by the RCC_GetClockFreq() function in the figure to be calculated incorrectly. Therefore, HSE_VALUE needs to be changed to 8000000. 
Write the picture description here
Another way is to replace the external 8M crystal oscillator with 25M, modify the RCC configuration to the official code, and it will run normally.

Summarize

STM32F107 has Ethernet, USB OTG and other network devices. When Ethernet uses the MII interface, a 25MHz clock is required. It is best for STM32F107 to use an external 25MHz crystal as the clock source. The official also recommends using 25MHz. To use an 8M crystal, you need to modify the HSE_VALUE value to 8000000, and then configure the corresponding PLL clock.


Keywords:STM32F107RCT6 Reference address:About the problem of incorrect serial port baud rate when using 8M crystal oscillator on STM32F107RCT6

Previous article:About the use of PA15 pin as normal IO in STM32
Next article:STM32 USART garbled code

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号