你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32的时钟配置

[复制链接]
STMCU小助手 发布时间:2022-12-26 16:00
5个时钟源
HSI,HSE,LSI,LSE,PLL

HSE为高速外部时钟,频率范围4~16 MHz

PLL的时钟源可以为:
HSE/2
HSE
HSI/2
倍频系数为2~16倍

STM32可以选择一个时钟信号输出到MCO脚,即PA8上,可以选择位PLL输出的二分频,HSI,HSE或系统时钟

注意:任何一个外设之前,都必须使能其对应的时钟

  1. /**
  2.   * @brief Reset and Clock Control
  3.   */

  4. typedef struct
  5. {
  6.   __IO uint32_t CR;
  7.   __IO uint32_t CFGR;
  8.   __IO uint32_t CIR;
  9.   __IO uint32_t APB2RSTR;
  10.   __IO uint32_t APB1RSTR;
  11.   __IO uint32_t AHBENR;
  12.   __IO uint32_t APB2ENR;
  13.   __IO uint32_t APB1ENR;
  14.   __IO uint32_t BDCR;
  15.   __IO uint32_t CSR;

  16. #ifdef STM32F10X_CL  
  17.   __IO uint32_t AHBRSTR;
  18.   __IO uint32_t CFGR2;
  19. #endif /* STM32F10X_CL */

  20. #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)   
  21.   uint32_t RESERVED0;
  22.   __IO uint32_t CFGR2;
  23. #endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */
  24. } RCC_TypeDef;
复制代码

4eb1912c6807466494f84994497d5690.png


如何查看SystemInit函数

49f73e196d724cafbc0b34576dcd0b26.png

可以看到这里有SystemInit函数的声明

42e5a44911b84250a91e5c28a9ece63f.png

打开这个文件,可以看到SystemInit函数的定义


  1. /**
  2.   * @brief  Setup the microcontroller system
  3.   *         Initialize the Embedded Flash Interface, the PLL and update the
  4.   *         SystemCoreClock variable.
  5.   * @note   This function should be used only after reset.
  6.   * @param  None
  7.   * @retval None
  8.   */
  9. void SystemInit (void)
  10. {
  11.   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  12.   /* Set HSION bit */
  13.   RCC->CR |= (uint32_t)0x00000001;

  14.   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  15. #ifndef STM32F10X_CL
  16.   RCC->CFGR &= (uint32_t)0xF8FF0000;
  17. #else
  18.   RCC->CFGR &= (uint32_t)0xF0FF0000;
  19. #endif /* STM32F10X_CL */   
  20.   
  21.   /* Reset HSEON, CSSON and PLLON bits */
  22.   RCC->CR &= (uint32_t)0xFEF6FFFF;

  23.   /* Reset HSEBYP bit */
  24.   RCC->CR &= (uint32_t)0xFFFBFFFF;

  25.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  26.   RCC->CFGR &= (uint32_t)0xFF80FFFF;

  27. #ifdef STM32F10X_CL
  28.   /* Reset PLL2ON and PLL3ON bits */
  29.   RCC->CR &= (uint32_t)0xEBFFFFFF;

  30.   /* Disable all interrupts and clear pending bits  */
  31.   RCC->CIR = 0x00FF0000;

  32.   /* Reset CFGR2 register */
  33.   RCC->CFGR2 = 0x00000000;
  34. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  35.   /* Disable all interrupts and clear pending bits  */
  36.   RCC->CIR = 0x009F0000;

  37.   /* Reset CFGR2 register */
  38.   RCC->CFGR2 = 0x00000000;      
  39. #else
  40.   /* Disable all interrupts and clear pending bits  */
  41.   RCC->CIR = 0x009F0000;
  42. #endif /* STM32F10X_CL */
  43.    
  44. #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  45.   #ifdef DATA_IN_ExtSRAM
  46.     SystemInit_ExtMemCtl();
  47.   #endif /* DATA_IN_ExtSRAM */
  48. #endif

  49.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  50.   /* Configure the Flash Latency cycles and enable prefetch buffer */
  51.   SetSysClock();

  52. #ifdef VECT_TAB_SRAM
  53.   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
  54. #else
  55.   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
  56. #endif
  57. }
