STM32时钟源介绍1. STM32的时钟源主要有:
HSI(内部高速时钟)
HSE(外部高速时钟)
LSI(内部低速时钟)
LSE(外部低速时钟)
PLL(锁相环)
MCO(时钟输出管脚)
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。 Reset_Handler PROC& g2 V* r9 f4 v* h0 K* r; t8 L; G5 aEXPORT Reset_Handler [WEAK]. _- V, u! V" r- m& X IMPORT __main2 z, x# ?5 D+ I+ e6 L IMPORT SystemInit LDR R0, =SystemInit BLX R0 " J/ ?4 l3 j& A4 x: @ LDR R0, =__main) T3 Z; e9 a, u; Q) r' \; \ BX R0 ENDP0 j2 R ]6 U! r2 [, d$ T4 Q$ F" w 通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。 2.2 SystemInit函数详解void SystemInit (void), k4 ^' Z: P) ]3 c$ R( G4 ?{ /* Reset the RCC clock configuration to the default reset state(for debug purpose) */9 _0 C. j& ?+ w9 J, d/ ~& b1 b! Z /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001; 9 i3 C- D9 b& K: m+ } /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */ #ifndef STM32F10X_CL RCC->CFGR &= (uint32_t)0xF8FF0000; #else RCC->CFGR &= (uint32_t)0xF0FF0000; m2 w5 a+ p. ] E #endif /* STM32F10X_CL */ . P) h' R0 X) F. q" d/ Q. \' t( G6 Z 9 v' D+ J, |; f& ?9 D /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF;/ z7 `; d$ {& Z2 L, e2 |0 N /* Reset HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ RCC->CFGR &= (uint32_t)0xFF80FFFF;8 N; W% n3 t; D1 z7 I+ _( O2 Y #ifdef STM32F10X_CL /* Reset PLL2ON and PLL3ON bits */ RCC->CR &= (uint32_t)0xEBFFFFFF; /* Disable all interrupts and clear pending bits */ RCC->CIR = 0x00FF0000; /* Reset CFGR2 register */ RCC->CFGR2 = 0x00000000; #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) u! D! t8 i# c6 L9 t% l /* Disable all interrupts and clear pending bits */7 N6 d) \, p9 g! u* d RCC->CIR = 0x009F0000;& s3 h$ L* A7 E1 O5 N7 A /* Reset CFGR2 register */ RCC->CFGR2 = 0x00000000; ; Z s, D& y4 f2 ?, Z* z& W0 C #else /* Disable all interrupts and clear pending bits */ RCC->CIR = 0x009F0000;/ O9 b& J3 B4 b" `& H) G #endif /* STM32F10X_CL */% X* J( u4 B. D" f9 i # s( `" E- t. [ W+ \3 p- [* Z' m #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) #ifdef DATA_IN_ExtSRAM SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */7 g. I; [1 r3 _; [ #endif . {9 y5 s q9 h8 f, q2 X. a- _, }/ m : e3 o: |& o) l, P: H' C /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */ /* Configure the Flash Latency cycles and enable prefetch buffer */ SetSysClock(); V& V4 U& a8 y3 p6 s9 e7 J% e4 D ) V' i) R5 C% f6 R6 _+ p #ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */) v7 P6 H" Y1 {3 `( W; c #else3 K; g6 s6 U* y. q% f SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ #endif ) R+ v/ x# E/ V3 K% v/ R } 打开内部8M时钟RCC->CR |= (uint32_t)0x00000001 通过查看寄存器手册可知,这段代码为打开内部8M时钟。
设置时钟配置寄存器#ifndef STM32F10X_CL RCC->CFGR &= (uint32_t)0xF8FF0000; #else RCC->CFGR &= (uint32_t)0xF0FF0000; #endif /* STM32F10X_CL */ $ _+ ^: K B8 P$ u0 s! i# | 对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。 后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。 2.3 SetSysClock()函数详解static void SetSysClock(void){ #ifdef SYSCLK_FREQ_HSE7 i9 u. z/ r" x& P4 U6 P/ W: Q SetSysClockToHSE(); #elif defined SYSCLK_FREQ_24MHz7 Y% F) H7 K/ g7 I SetSysClockTo24(); #elif defined SYSCLK_FREQ_36MHz SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz& ?2 l8 I! V, I9 O+ U SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz, b7 j3 Q: E, a- B1 ^ SetSysClockTo72();7 U* j8 O/ }; t( S1 C #endif }* i$ [7 c* A- P/ L system_stm32f10x.c文件中会根据芯片的型号定义对应的宏 #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)/* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000- z& R- x) |4 F7 v# A7 i& z, v7 F #else W4 A' W; a! q: G! N. p /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #define SYSCLK_FREQ_24MHz 24000000 */ /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */4 {9 y! S. P( [# Y! F3 B" u" }7 n #define SYSCLK_FREQ_72MHz 72000000/ E! D; [6 D" w. ?+ i- x #endif* L% B) t7 G+ @0 e 3. 时钟配置函数3.1 时钟初始化配置函数void SystemInit(void);1 B5 z1 X% e4 y U SYSCLK(系统时钟)=72MHZ;+ j8 e4 h4 B0 M$ B6 L9 a AHB总线时钟(HCLK=SYSCLK)=72MHZ; APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;. B3 R6 z) i4 K- l) | APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ; PLL主时钟=72MHZ;! P- M0 I' H. P8 H& P7 v 3.2 外设时钟使能配置函数void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);; I- Z2 }* j% l" a2 o7 D void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);2 }* \, G4 Y" l9 b 3.3 时钟源使能函数void RCC_HSICmd(FunctionalState NewState); void RCC_LSICmd(FunctionalState NewState); void RCC_PLLCmd(FunctionalState NewState); void RCC_RTCCLKCmd(FunctionalState NewState);; }) N+ J+ n5 o1 c3 p4 N 3.4 时钟源和倍频因子配置函数void RCC_HSEConfig(uint32_t RCC_HSE); void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource); void RCC_HCLKConfig(uint32_t RCC_SYSCLK);- {) q. e5 W2 |# Y- x% d void RCC_PCLK1Config(uint32_t RCC_HCLK);7 @- y+ @7 D, E+ i void RCC_PCLK2Config(uint32_t RCC_HCLK);; m: O+ t3 F* L( @* C2 Q 3.5 外设时钟复位函数void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);! Q- o, ?( s. V# t7 m. r+ b 3.6 自定义系统时钟void RCC_HSE_Config(u32 div,u32 pllm)# R, i2 D- |5 c! _( H- G; d0 u { RCC_DeInit();! Z( q4 y! k4 H' V- x; S' f: B RCC_HSEConfig(RCC_HSE_ON);1 P/ K& |& ? A& _% T" i$ `3 X! D if(RCC_WaitForHSEStartUp()==SUCCESS)# T r! i, }& c1 w0 F { & ^* W2 L8 c- l4 N! d! x. K RCC_HCLKConfig(RCC_SYSCLK_Div1);% y7 T! C* i& f$ F" v2 U8 [& D RCC_PCLK1Config(RCC_HCLK_Div2); RCC_PCLK2Config(RCC_HCLK_Div1); RCC_PLLConfig(div,pllm);9 N8 N; i( w. t+ O* }' i8 H, q RCC_PLLCmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET) RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK). N3 G, C5 _/ P; f9 c while(RCC_GetSCLKSource()!=0x08); }' e+ m' w! U2 Q8 f \& Y } |
微信公众号
手机版