A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

STM32F4系统时钟树



STM32F4的系统时钟非常重要,涉及到整个系统的运行结果,无论是什么操作,都需要时钟信号,不同型号的微控制器的默认系统时钟配置是不同的,这里,给出两种配置STM32F407系统时钟的方法。方法一,采用官方库提供的配置(这里外部晶振8MHz,系统配置为168MHz)
  • STM32F4启动与STM32F10X不同,时钟已经默认配置好
  • 启动代码,文件:startup_stm32f4xx.s


  • Reset_Handler    PROC



  •                  EXPORT  Reset_Handler             [WEAK]



  •         IMPORT  SystemInit



  •         IMPORT  __main







  •                  LDR     R0, =SystemInit



  •                  BLX     R0



  •                  LDR     R0, =__main



  •                  BX      R0



  •                  ENDP


可以看出,在进入main函数之前,系统调用了SystemInit函数.
  • SystemInit函数分析:SystemInit函数位于system_stm32f4xx.c文件中.此文件提供几个宏定义可以设置各个时钟:



  • /************************* PLL Parameters *************************************/



  • #if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx)



  • /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */



  • #define PLL_M      8



  • #else /* STM32F411xE */



  • #if defined (USE_HSE_BYPASS)



  • #define PLL_M      8   



  • #else /* STM32F411xE */   



  • #define PLL_M      16



  • #endif /* USE_HSE_BYPASS */



  • #endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx */  











  • /* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */



  • #define PLL_Q      7











  • #if defined (STM32F40_41xxx)



  • #define PLL_N      336



  • /* SYSCLK = PLL_VCO / PLL_P */



  • #define PLL_P      2  //2            //2---168M   4---84M



  • #endif /* STM32F40_41xxx */











  • #if defined (STM32F427_437xx) || defined (STM32F429_439xx)



  • #define PLL_N      360



  • /* SYSCLK = PLL_VCO / PLL_P */



  • #define PLL_P      2



  • #endif /* STM32F427_437x || STM32F429_439xx */











  • #if defined (STM32F401xx)



  • #define PLL_N      336



  • /* SYSCLK = PLL_VCO / PLL_P */



  • #define PLL_P      4



  • #endif /* STM32F401xx */











  • #if defined (STM32F411xE)



  • #define PLL_N      400



  • /* SYSCLK = PLL_VCO / PLL_P */



  • #define PLL_P      4   



  • #endif /* STM32F411xx */











  • /******************************************************************************/


我使用的是STM32F407,筛选可用信息如下:



  • /************************* PLL Parameters *************************************/  



  • /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */  



  • #define PLL_M      8



  • #define PLL_N      336  







  • /* SYSCLK = PLL_VCO / PLL_P */  



  • #define PLL_P      2  







  • /* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */  



  • #define PLL_Q      7  







  • /******************************************************************************/



  • 而晶振频率则是在文件stm32f4xx.h中进行设置:

  • 外部晶振:




  • #if !defined  (HSE_VALUE)



  •   #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */







  • #endif /* HSE_VALUE */


  • 内部晶振:


  • #if !defined  (HSI_VALUE)   



  •   #define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/



  • #endif /* HSI_VALUE */   





综上,如果使用外部晶振8MHz,则可以得出默认配置中:


锁相环压腔振荡器时钟PLL_VCO =(HSE_VALUE/PLL_M)* PLL_N=8/ 8* 336 = 336MHz


系统时钟SYSCLK = PLL_VCO / PLL_P=336 / 2 = 168MHz