复制代码

如下图所示

ac87cb992fb74286b66d1ff2201a78ed.png

函数解析
  1. /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  2.   /* Set HSION bit */
  3.   RCC->CR |= (uint32_t)0x00000001;
复制代码


首先把CR寄存器的最低位置1

Set HSION Bit 相对于打开HSION,相对于把内部的8 MHz晶振打开

bf1184340d7f4121beeefb7e1b6e2518.png

也就是这个

ee533c979e8a4dbdb4b8796192f65865.png

  1. /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  2. #ifndef STM32F10X_CL
  3.   RCC->CFGR &= (uint32_t)0xF8FF0000;
  4. #else
  5.   RCC->CFGR &= (uint32_t)0xF0FF0000;
  6. #endif /* STM32F10X_CL */   
复制代码

dae33a2dadce4736b886556f092ac8a0.png

以上代码主要是看你所用的芯片是大容量还是小容量,可以在魔术棒-C/C++里的宏处查看,例如,大容量为:

STM32F10X_HD

因此,这里相对于是根据所用的芯片容量选择RCC->CFGR寄存器的初始状态
  1.   /* Reset HSEON, CSSON and PLLON bits */
  2.   RCC->CR &= (uint32_t)0xFEF6FFFF;
复制代码

bb17248645c847f0b360948e167dac78.png

把HSEON,CSSON和PLLON对应的位清0
  1.   /* Reset HSEBYP bit */
  2.   RCC->CR &= (uint32_t)0xFFFBFFFF;
复制代码

a1a0a1b0b9a84a239d08e77c71be1ca6.png

把HSEBYP对应的位清0
  1.   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  2.   RCC->CFGR &= (uint32_t)0xFF80FFFF;
复制代码

f1c4cf14cbc349588f99791a0ed7d527.png

类似

接下来是一个条件编译

  1. #ifdef STM32F10X_CL
  2.   /* Reset PLL2ON and PLL3ON bits */
  3.   RCC->CR &= (uint32_t)0xEBFFFFFF;

  4.   /* Disable all interrupts and clear pending bits  */
  5.   RCC->CIR = 0x00FF0000;

  6.   /* Reset CFGR2 register */
  7.   RCC->CFGR2 = 0x00000000;
  8. #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  9.   /* Disable all interrupts and clear pending bits  */
  10.   RCC->CIR = 0x009F0000;

  11.   /* Reset CFGR2 register */
  12.   RCC->CFGR2 = 0x00000000;      
  13. #else
  14.   /* Disable all interrupts and clear pending bits  */
  15.   RCC->CIR = 0x009F0000;
  16. #endif /* STM32F10X_CL */
复制代码


823a301f0b024810a8549e24852fcece.png

执行的是这一段:

9728413aabb84591aaa599c40b458a18.png

也就是关闭所有的中断,并清除所有的标志位

接下来调用了一个非常重要的函数
  1.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  2.   /* Configure the Flash Latency cycles and enable prefetch buffer */
  3.   SetSysClock();
复制代码

226ba74ad07f41b1a553eaab04c4fef9.png

