时钟是嵌入式系统的脉搏,对嵌入式系统至关重要。处理器内核在时钟驱动下完成状态变换等动作,外设部件在时钟的驱动下完成各种工作,比如串口数据的发送、A/D转换、定时器计数等等。stm32l0xx系列低功耗新增MSI内部多频率可选时钟源,代码配置方面基于HAL库,与f系列相比存在一定的区别,本文以datasheet中的时钟树图为基础对时钟系统进行学习总结。时钟树如下图1所示:
8 K. |) D0 t1 f; s a- G4 Q4 L4 M9 w! [$ ~: ?. ^( \
9 T ?8 I: D1 S a7 d& a6 U/ H4 U+ _6 D$ j
1、LSI RC,低速内部时钟(RC振荡器),是看门狗(WatchdogLS)的唯一时钟来源,可以作为实时时钟RTC和主时钟输出(MCO)的时钟源。
% r* Z8 T/ i9 y$ N# C& R# [* T
: K7 C( r! `* F S$ i! {2、LSE OSC,外部低速时钟(晶振),输入输出引脚接OSC32_IN、OCS32_OUT可以作为实时时钟RTC和主时钟输出(MCO)的时钟源。精度高于内部低速时钟。
; j1 [2 g3 D2 H- v2 t7 n. V+ c5 e1 T
3、MSI RC,全称为Multispeedinternal RC oscillator,是stm32lxx低功耗系列独有的时钟,可提供12种频率的时钟源,范围可以从100KHZ到48MHZ之间变化。可以直接选择为系统时钟和AHB时钟,也可以作为MCO的时钟源。MSI为低功耗模式提供了更多的选择,但是精度不高。官方提供的例程中多以MSI作为时钟源。- z q! y0 p7 k& o @/ k) z
) N K, L" y! ^6 P N
4、HSI,内部高速时钟(RC振荡器),可以直接选择为系统时钟,可以作为PLL(锁相环倍频输出)时钟源,经倍频后选择作为系统的System Clock(系统时钟)和AHB时钟。HSI还可以作为ADCCLK时钟源。& Q8 X9 M% I, T+ C# s0 R( f8 n
3 ^: x* d; _ X7 ^ `4 m5、HSE,外部高速时钟(晶振),输入输出引脚接OSC_IN、OCS_OUT,可以直接选择为系统时钟,可以作为PLL源,经倍频后选择作为系统的(系统时钟)和AHB时钟。还可以作为MCO和RTC时钟源。
: R `, V! `; K+ F8 p, u
+ Q. |$ X! g0 J$ e B6、System Clock,系统时钟,是供STM32 中绝大部分部件工作的时钟源,是其他所有外设的时钟的来源。System Clock通过 AHB 分频器分频后送给各模块使用。System Clock还是CK_PWR和MCO的时钟源。
4 O2 u# f- L( C6 B h
4 z8 x- y3 Z! f7、HCLK,高速外设时钟,是AHB总线时钟源,SystemClock经AHB预分频得到。供内存和 DMA 等使用。
5 _/ z& C5 h5 Y5 x7 g! G2 B4 u2 f1 V2 `% ?! M1 s9 F* t0 i" D
8、FCLK为自由振荡处理器时钟,用来保证在休眠是采样到中断和跟踪休眠事件,与HCLK时钟源相同。
. @& P) t, _; m$ D9 W! {% l. E1 H1 ~* {% ^5 D& H* ]- m: z
9、PCLK1,System Clock经AHB预分频后,送给 APB1 分频器,得出PCLK1,是APB1时钟源,供 APB1 外设使用。APB1上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等。另一路送给TIMx使用,若APB1分频系数为1,则不倍频,否则倍频系数为2。7 k: Z$ ?* f, I4 O% R. z6 ^6 w+ ~
2 h2 R E* Y8 P9、PCLK2,System Clock经AHB预分频后,送给 APB2 分频器,得出PCLK2,是APB2时钟源,供 APB2外设使用,APB2 上面连接的是高速外设包括UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。另一路送给TIMx使用,若APB2分频系数为1,则不倍频,否则倍频系数为2。
4 _2 y8 ]+ w2 H% X& W0 t+ d' s4 h& t; e) m3 K% y) j) H
6 k7 Z- v8 j* I
6 x; e* A( r" h1 z) `时钟初始化代码配置,选用了HSE外部时钟,未进行倍频和分频:* _5 K% j/ j/ b1 `6 R7 i- z4 Y
, Q% |6 N4 ~1 V/ l5 Z0 r4 Q$ g- void SystemClock_Config(void)
. X% r2 ~# O1 M6 e - {% E! B. ~9 D$ J0 y. e) _! o8 q
7 u# J& n/ J1 K H# w
* F# O! b& d3 P9 {8 q- RCC_OscInitTypeDef RCC_OscInitStruct;
; [+ m8 P# C$ g/ F - RCC_ClkInitTypeDef RCC_ClkInitStruct;
$ q* t0 g8 {/ t- U* U - * E/ Z0 x8 L" {; w0 U
- * [, `; X# p' ~ P8 J" H" n
- /**Configure the main internal regulator output voltage
' f( g8 B# H: m( P! o6 j& ^ - */' [" B5 q" K$ G# l2 v& e! x1 s
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);3 q4 I8 ] m: E; z$ k/ j c
- ( ]; O# ?& b F4 w* f/ E9 H
- ! V9 `/ r1 D3 w9 s' [
- /**Initializes the CPU, AHB and APB busses clocks
# m1 y3 ]6 [1 e) I' _ - */2 h+ Y6 i; j8 [( x
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;0 R; B0 y, R$ o# ^
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
( o0 a' e, _" j - RCC_OscInitStruct.LSIState = RCC_LSI_ON;% V Y8 O+ R# f; K
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
% x3 T4 t$ `, b - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)8 R. D, }9 [+ c; `( h, S( z: b# `
- {
* D2 {4 P* y/ o' O7 l - Error_Handler();' U$ u% Z+ q. q8 r' U/ b
- }5 V: m& _, t/ Q8 h6 Q- H) ]
- $ z; Q6 N/ Z1 n+ ]2 L
# T# A: A9 S& H& a, i7 u- /**Initializes the CPU, AHB and APB busses clocks
" r' S% j* D8 I, J) q - */
" Y& F: e8 C6 I! h - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
S: x; L- h2 _" Q4 [ - |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
2 ~$ M# s5 W* [: {5 x1 P9 Z, _+ L6 E - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;' i9 c$ x7 @4 f* M- D% m+ a
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;+ n9 n" v# x4 W( m V( z4 B5 ^) @* P5 A+ X
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;/ X- n+ Z, w* h, o0 c5 j. o1 \* a. [
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;2 _/ h" X: x( I* @0 l+ t. c5 F
& x9 G! ^2 W; M0 v0 t0 g- Y: H- ) i* f0 F, `2 a( g
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
+ a2 Z3 c; I6 W - {% |, i" s* s$ v6 `" H* M
- Error_Handler();
% ` N, j6 b: W - }
5 g+ N' g8 N& O$ e, \" `. F4 l
6 t" z- g; ~3 F2 h6 R) }# f
6 i1 V7 @/ P. ?1 E- /**Configure the Systick interrupt time ; N& J2 F: g$ S$ u0 q
- */2 i O* n J! B) B+ _( [
- HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);: N6 [! ?; R' z+ H
- 3 J9 i6 J; H+ f: [; j
- $ v" `, B" m% o) Z
- /**Configure the Systick 8 v$ c1 @; `. n5 h1 j3 `
- */
0 S& w( Y6 d5 n( B - HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); n) \/ p) Z9 r$ l5 @. A
- 1 P u" p6 ^, N+ d/ H8 B
- " ?" W& A" ?- _8 B* m
- /* SysTick_IRQn interrupt configuration */) u9 j. y. x: T2 g
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
0 \# Y2 i$ ]- A% S0 }$ N - }
, J5 K }( C5 Y7 |, i
) g- l+ h7 H# E4 w
复制代码
: f6 x5 R3 e* F! w( a* |: y8 Z9 L; A% N; d% Q6 N. @8 ^; j
|