STM32时钟源介绍1. STM32的时钟源主要有:
HSI(内部高速时钟)
HSE(外部高速时钟)
LSI(内部低速时钟)
LSE(外部低速时钟)
PLL(锁相环)
MCO(时钟输出管脚)
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。 Reset_Handler PROCEXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit) |/ _' O* C+ R0 d. h BLX R0 LDR R0, =__main$ h8 s5 M' n+ ]% h+ I" O BX R0 ENDP 通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。 2.2 SystemInit函数详解void SystemInit (void){' m- _6 O" C& ^: ?- a+ G B /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ /* Set HSION bit */# M; _7 e2 u. l8 p( J- T! B RCC->CR |= (uint32_t)0x00000001; /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */6 ]+ a. j. t1 E4 \. ?* s #ifndef STM32F10X_CL RCC->CFGR &= (uint32_t)0xF8FF0000;& ^4 \8 P8 B8 H- M- v #else RCC->CFGR &= (uint32_t)0xF0FF0000;- @5 m- m& |' ~1 w #endif /* STM32F10X_CL */ . g! N0 Y* H! a9 n+ u+ s /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* Reset HSEBYP bit */2 e5 A4 _# n% k* l, X RCC->CR &= (uint32_t)0xFFFBFFFF;$ _- L' q) [# ?8 S! Q /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ RCC->CFGR &= (uint32_t)0xFF80FFFF; 1 _5 I4 m8 `8 x #ifdef STM32F10X_CL /* Reset PLL2ON and PLL3ON bits */ RCC->CR &= (uint32_t)0xEBFFFFFF;$ u8 b+ z5 i0 m* _. ]" f /* Disable all interrupts and clear pending bits */+ ^3 i+ ~. k& l RCC->CIR = 0x00FF0000; . [: f8 q% }. I2 b- b- X /* Reset CFGR2 register */ RCC->CFGR2 = 0x00000000; #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* Disable all interrupts and clear pending bits */ RCC->CIR = 0x009F0000;8 d3 c h8 v9 p6 a& o/ F; ] 2 r7 w% m. ~; L /* Reset CFGR2 register */ RCC->CFGR2 = 0x00000000; / p8 w! R- n5 C- M* ` b #else /* Disable all interrupts and clear pending bits */: d! U" C1 M( x( h' A4 B1 Y# L) q5 J$ g RCC->CIR = 0x009F0000;' s( Q: X8 V/ l; x7 z6 l, \: I #endif /* STM32F10X_CL */, l) d: t+ D' J* E- z% [ ) l4 }. a6 I L# Y# F4 C #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL) #ifdef DATA_IN_ExtSRAM SystemInit_ExtMemCtl(); 5 L- K* |! l3 d, F #endif /* DATA_IN_ExtSRAM */ #endif " R# W2 o7 }. ^/ F8 o" u /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */! [. k) A4 o; b) d /* Configure the Flash Latency cycles and enable prefetch buffer */ SetSysClock(); 4 c0 H0 P3 y0 V #ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */ #else# @0 W9 p+ k3 j" `$ p, B SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ #endif * L& E9 n3 L- k# a$ E( g }% u( s! s9 q: W# X( h 打开内部8M时钟RCC->CR |= (uint32_t)0x000000018 D) \! |' t0 Y. A$ i 通过查看寄存器手册可知,这段代码为打开内部8M时钟。 f! U( ?, q/ F) Z7 j f
设置时钟配置寄存器#ifndef STM32F10X_CL RCC->CFGR &= (uint32_t)0xF8FF0000; #else RCC->CFGR &= (uint32_t)0xF0FF0000;( a' ~4 i0 }) n. u4 |' w #endif /* STM32F10X_CL */ 对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。 后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。 2.3 SetSysClock()函数详解static void SetSysClock(void){ #ifdef SYSCLK_FREQ_HSE SetSysClockToHSE();; O4 b/ J% K# z) g0 ^ #elif defined SYSCLK_FREQ_24MHz SetSysClockTo24();+ B5 k* Q1 i0 S5 U, t6 X5 T #elif defined SYSCLK_FREQ_36MHz SetSysClockTo36();2 l. b: j5 M$ g/ W: r2 m5 | #elif defined SYSCLK_FREQ_48MHz SetSysClockTo48(); #elif defined SYSCLK_FREQ_56MHz SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz, Q" e8 j$ W6 h, F! d SetSysClockTo72();* c6 q3 s9 r! d0 B' t/ R #endif }1 m/ G! w2 u1 N2 D 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 #else /* #define SYSCLK_FREQ_HSE HSE_VALUE */- K1 C+ w* L6 F# l2 U3 U7 P /* #define SYSCLK_FREQ_24MHz 24000000 */ - a# H; q; Q/ A; d7 w- W /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */ /* #define SYSCLK_FREQ_56MHz 56000000 */ #define SYSCLK_FREQ_72MHz 72000000. E# E8 G) H: B# W #endif 3. 时钟配置函数3.1 时钟初始化配置函数void SystemInit(void); SYSCLK(系统时钟)=72MHZ;, F- I. Q6 s( p L6 V6 } G1 @6 S0 M AHB总线时钟(HCLK=SYSCLK)=72MHZ; APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;9 W* U' @" K; _ APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;; F2 l9 ?9 b. p: M3 ]: n: E PLL主时钟=72MHZ;2 F9 U+ l* A* k+ m2 f: d 3.2 外设时钟使能配置函数void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);! [# c) |% t$ C void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);; d1 i. U: d9 _ void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);+ A! a0 q$ j! o, R% ? 3.3 时钟源使能函数void RCC_HSICmd(FunctionalState NewState); void RCC_LSICmd(FunctionalState NewState);4 T& Z6 Y. |: [% H8 S' w/ s, b: G8 T; l; B void RCC_PLLCmd(FunctionalState NewState);+ m: _/ r, D( d8 M void RCC_RTCCLKCmd(FunctionalState NewState); 3.4 时钟源和倍频因子配置函数void RCC_HSEConfig(uint32_t RCC_HSE); void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);$ y0 o, n" j3 i, y void RCC_HCLKConfig(uint32_t RCC_SYSCLK);4 D" M) u- \. C" u void RCC_PCLK1Config(uint32_t RCC_HCLK); void RCC_PCLK2Config(uint32_t RCC_HCLK);/ y [- ^. {; A+ }7 _$ \ l 3.5 外设时钟复位函数void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);& G8 A& J+ \& l; L0 J void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);* s0 C& k1 x0 p) U1 a 3.6 自定义系统时钟void RCC_HSE_Config(u32 div,u32 pllm)$ W" k1 z+ n0 c4 `" n7 x5 _ {0 z u7 f6 |& _* K y+ @ RCC_DeInit(); RCC_HSEConfig(RCC_HSE_ON);: B- X" v9 x) \2 {0 k; V; h if(RCC_WaitForHSEStartUp()==SUCCESS)! ~5 s% s5 k; B, ?3 Z { RCC_HCLKConfig(RCC_SYSCLK_Div1); RCC_PCLK1Config(RCC_HCLK_Div2); RCC_PCLK2Config(RCC_HCLK_Div1); RCC_PLLConfig(div,pllm);/ A b) h1 k9 H" v4 q1 ^) | RCC_PLLCmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)6 g _4 y2 }! r7 o! R RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK)* o% @/ f# x K# q& Q' ]; S. W while(RCC_GetSCLKSource()!=0x08); 3 s, N, f5 c! E# L( w }+ U% g5 R* G) o9 c5 E } |
微信公众号
手机版