看一下这个函数的实现:
  1. /**
  2.   * @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
  3.   * @param  None
  4.   * @retval None
  5.   */
  6. static void SetSysClock(void)
  7. {
  8. #ifdef SYSCLK_FREQ_HSE
  9.   SetSysClockToHSE();
  10. #elif defined SYSCLK_FREQ_24MHz
  11.   SetSysClockTo24();
  12. #elif defined SYSCLK_FREQ_36MHz
  13.   SetSysClockTo36();
  14. #elif defined SYSCLK_FREQ_48MHz
  15.   SetSysClockTo48();
  16. #elif defined SYSCLK_FREQ_56MHz
  17.   SetSysClockTo56();  
  18. #elif defined SYSCLK_FREQ_72MHz
  19.   SetSysClockTo72();
  20. #endif
复制代码

4f08b87b29cb495487f3740faa54c379.png

这个函数主要是看看这些标志符有没有被定义,这个定义我们是设置在下面这个文件中,我们进去看一下:

system_stm32f10x.c
  1. #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  2. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */
  3. #define SYSCLK_FREQ_24MHz  24000000
  4. #else
  5. /* #define SYSCLK_FREQ_HSE    HSE_VALUE */
  6. /* #define SYSCLK_FREQ_24MHz  24000000 */
  7. /* #define SYSCLK_FREQ_36MHz  36000000 */
  8. /* #define SYSCLK_FREQ_48MHz  48000000 */
  9. /* #define SYSCLK_FREQ_56MHz  56000000 */
  10. #define SYSCLK_FREQ_72MHz  72000000
  11. #endif
复制代码

e6c88e2122454290a9fd2a05c68a6410.png

SetSysClock函数通过判断宏定义标志符来判断要调用哪个函数

例如,我们在宏定义中定义了SYSCLK_FREQ_72MHz,那么SetSysClock函数就会调用SetSysClockTo72函数


SetSysClockTo72函数的实现
  1. /**
  2.   * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2
  3.   *          and PCLK1 prescalers.
  4.   * @note   This function should be used only after reset.
  5.   * @param  None
  6.   * @retval None
  7.   */
  8. static void SetSysClockTo72(void)
  9. {
  10.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  11.   
  12.   /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   
  13.   /* Enable HSE */   
  14.   RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  15.   /* Wait till HSE is ready and if Time out is reached exit */
  16.   do
  17.   {
  18.     HSEStatus = RCC->CR & RCC_CR_HSERDY;
  19.     StartUpCounter++;  
  20.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  21.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  22.   {
  23.     HSEStatus = (uint32_t)0x01;
  24.   }
  25.   else
  26.   {
  27.     HSEStatus = (uint32_t)0x00;
  28.   }  

  29.   if (HSEStatus == (uint32_t)0x01)
  30.   {
  31.     /* Enable Prefetch Buffer */
  32.     FLASH->ACR |= FLASH_ACR_PRFTBE;

  33.     /* Flash 2 wait state */
  34.     FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
  35.     FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;   


  36.     /* HCLK = SYSCLK */
  37.     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
  38.       
  39.     /* PCLK2 = HCLK */
  40.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
  41.    
  42.     /* PCLK1 = HCLK */
  43.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

  44. #ifdef STM32F10X_CL
  45.     /* Configure PLLs ------------------------------------------------------*/
  46.     /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
  47.     /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
  48.         
  49.     RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
  50.                               RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
  51.     RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
  52.                              RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  53.   
  54.     /* Enable PLL2 */
  55.     RCC->CR |= RCC_CR_PLL2ON;
  56.     /* Wait till PLL2 is ready */
  57.     while((RCC->CR & RCC_CR_PLL2RDY) == 0)
  58.     {
  59.     }
  60.    
  61.    
  62.     /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
  63.     RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
  64.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
  65.                             RCC_CFGR_PLLMULL9);
  66. #else   
  67.     /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
  68.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
  69.                                         RCC_CFGR_PLLMULL));
  70.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
  71. #endif /* STM32F10X_CL */

  72.     /* Enable PLL */
  73.     RCC->CR |= RCC_CR_PLLON;

  74.     /* Wait till PLL is ready */
  75.     while((RCC->CR & RCC_CR_PLLRDY) == 0)
  76.     {
  77.     }
  78.    
  79.     /* Select PLL as system clock source */
  80.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  81.     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   

  82.     /* Wait till PLL is used as system clock source */
  83.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
  84.     {
  85.     }
  86.   }
  87.   else
  88.   { /* If HSE fails to start-up, the application will have wrong clock
  89.          configuration. User can add here some code to deal with this error */
  90.   }
  91. }
复制代码

9940eb72e7644455bca84fd012bf41f2.png

首先,通过配置CR寄存器打开HSE,即外部高速时钟使能

0c0f28369b684eebba1b65d5df0d72d3.png

7939f1e6003e468289215b7a7a8ad707.png

b98eb7647bd3471cbee5a322a61839a4.png

接下来等待HSE的稳定,方法是查看CR寄存器的HSERDY位

4142b8ed7be447f0ab7411645efb0edf.png

abbcce406d434efb919e429e0423a3aa.png

