标题: STM32F4系统时钟树 [打印本页]
作者: gaozx_1980 时间: 2018-10-29 13:48
标题: STM32F4系统时钟树
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. }
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |