STM32时钟源介绍1. STM32的时钟源主要有:
HSI(内部高速时钟)
HSE(外部高速时钟)
LSI(内部低速时钟)
LSE(外部低速时钟)
PLL(锁相环)
MCO(时钟输出管脚)
首先打开startup_stm32f10x_hd.s,该文件为stm32的启动文件,在该文件内会发现有这么一块用汇编写的代码。 Reset_Handler PROCEXPORT Reset_Handler [WEAK] IMPORT __main8 o% a# U0 b; \% d& i IMPORT SystemInit LDR R0, =SystemInit3 I* q7 @8 T$ l Q2 U. l2 O: Y BLX R0 : S& \( {. ~+ M, L! v LDR R0, =__main+ q' O# U* F3 I* ]: c BX R0 ENDP, F' H8 _3 a N) A8 i) h$ P% N9 o 通过这段汇编代码可以看出,程序在执行main函数之前,会先执行SystemInit函数。 2.2 SystemInit函数详解void SystemInit (void){( S0 h9 r: {% l/ }. \ /* Reset the RCC clock configuration to the default reset state(for debug purpose) */" ~- x, a5 i9 B [: v3 } /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001;, H7 h' r% Z6 o8 c. w /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */9 P0 B# A" \& V% E% M) v) q #ifndef STM32F10X_CL RCC->CFGR &= (uint32_t)0xF8FF0000;2 J! b( E+ z9 c8 z4 x( x" g: X #else RCC->CFGR &= (uint32_t)0xF0FF0000; #endif /* STM32F10X_CL */ /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* Reset HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */ RCC->CFGR &= (uint32_t)0xFF80FFFF;8 R3 m& s; x2 f" f+ r #ifdef STM32F10X_CL+ W$ Y( Z, A% K1 U7 P* ~3 C7 }( l [ /* Reset PLL2ON and PLL3ON bits */ RCC->CR &= (uint32_t)0xEBFFFFFF; /* Disable all interrupts and clear pending bits */ RCC->CIR = 0x00FF0000;5 \! v5 r7 o) F" C" L /* 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;0 v! F& m' z6 f$ ]* f* v8 G /* Reset CFGR2 register */. `0 Y% Y; T# J8 J% _: F# } RCC->CFGR2 = 0x00000000; #else /* Disable all interrupts and clear pending bits */* E' E- ?+ K4 r+ t$ ?7 g$ a1 _" z RCC->CIR = 0x009F0000;( }# T" Z. N3 D! L! U #endif /* STM32F10X_CL */; W/ m, ?/ P" S! B3 M/ Q: e- j {) z , `) B* a$ \) o: k& I; D #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)' T6 j4 a8 t& l( }; z/ j #ifdef DATA_IN_ExtSRAM: S% J3 r, L4 S SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */5 _. u/ W# d; r& g( z. d5 [9 n #endif ( y) Q( a3 }) M, ~: p /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */) b: o9 I' T$ u8 H9 p; N3 Y /* Configure the Flash Latency cycles and enable prefetch buffer */& o7 t( w' F* x SetSysClock();" h9 ?8 ~7 q+ J, ]. s- m" J , {7 b5 b, Q. |6 @% x #ifdef VECT_TAB_SRAM1 b. p* h5 o- e5 m SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */: M$ q* s6 N Z' x0 o: l( h #else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */ #endif }, h7 O9 A8 u/ N- S+ Z) B 打开内部8M时钟RCC->CR |= (uint32_t)0x00000001 通过查看寄存器手册可知,这段代码为打开内部8M时钟。; \1 U0 b2 p* W- n4 O
设置时钟配置寄存器#ifndef STM32F10X_CL RCC->CFGR &= (uint32_t)0xF8FF0000;% b% u) w9 e9 j0 C3 m/ b5 \ #else RCC->CFGR &= (uint32_t)0xF0FF0000;2 d4 K. R% a1 h, s$ @ #endif /* STM32F10X_CL */ * i% P1 o9 N7 |! K$ g7 V 对应寄存器说明可查看《STM32中文参考手册_V10》的6.3.2 时钟配置寄存器(RCC_CFGR)章节。 后续代码,有兴趣可根据《STM32中文参考手册_V10》手册,查看代码具体作用。 2.3 SetSysClock()函数详解static void SetSysClock(void)4 \4 }* d+ n( S6 h. v% p{- l6 t/ `: l# G7 S9 v4 s #ifdef SYSCLK_FREQ_HSE SetSysClockToHSE();( l. y! H4 q4 A0 Z* M5 H8 u #elif defined SYSCLK_FREQ_24MHz# ]3 J9 Y( {* S$ L5 B- d- M SetSysClockTo24(); #elif defined SYSCLK_FREQ_36MHz2 E1 X; `. n! s8 S# g3 P SetSysClockTo36(); #elif defined SYSCLK_FREQ_48MHz0 F7 N! e7 \- q( F) \: y) J SetSysClockTo48();% j, u6 r0 {8 Z5 I4 t I2 o #elif defined SYSCLK_FREQ_56MHz+ u! C" @+ R8 u" l SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz, C6 T. u0 f% z: J' t7 I* ?: S' w SetSysClockTo72(); #endif! B2 E" Z, g" L) [# X% c( `- k }' f; c- N" i7 D# l4 n: Y- c, [ system_stm32f10x.c文件中会根据芯片的型号定义对应的宏 #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)7 ]( R& x; q3 `7 d/* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000" J b! {: G- m- e+ I #else: C Q9 t# v) t' f: W& s3 k w* E& K /* #define SYSCLK_FREQ_HSE HSE_VALUE */! ]' A% f1 I! K1 |7 W3 s /* #define SYSCLK_FREQ_24MHz 24000000 */ & M9 H! Z6 C0 S) A1 d* ^& X; L /* #define SYSCLK_FREQ_36MHz 36000000 */ /* #define SYSCLK_FREQ_48MHz 48000000 */3 C+ _( A; M5 N- t' P /* #define SYSCLK_FREQ_56MHz 56000000 */7 e" Y: _2 G/ s #define SYSCLK_FREQ_72MHz 72000000 #endif; D: t( i6 r" @8 Q 3. 时钟配置函数3.1 时钟初始化配置函数void SystemInit(void); SYSCLK(系统时钟)=72MHZ; AHB总线时钟(HCLK=SYSCLK)=72MHZ; APB1总线时钟(PCLK1=SYSCLK/2)=36MHZ;! p4 P, G5 C0 e1 `" q' H3 F* A% r APB2总线时钟(PCLK1=SYSCLK/1)=72MHZ;7 N; ~0 ` S. V, E1 G- a) ~, y PLL主时钟=72MHZ; 3.2 外设时钟使能配置函数void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);1 t/ F3 y9 `; y1 p) [' t void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); 3.3 时钟源使能函数void RCC_HSICmd(FunctionalState NewState); void RCC_LSICmd(FunctionalState NewState);+ k3 x% w& d' i' O+ H- @" k. b/ y, n void RCC_PLLCmd(FunctionalState NewState);0 p( c0 E7 F; ]0 [# C7 f) S" a void RCC_RTCCLKCmd(FunctionalState NewState); 3.4 时钟源和倍频因子配置函数void RCC_HSEConfig(uint32_t RCC_HSE);/ e% C' s( `, \: L* g void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource); void RCC_HCLKConfig(uint32_t RCC_SYSCLK);6 n! b' |4 U" I void RCC_PCLK1Config(uint32_t RCC_HCLK);2 O( ?0 W3 m8 w' g; p void RCC_PCLK2Config(uint32_t RCC_HCLK); 3.5 外设时钟复位函数void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);1 ?$ c. h8 C2 c) w* [/ P" s void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); 3.6 自定义系统时钟void RCC_HSE_Config(u32 div,u32 pllm) {+ q; n+ l5 B0 f; q8 N5 ]( A. u RCC_DeInit();2 m1 m* p% a% h3 {4 d RCC_HSEConfig(RCC_HSE_ON);/ ~/ {7 e/ F) H* `9 b' P% ~/ X if(RCC_WaitForHSEStartUp()==SUCCESS)( r( w/ v2 f% _ { RCC_HCLKConfig(RCC_SYSCLK_Div1);+ x% ?9 y: O0 [ |6 m( v RCC_PCLK1Config(RCC_HCLK_Div2);! [4 C* ^0 D2 ]: X$ E RCC_PCLK2Config(RCC_HCLK_Div1);6 b6 e" _. f# Q RCC_PLLConfig(div,pllm); RCC_PLLCmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET) RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK), G$ K9 U& m/ E2 z% c3 K while(RCC_GetSCLKSource()!=0x08);5 z* x' I6 j; f } }( U7 U/ ]# Y9 ~& Y' x B |
基于STM32F767通过cube配置:QSPI接口读写64M PSRAM+flash参考资料...
STM32L562DK探索板——串口通讯测试成功
STM32L562DK探索板——再试串口通讯仍不成
实战经验 | 基于STM32G0B1的全桥移相+同步整流PWM解决方案
STM32L562DK探索板——串口通讯的再测试
STM32L562DK探索板——串口通讯的测试
STM32L562DK探索板——运动传感器测试
STM32L562DK探索板——继续深入了解Audio Play的工作流程
STM32L562DK探索板——触摸菜单实验之触摸测试
STM32L562DK探索板——触摸菜单实验之LED闪烁
微信公众号
手机版