USB,SD卡时钟 = PLL_VCO / PLLQ=336 / 7 = 48MHz



  • SystemInit函数代码:


  • void SystemInit(void)



  • {



  •   /* FPU settings ------------------------------------------------------------*/



  •   #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)



  •     SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */



  •   #endif



  •   /* Reset the RCC clock configuration to the default reset state ------------*/



  •   /* Set HSION bit */



  •   RCC->CR |= (uint32_t)0x00000001;







  •   /* Reset CFGR register */



  •   RCC->CFGR = 0x00000000;







  •   /* Reset HSEON, CSSON and PLLON bits */



  •   RCC->CR &= (uint32_t)0xFEF6FFFF;







  •   /* Reset PLLCFGR register */



  •   RCC->PLLCFGR = 0x24003010;







  •   /* Reset HSEBYP bit */



  •   RCC->CR &= (uint32_t)0xFFFBFFFF;







  •   /* Disable all interrupts */



  •   RCC->CIR = 0x00000000;







  • #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)



  •   SystemInit_ExtMemCtl();



  • #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */







  •   /* Configure the System clock source, PLL Multiplier and Divider factors,



  •      AHB/APBx prescalers and Flash settings ----------------------------------*/



  •   SetSysClock();







  •   /* Configure the Vector Table location add offset address ------------------*/



  • #ifdef VECT_TAB_SRAM



  •   SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */



  • #else



  •   SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */



  • #endif



  • }


  • SetSysClock函数分析,在SetSysClock函数中,配置了系统时钟,PLL倍频以及分频系数:


  • static void SetSysClock(void)  



  • {  



  • /******************************************************************************/  



  • /*            PLL (clocked by HSE) used as System clock source                */  



  • /******************************************************************************/  



  •   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;  







  •   /* Enable HSE */  



  •   RCC->CR |= ((uint32_t)RCC_CR_HSEON);  







  •   /* Wait till HSE is ready and if Time out is reached exit */  



  •   do  



  •   {  



  •     HSEStatus = RCC->CR & RCC_CR_HSERDY;  



  •     StartUpCounter++;  



  •   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));  







  •   if ((RCC->CR & RCC_CR_HSERDY) != RESET)  



  •   {  



  •     HSEStatus = (uint32_t)0x01;  



  •   }  



  •   else  



  •   {  



  •     HSEStatus = (uint32_t)0x00;  



  •   }  







  •   if (HSEStatus == (uint32_t)0x01)  



  •   {  



  •     /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */  



  •     RCC->APB1ENR |= RCC_APB1ENR_PWREN;  



  •     PWR->CR |= PWR_CR_VOS;  







  •     /* HCLK = SYSCLK / 1*/  



  •     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;  







  •     /* PCLK2 = HCLK / 2*/  



  •     RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;  







  •     /* PCLK1 = HCLK / 4*/  



  •     RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;  







  •     /* Configure the main PLL */  



  •     RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |  



  •                    (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);  



  •   点击打开链接



  •     /* Enable the main PLL */  



  •     RCC->CR |= RCC_CR_PLLON;  







  •     /* Wait till the main PLL is ready */  



  •     while((RCC->CR & RCC_CR_PLLRDY) == 0)  



  •     {  



  •     }  







  •     /* Configure Flash prefetch, Instruction cache, Data cache and wait state */  



  •     FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;  







  •     /* Select the main PLL as system clock source */  



  •     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));  



  •     RCC->CFGR |= RCC_CFGR_SW_PLL;  







  •     /* Wait till the main PLL is used as system clock source */  



  •     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);  



  •     {  



  •     }  



  •   }  



  •   else  



  •   { /* If HSE fails to start-up, the application will have wrong clock



  •          configuration. User can add here some code to deal with this error */  



  •   }  







  • }






如果外部时钟启动失败,系统会使用内部时钟


默认配置:


HCLK = SYSCLK / 1 = 168MHz ,AHB总线时钟


PCLK2 = HCLK / 2 = 84MHz


PCLK1 = HCLK / 4 = 42MHz

定时器初始化设置时计算定时时间需要用到该定时器时钟频率,具体原因详细看我整理的一篇博客文章,链接如下:

点击打开链接



方法二,根据需要重新进行配置(这里外部晶振25MHz,系统配置为168MHz)
  • 自己根据自己外部晶振大小和需要进行配置


  • /*******************************************************************************



  • * Function Name  : RCC_Configuration



  • * Description    : Configures the different system clocks.



  • * Input          : None



  • * Output         : None



  • * Return         : None



  • *******************************************************************************/



  • void RCC_Configuration(void)



  • {



  •         ErrorStatus HSEStartUpStatus;



  •   uint32_t PLL_M_Temp = 0;      



  •   uint32_t PLL_N_Temp = 0;



  •   uint32_t PLL_P_Temp = 0;



  •   uint32_t PLL_Q_Temp = 0;











  •         RCC_DeInit();                                 //½«ËùÓÐRCCÖØÖÃΪ³õʼֵ







  •         RCC_HSEConfig(RCC_HSE_ON);



  •         HSEStartUpStatus = RCC_WaitForHSEStartUp();   //Ñ¡ÔñÍⲿ¾§Õñ(HSE)×÷ΪʱÖÓÔ´ µÈ´ýÍⲿʱÖÓ×¼±¸ºÃ











  •   if (HSEStartUpStatus == SUCCESS)   //ÉèÖÃʱÖÓΪ168M



  •   {



  •     /* Enable Prefetch Buffer */



  •     //FLASH_PrefetchBufferCmd(ENABLE);







  •     /* Flash 2 wait state */



  •     //FLASH_SetLatency(FLASH_Latency_5);







  •                 //HSE_VALUE = 8MHz,PLL_VCO input clock = (HSE_VALUE or HSI_VALUE)/PLL_M,½¨Òé´ËֵΪ1~2MHz,Òò´ËÈ¡PLL_M=8£¬



  •                 //PLL_VCO input clock = 1MHz;



  •                 PLL_M_Temp = 8;







  •                 //PLL_VCO output clock = (PLL_VCO input clock)*PLL_N



  •                 //PLL_VCO output clock = 336;



  •                 PLL_N_Temp = 336;







  •                 //System Clock = (PLL_VCO output clock)/PLL_P ,



  •                 //System Clock = 84MHz







  •                 PLL_P_Temp = 4;







  •                 //´ËϵÊýÓÃÓÚÉèÖÃSD¿¨¶Áд£¬USBµÈ¹¦ÄÜ£¬ÔÝʱ²»ÓÃ



  •                 PLL_Q_Temp = 7;







  •     /* PLL configuration */



  •     RCC_PLLConfig(RCC_PLLSource_HSE, PLL_M_Temp, PLL_N_Temp, PLL_P_Temp, PLL_Q_Temp);



  •     /* 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)



  •     {



  •     }







  •   }



  • }





0 个回复

您需要登录后才可以回帖 登录 | 加入黑马