STM32F4系統時鐘樹 STM32F4的系統時鐘非常重要,涉及到整個系統的運行結果,無論是什么操作,都需要時鐘信號,不同型號的微控制器的默認系統時鐘配置是不同的,這里,給出兩種配置STM32F407系統時鐘的方法。 方法一,采用官方庫提供的配置(這里外部晶振8MHz,系統配置為168MHz) · STM32F4啟動與STM32F10X不同,時鐘已經默認配置好 · 啟動代碼,文件:startup_stm32f4xx.s 1. Reset_Handler PROC 2. EXPORT Reset_Handler [WEAK] 3. IMPORT SystemInit 4. IMPORT __main 5. 6. LDR R0, =SystemInit 7. BLX R0 8. LDR R0, =__main 9. BX R0 10. ENDP 可以看出,在進入main函數之前,系統調用了SystemInit函數. · SystemInit函數分析:SystemInit函數位于system_stm32f4xx.c文件中.此文件提供幾個宏定義可以設置各個時鐘:
1. /************************* PLL Parameters*************************************/ 2. #if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx) 3. /* PLL_VCO = (HSE_VALUE or HSI_VALUE /PLL_M) * PLL_N */ 4. #define PLL_M 8 5. #else /* STM32F411xE */ 6. #if defined (USE_HSE_BYPASS) 7. #define PLL_M 8 8. #else /* STM32F411xE */ 9. #define PLL_M 16 10. #endif /* USE_HSE_BYPASS*/ 11. #endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx */ 12. 13. 14. /* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ 15. #define PLL_Q 7 16. 17. 18. #if defined (STM32F40_41xxx) 19. #define PLL_N 336 20. /* SYSCLK = PLL_VCO / PLL_P */ 21. #define PLL_P 2 //2 //2---168M 4---84M 22. #endif /* STM32F40_41xxx */ 23. 24. 25. #if defined (STM32F427_437xx) || defined (STM32F429_439xx) 26. #define PLL_N 360 27. /* SYSCLK = PLL_VCO / PLL_P */ 28. #define PLL_P 2 29. #endif /* STM32F427_437x || STM32F429_439xx */ 30. 31. 32. #if defined (STM32F401xx) 33. #define PLL_N 336 34. /* SYSCLK = PLL_VCO / PLL_P */ 35. #define PLL_P 4 36. #endif /* STM32F401xx */ 37. 38. 39. #if defined (STM32F411xE) 40. #define PLL_N 400 41. /* SYSCLK = PLL_VCO / PLL_P */ 42. #define PLL_P 4 43. #endif /* STM32F411xx */ 44. 45. 46. /******************************************************************************/ 我使用的是STM32F407,篩選可用信息如下: 1. /************************* PLL Parameters*************************************/ 2. /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M)* PLL_N */ 3. #define PLL_M 8 4. #define PLL_N 336 5. 6. /* SYSCLK = PLL_VCO / PLL_P */ 7. #define PLL_P 2 8. 9. /* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */ 10. #define PLL_Q 7 11. 12. /******************************************************************************/ · 而晶振頻率則是在文件stm32f4xx.h中進行設置: · 外部晶振: 1. #if !defined (HSE_VALUE) 2. #defineHSE_VALUE ((uint32_t)8000000) /*!< Value ofthe External oscillator in Hz */ 3. 4. #endif /* HSE_VALUE */ · 內部晶振: 1. #if !defined (HSI_VALUE) 2. #defineHSI_VALUE ((uint32_t)16000000) /*!< Value ofthe Internal oscillator in Hz*/ 3. #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函數代碼: 1. void SystemInit(void) 2. { 3. /* FPU settings------------------------------------------------------------*/ 4. #if (__FPU_PRESENT== 1) && (__FPU_USED == 1) 5. SCB->CPACR|= ((3UL<< 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ 6. #endif 7. /* Reset the RCCclock configuration to the default reset state ------------*/ 8. /* Set HSION bit */ 9. RCC->CR |= (uint32_t)0x00000001; 10. 11. /* Reset CFGRregister */ 12. RCC->CFGR = 0x00000000; 13. 14. /* Reset HSEON,CSSON and PLLON bits */ 15. RCC->CR &=(uint32_t)0xFEF6FFFF; 16. 17. /* Reset PLLCFGRregister */ 18. RCC->PLLCFGR =0x24003010; 19. 20. /* Reset HSEBYP bit*/ 21. RCC->CR &=(uint32_t)0xFFFBFFFF; 22. 23. /* Disable allinterrupts */ 24. RCC->CIR = 0x00000000; 25. 26. #if defined (DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM) 27. SystemInit_ExtMemCtl(); 28. #endif /* DATA_IN_ExtSRAM|| DATA_IN_ExtSDRAM */ 29. 30. /* Configure theSystem clock source, PLL Multiplier and Divider factors, 31. AHB/APBx prescalers and Flash settings----------------------------------*/ 32. SetSysClock(); 33. 34. /* Configure theVector Table location add offset address ------------------*/ 35. #ifdef VECT_TAB_SRAM 36. SCB->VTOR =SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM*/ 37. #else 38. SCB->VTOR =FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in InternalFLASH */ 39. #endif 40. } · SetSysClock函數分析,在SetSysClock函數中,配置了系統時鐘,PLL倍頻以及分頻系數: 1. static void SetSysClock(void) 2. { 3. /******************************************************************************/ 4. /* PLL (clocked by HSE) used as Systemclock source */ 5. /******************************************************************************/ 6. __IO uint32_t StartUpCounter = 0, HSEStatus = 0; 7. 8. /* Enable HSE */ 9. RCC->CR |= ((uint32_t)RCC_CR_HSEON); 10. 11. /* Wait till HSE isready and if Time out is reached exit */ 12. do 13. { 14. HSEStatus =RCC->CR & RCC_CR_HSERDY; 15. StartUpCounter++; 16. } while((HSEStatus == 0) &&(StartUpCounter != HSE_STARTUP_TIMEOUT)); 17. 18. if ((RCC->CR &RCC_CR_HSERDY) != RESET) 19. { 20. HSEStatus = (uint32_t)0x01; 21. } 22. else 23. { 24. HSEStatus = (uint32_t)0x00; 25. } 26. 27. if (HSEStatus == (uint32_t)0x01) 28. { 29. /* Select regulatorvoltage output Scale 1 mode, System frequency up to 168 MHz */ 30. RCC->APB1ENR|= RCC_APB1ENR_PWREN; 31. PWR->CR |= PWR_CR_VOS; 32. 33. /* HCLK = SYSCLK /1*/ 34. RCC->CFGR |=RCC_CFGR_HPRE_DIV1; 35. 36. /* PCLK2 = HCLK /2*/ 37. RCC->CFGR |=RCC_CFGR_PPRE2_DIV2; 38. 39. /* PCLK1 = HCLK /4*/ 40. RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; 41. 42. /* Configure themain PLL */ 43. RCC->PLLCFGR= PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | 44. (RCC_PLLCFGR_PLLSRC_HSE) |(PLL_Q << 24); 46. /* Enable the mainPLL */ 47. RCC->CR |=RCC_CR_PLLON; 48. 49. /* Wait till themain PLL is ready */ 50. while((RCC->CR &RCC_CR_PLLRDY) == 0) 51. { 52. } 53. 54. /* Configure Flashprefetch, Instruction cache, Data cache and wait state */ 55. FLASH->ACR =FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; 56. 57. /* Select the mainPLL as system clock source */ 58. RCC->CFGR&= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 59. RCC->CFGR |=RCC_CFGR_SW_PLL; 60. 61. /* Wait till themain PLL is used as system clock source */ 62. while ((RCC->CFGR &(uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); 63. { 64. } 65. } 66. else 67. { /* If HSE fails tostart-up, the application will have wrong clock 68. configuration. User can add here somecode to deal with this error */ 69. } 70. 71. }
如果外部時鐘啟動失敗,系統會使用內部時鐘 默認配置: HCLK = SYSCLK / 1 = 168MHz ,AHB總線時鐘 PCLK2 = HCLK / 2 = 84MHz PCLK1 = HCLK / 4 = 42MHz 定時器初始化設置時計算定時時間需要用到該定時器時鐘頻率,具體原因詳細看我整理的一篇博客文章,鏈接如下: 方法二,根據需要重新進行配置(這里外部晶振25MHz,系統配置為168MHz) · 自己根據自己外部晶振大小和需要進行配置 1. /******************************************************************************* 2. * Function Name : RCC_Configuration 3. * Description : Configures the different system clocks. 4. * Input : None 5. * Output : None 6. * Return : None 7. *******************************************************************************/ 8. void RCC_Configuration(void) 9. { 10. ErrorStatusHSEStartUpStatus; 11. uint32_t PLL_M_Temp = 0; 12. uint32_t PLL_N_Temp = 0; 13. uint32_t PLL_P_Temp = 0; 14. uint32_t PLL_Q_Temp = 0; 15. 16. 17. RCC_DeInit(); //½«ËùóDRCCÖØÖÃÎa3õê¼Öμ 18. 19. RCC_HSEConfig(RCC_HSE_ON); 20. HSEStartUpStatus= RCC_WaitForHSEStartUp(); //Ñ¡Ôñía2¿¾§Õñ(HSE)×÷Îaê±ÖóÔ′μè′yía2¿ê±Öó×¼±¸oà 21. 22. 23. if (HSEStartUpStatus ==SUCCESS) //éèÖÃê±ÖóÎa168M 24. { 25. /* Enable PrefetchBuffer */ 26. //FLASH_PrefetchBufferCmd(ENABLE); 27. 28. /* Flash 2 waitstate */ 29. //FLASH_SetLatency(FLASH_Latency_5); 30. 31. //HSE_VALUE =8MHz,PLL_VCO input clock = (HSE_VALUE orHSI_VALUE)/PLL_M,½¨òé′ËÖμÎa1~2MHz,òò′Ëè¡PLL_M=8£¬ 32. //PLL_VCO inputclock = 1MHz; 33. PLL_M_Temp= 8; 34. 35. //PLL_VCO outputclock = (PLL_VCO input clock)*PLL_N 36. //PLL_VCO outputclock = 336; 37. PLL_N_Temp= 336; 38. 39. //System Clock =(PLL_VCO output clock)/PLL_P , 40. //System Clock =84MHz 41. 42. PLL_P_Temp= 4; 43. 44. //′ËÏμêyóÃóúéèÖÃSD¿¨¶áD′£¬USBμè1|Äü£¬ÔYê±2»óà 45. PLL_Q_Temp= 7; 46. 47. /* PLLconfiguration */ 48. RCC_PLLConfig(RCC_PLLSource_HSE,PLL_M_Temp, PLL_N_Temp, PLL_P_Temp, PLL_Q_Temp); 49. /* Enable PLL */ 50. RCC_PLLCmd(ENABLE); 51. 52. /* Wait till PLL isready */ 53. while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) 54. { 55. } 56. 57. /* Select PLL assystem clock source */ 58. RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 59. 60. /* Wait till PLL isused as system clock source */ 61. while(RCC_GetSYSCLKSource()!= 0x08) 62. { 63. } 64. 65. }
66. }
|