若就绪,则HSEStatus = 1
接下来,当HSEStatus = 1时执行如下操作
  1.   if (HSEStatus == (uint32_t)0x01)
  2.   {
  3.     /* Enable Prefetch Buffer */
  4.     FLASH->ACR |= FLASH_ACR_PRFTBE;

  5.     /* Flash 2 wait state */
  6.     FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
  7.     FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;   


  8.     /* HCLK = SYSCLK */
  9.     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
  10.       
  11.     /* PCLK2 = HCLK */
  12.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
  13.    
  14.     /* PCLK1 = HCLK */
  15.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

  16. #ifdef STM32F10X_CL
  17.     /* Configure PLLs ------------------------------------------------------*/
  18.     /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
  19.     /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
  20.         
  21.     RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
  22.                               RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
  23.     RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
  24.                              RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  25.   
  26.     /* Enable PLL2 */
  27.     RCC->CR |= RCC_CR_PLL2ON;
  28.     /* Wait till PLL2 is ready */
  29.     while((RCC->CR & RCC_CR_PLL2RDY) == 0)
  30.     {
  31.     }
  32.    
  33.    
  34.     /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
  35.     RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
  36.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
  37.                             RCC_CFGR_PLLMULL9);
  38. #else   
  39.     /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
  40.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
  41.                                         RCC_CFGR_PLLMULL));
  42.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
  43. #endif /* STM32F10X_CL */

  44.     /* Enable PLL */
  45.     RCC->CR |= RCC_CR_PLLON;

  46.     /* Wait till PLL is ready */
  47.     while((RCC->CR & RCC_CR_PLLRDY) == 0)
  48.     {
  49.     }
  50.    
  51.     /* Select PLL as system clock source */
  52.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  53.     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   

  54.     /* Wait till PLL is used as system clock source */
  55.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
  56.     {
  57.     }
  58.   }
  59.   else
  60.   { /* If HSE fails to start-up, the application will have wrong clock
  61.          configuration. User can add here some code to deal with this error */
  62.   }
复制代码

由CPU的速度是远远快于FLASH的速度的,因此需要对FLASH控制器进行配置

772f84123000422ead8f9dd2a8261a43.png

通过CFGR寄存器设置AHB Prescale 设为1,泽恩HCLK就等于SYSCLK

22843ba4c8e14c819ec8d98bf7b4fd73.png

1175c083c0374cc6b113316734d67417.png

0773df0779e04b4296583cc00cc8569d.png

7f8a3be7a71342e8a1ae92fb02ff5334.png

a63b28cdbf3a4e82bce34b74731dd6cc.png

f577dd777b9a420580e06a98e64e7e47.png

24331fedc033422aa2b1b3ad2e64419e.png


本质上是将APB2的Prescale设置为1

42ab9b153fcd4c6e87470f224f02743e.png

01cb0958b6324b37a16c3b9e4fba1e6f.png

8bc7d3513a584773b8b0c4c897350d3e.png

6b711a96f798468c9564b645e6d5a3e2.png

经过以上配置:
HCLK = SYSCLK
PCLK2  = SYSCLK
PCLK1 = SYSCLK


4d76f244c7304777a5e924a7ef0ba986.png

此处条件编译

执行的是这段

d66d8e3f6c014810bd2799aec32de236.png

  1. CC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
  2.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6);
复制代码

将HSE作为时钟源,倍频系数为9,即将HSE直接作为时钟源,倍频9后的PLLCLK作为系统时钟,后面的预分频都是72 MHz

4c4e538a4eda4470bca3f30158cfce5a.png

84c504ec27bf4f539652567e9ddefa77.png

bad94af1ff8842209dfc526a34f60eba.png

6c424b43db464bbc9e6fcf568d5d3409.png

等待PLL就绪

90c976682b3a49f09cc755850dbc6e0f.png

b7ffbf05369a4f3a8d3a43b257822054.png

PLL作为系统时钟,并等待其稳定

65d45ed47c304712aa1838576f7730f8.png

调用SystemInit函数的地方

8a81383fbd2e430185d3f40b5272fa19.png

startup_stm32f10x_hd.s
这里定义先执行SystemInit函数,再执行main函数

4614dab15bf8423c824d4377246ac5a7.png

————————————————
版权声明:CodeForCoffee





收藏 评论0 发布时间:2022-12-26 16:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版