STM32时钟源介绍1. STM32的时钟源主要有:
HSI(内部高速时钟)
HSE(外部高速时钟)
LSI(内部低速时钟)
LSE(外部低速时钟)
PLL(锁相环)
MCO(时钟输出管脚)
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。 Reset_Handler PROCEXPORT Reset_Handler [WEAK]2 T( k1 S% T! E$ y IMPORT __main IMPORT SystemInit* _: s3 F3 T, ~! [. ] LDR R0, =SystemInit BLX R0 0 i# n% B4 m4 y LDR R0, =__main BX R0; o4 r6 z/ W9 S) k2 c ENDP 通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。 2.2 SystemInit函数详解void SystemInit (void){ /* Reset the RCC clock configuration to the default reset state(for debug purpose) */' i7 S# S3 K/ [1 j. {& z /* Set HSION bit */; f# F# m! n \6 l3 j RCC->CR |= (uint32_t)0x00000001;5 H* x' H, I, n; ~9 \" r$ N. A& k 5 E, z( Q( I! B1 p3 K& P( \ /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ #ifndef STM32F10X_CL- X- H8 p' S9 ?- t: s RCC->CFGR &= (uint32_t)0xF8FF0000; #else6 u: ? u( X, H7 k# n RCC->CFGR &= (uint32_t)0xF0FF0000; #endif /* STM32F10X_CL */ * K7 N* a6 G) N! P9 a& Y , T: O4 _- Z0 B% W" X, u$ _ /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF;' P. B+ ^$ V2 m' b' o /* Reset HSEBYP bit */8 G9 }* U' z: ^& i RCC->CR &= (uint32_t)0xFFFBFFFF; /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */; X' D3 s" r6 Y2 q RCC->CFGR &= (uint32_t)0xFF80FFFF;! q, w; d# Q/ J. v" N; B , e! Q1 V1 }2 w4 o, V& Y/ l. } #ifdef STM32F10X_CL6 a8 u; ^" R3 D- q6 q% @+ v$ v /* Reset PLL2ON and PLL3ON bits */ RCC->CR &= (uint32_t)0xEBFFFFFF; /* Disable all interrupts and clear pending bits */ RCC->CIR = 0x00FF0000;; ~' C( x( @% ]0 O 0 f1 J8 b+ M$ w /* Reset CFGR2 register */7 k1 ^; U: O: u E. {' z4 M _ RCC->CFGR2 = 0x00000000;8 @, i2 V' j; Z6 | #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* Disable all interrupts and clear pending bits */3 \# U F1 D6 a l8 E }/ L% O RCC->CIR = 0x009F0000;& O. O8 E6 M0 b# n # `/ K' S( ?! t1 S) k* l. [& n /* Reset CFGR2 register */8 V3 \, V* X& f RCC->CFGR2 = 0x00000000; #else /* Disable all interrupts and clear pending bits */! ~$ U! k) [* V. \0 {6 ^7 q! F RCC->CIR = 0x009F0000;1 z* C/ ?) @$ o) Z% d' z9 H #endif /* STM32F10X_CL */# Z4 ~! O% w# R1 Z 2 @9 r5 x6 w8 ^! X% {! |# J #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)# `6 i% w- D, X1 w1 b9 f #ifdef DATA_IN_ExtSRAM9 f$ `) [( [# Q+ h( r: u d- P3 N$ p SystemInit_ExtMemCtl(); ' v+ z7 Y+ ?8 A% _ #endif /* DATA_IN_ExtSRAM */8 Q' f! g8 h; ?% K a #endif , \' ]5 D Y. l" h4 e$ r /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ /* Configure the Flash Latency cycles and enable prefetch buffer */# e& b) v& j& e SetSysClock();% Y S1 X8 ]' O: R v #ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */1 i: L' Q5 ?0 ~ #else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */: X4 _, [3 H8 K2 O# M #endif 9 U" B& q$ e1 P( G" D }/ c8 j. H& m* d# S' p& v7 m4 n3 p 打开内部8M时钟RCC->CR |= (uint32_t)0x00000001' |7 l) n4 H# ?$ }" V 通过查看寄存器手册可知,这段代码为打开内部8M时钟。
设置时钟配置寄存器#ifndef STM32F10X_CL( P7 t" w: C& R# p RCC->CFGR &= (uint32_t)0xF8FF0000;; I" y+ c3 S4 x' r* M #else RCC->CFGR &= (uint32_t)0xF0FF0000; #endif /* STM32F10X_CL */ 对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。 后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。 2.3 SetSysClock()函数详解static void SetSysClock(void)6 E$ {- F: j1 W' b0 [0 Q{- n' {) Q! g, H$ j3 w) L7 [ #ifdef SYSCLK_FREQ_HSE SetSysClockToHSE();5 y# \; m: ^: Q0 y" T #elif defined SYSCLK_FREQ_24MHz% c( G0 A5 Y4 A' {* v) i( S9 }- \ SetSysClockTo24();! L4 D& }" L2 g4 l* u4 E! ` #elif defined SYSCLK_FREQ_36MHz6 M( p8 v/ }" c) d( o( T SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz' P" f& T) s6 l SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz SetSysClockTo56(); $ h F& k3 f8 ]) W( K #elif defined SYSCLK_FREQ_72MHz+ v$ D1 E v9 r- g SetSysClockTo72();- ^/ t" e7 n. E! w #endif } system_stm32f10x.c文件中会根据芯片的型号定义对应的宏 #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)/* #define SYSCLK_FREQ_HSE HSE_VALUE *// F! j4 h8 A% w# o #define SYSCLK_FREQ_24MHz 24000000 #else; k7 c. f4 K5 v" u; t" h3 v /* #define SYSCLK_FREQ_HSE HSE_VALUE */+ S, r$ ?3 z I3 Q( \ /* #define SYSCLK_FREQ_24MHz 24000000 */ ( s* e: E( J* D8 f' A3 p /* #define SYSCLK_FREQ_36MHz 36000000 */: B: f* H& d5 L6 K /* #define SYSCLK_FREQ_48MHz 48000000 */, E9 n& O) `1 B /* #define SYSCLK_FREQ_56MHz 56000000 */5 R7 ] U9 `0 c4 I2 @' m4 P #define SYSCLK_FREQ_72MHz 72000000- r/ i7 T7 k; ?6 r #endif 3. 时钟配置函数3.1 时钟初始化配置函数void SystemInit(void); SYSCLK(系统时钟)=72MHZ;5 O0 U) ~2 k- ]5 @9 z+ \ AHB总线时钟(HCLK=SYSCLK)=72MHZ; APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;. q) Z" `* }1 Z/ I8 M APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ; PLL主时钟=72MHZ;+ w, I, r/ A9 u+ i. d 3.2 外设时钟使能配置函数void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);6 n5 _! ?+ Z! O0 F- X void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);6 s! Q. H6 J, f. Z# J! P void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); 3.3 时钟源使能函数void RCC_HSICmd(FunctionalState NewState); void RCC_LSICmd(FunctionalState NewState);; j# T1 s/ `# X, m) W void RCC_PLLCmd(FunctionalState NewState); void RCC_RTCCLKCmd(FunctionalState NewState);. c8 P$ O& A- J- Z2 i4 f, X 3.4 时钟源和倍频因子配置函数void RCC_HSEConfig(uint32_t RCC_HSE); void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource); void RCC_HCLKConfig(uint32_t RCC_SYSCLK); void RCC_PCLK1Config(uint32_t RCC_HCLK); void RCC_PCLK2Config(uint32_t RCC_HCLK);) ?/ p/ X5 m+ y# L; l5 w5 W/ d 3.5 外设时钟复位函数void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);" i& j" [4 K! t0 _. V8 K& ~ void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);4 }" Y. A& H+ k% ^ 3.6 自定义系统时钟void RCC_HSE_Config(u32 div,u32 pllm): ^) P1 D2 s% Y3 H {5 t ^% H. X' X4 W! H RCC_DeInit();1 [! D# W; E) v3 ?! o RCC_HSEConfig(RCC_HSE_ON); if(RCC_WaitForHSEStartUp()==SUCCESS)4 Y W0 N+ ]( o; b' b+ f { RCC_HCLKConfig(RCC_SYSCLK_Div1); RCC_PCLK1Config(RCC_HCLK_Div2);, s/ i& ^4 t, F& L. H RCC_PCLK2Config(RCC_HCLK_Div1); RCC_PLLConfig(div,pllm); RCC_PLLCmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)0 y* H6 I4 J, p+ e5 C RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)3 ?: B G4 i/ c! Q% u while(RCC_GetSCLKSource()!=0x08);5 k; d7 K8 a1 r7 q# ~0 |/ k 7 x9 S- C) y( F( Z7 O } }. X, W) U% K) M6 \, p# Z/ L! q |
实战经验 | 基于STM32G0B1的全桥移相+同步整流PWM解决方案
STM32L562DK探索板——串口通讯的再测试
STM32L562DK探索板——串口通讯的测试
STM32L562DK探索板——运动传感器测试
STM32L562DK探索板——继续深入了解Audio Play的工作流程
STM32L562DK探索板——触摸菜单实验之触摸测试
STM32L562DK探索板——触摸菜单实验之LED闪烁
STM32L562DK探索板——Audio Play的再了解
STM32L562DK探索板——测试小结
STM32L562DK探索板——给Audio Play添加音量控制功能
微信公众号
手机版