EDA365电子工程师网

标题: 送给新手:STM32的时钟树解析 [打印本页]

作者: liao821    时间: 2015-11-12 09:56
标题: 送给新手:STM32的时钟树解析
STM32的时钟树' ?" }7 I% u; P: a2 H5 g% a
         对于广大初次接触STM32的读者朋友(甚至是初次接触ARM器件的读者朋友)来说,在熟悉了开发环境的使用之后,往往“栽倒”在同一个问题上。这问题有个关键字叫:时钟树。
% \! V+ B3 h0 z   众所周知,微控制器(处理器)的运行必须要依赖周期性的时钟脉冲来驱动——往往由一个外部晶体振荡器提供时钟输入为始,最终转换为多个外部设备的周期性运 作为末,这种时钟“能量”扩散流动的路径,犹如大树的养分通过主干流向各个分支,因此常称之为“时钟树”。在一些传统的低端8位单片机诸如 51,AVR,PIC等单片机,其也具备自身的一个时钟树系统,但其中的绝大部分是不受用户控制的,亦即在单片机上电后,时钟树就固定在某种不可更改的状 态(假设单片机处于正常工作的状态)。比如51单片机使用典型的12MHz晶振作为时钟源,则外设如IO口、定时器、串口等设备的驱动时钟速率便已经是固 定的,用户无法将此时钟速率更改,除非更换晶振。
( m: j# v0 S1 y( P* r' u         而STM32微控制器的时钟树则是可配置的,其时钟输入源与最终达到外设处的时钟速率不再有固定的关系,本文将来详细解析STM32微控制器的时钟树。图1是STM32微控制器的时钟树,表1是图中各个标号所表示的部件。0 B1 Q7 \3 i. H: q& v$ E- N
标号            图1标号释义
8 N3 k: S3 ^9 H0 a. f# C0 `1     内部低速振荡器(LSI,40Khz)
4 r9 ]3 n- o, Z- x) D& O( A0 X2     外部低速振荡器(LSE,32.768Khz)
  h% g+ k# ?- U, V! j& F. [7 E. A3    外部高速振荡器(HSE,3-25MHz)2 k. k6 R- w- Z3 m" u* Q" n! x
4    内部高速振荡器(HIS,8MHz)
' W. ?. l' M. U5 p0 [+ k; d2 A5    PLL输入选择位1 W# r8 w, `2 p$ @
6    RTC时钟选择位$ w9 D6 I2 }/ m: p; q: B* P" H( z
7    PLL1分频数寄存器
, Q! w* }- M4 z& T8    PLL1倍频寄存器) u' ~* j, Z9 I
9    系统时钟选择位- a5 _3 ^6 S/ E8 H
10            USB分频寄存器
. x1 f2 v( t0 Q11            AHB分频寄存器
6 m1 @1 [6 t1 i" U5 [2 L6 ]12            APB1分频寄存器4 @4 \: V# d4 Q6 l
13            AHB总线
* d8 ]; _5 |( W3 _/ f14            APB1外设总线
( |0 Z; D( a) A: j' x8 o4 J15            APB2分频寄存器0 c. ?6 K0 u$ A3 H+ A+ T
16       APB2外设总线
3 e5 i1 w/ P+ [5 s& u) i( N17            ADC预分频寄存器0 |3 ]: s. U% _9 \5 x/ v( ^, C9 I
18            ADC外设6 H( |4 |5 S  Y! Q0 ]
19            PLL2分频数寄存器
- m& h4 }/ q+ ]* @4 H0 }20            PLL2倍频寄存器
9 N; a  ]+ h7 b/ E21            PLL时钟源选择寄存器; M) ^6 F7 M' i
22            独立看门狗设备
, q5 C+ O; h) |* J* c3 }, G1 Z23       RTC设备
4 M: o1 w  \/ Z( R( G( @STM32时钟树.jpg+ k5 _9 [9 W; z; V5 s$ v6 W1 ]3 e: {
图1  STM32的时钟树
; f8 G$ D3 Y- g+ R' ~' h   在认识这颗时钟树之前,首先要明确“主干”和最终的“分支”。假设使用外部8MHz晶振作为STM32的时钟输入源(这也是最常见的一种做法),则这个 8MHz便是“主干”,而“分支”很显然是最终的外部设备比如通用输入输出设备(GPIO)。这样可以轻易找出第一条时钟的“脉络”:8 O! Y% B( ?7 ?; w+ u3 k2 c$ M7 o# }
3——5——7——21——8——9——11——13
& X2 K1 B+ \2 M! y! r. z对此条时钟路径做如下解析:2 f& G$ C. b) u, D8 }6 i: G
对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;
$ u6 a6 Z" Z2 n0 N! j$ N) \- u# j对于5,通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);
- H1 F# B: L  z0 ^/ p9 D对于7,设置外部晶振的分频数(假设1分频);
# b" l/ |% O$ T, a" r+ O对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);, q6 y* N. V" ^% [( O% d
对于8,设置PLL倍频数(假设9倍频);7 J. ]$ }0 L( n* G) P6 n; a" Y6 J* I
对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);3 J7 v$ Y5 k+ c! ]
对于11,设置AHB总线分频数(假设1分频);
# y+ U" \5 }" h对于13,时钟到达AHB总线;( F+ N" r% _9 _3 o% ^6 @
在上一章节中所介绍的GPIO外设属于APB2设备,即GPIO的时钟来源于APB2总线,同样在图1中也可以寻获GPIO外设的时钟轨迹:
0 g  y7 ^1 ~0 Q- d) @0 j* R4 V3——5——7——21——8——9——11——15——16- s# W3 B8 j) Q7 k) ]8 o( H
对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;* R8 x& Q6 K5 |; U
对于5, 通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);) l6 ?' S) G% P, P3 {+ c" p; r
对于7,设置外部晶振的分频数(假设1分频);
  |' D: V( P5 @6 r( W对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);2 ~6 O  d/ I7 ~1 [  g
对于8,设置PLL倍频数(假设9倍频);
7 }# u0 b9 L1 f对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);
1 y' w* g& ~' \" m& r4 B对于11,设置AHB总线分频数(假设1分频);
5 a: R( m0 o+ |4 D对于15,设置APB2总线分频数(假设1分频);- p% g7 K% G1 j2 p/ W9 |
对于16,时钟到达APB2总线;6 ~# g- p) i% @
现在来计算一下GPIO设备的最大驱动时钟速率(各个条件已在上述要点中假设):# g6 L7 ]9 u6 Q6 q5 m. A
1)   由3所知晶振输入为8MHz,由5——21知PLL的时钟源为经过分频后的外部晶振时钟,并且此分频数为1分频,因此首先得出PLL的时钟源为:8MHz / 1 = 8MHz。
% \5 |- ]  F7 a+ p/ B# [' X# S* _2)   由8、9知PLL倍频数为9,且将PLL倍频后的时钟输出选择为系统时钟,则得出系统时钟为 8MHz * 9 = 72MHz。
0 W/ u3 a; F& A) [7 V" C3)   时钟到达AHB预分频器,由11知时钟经过AHB预分频器之后的速率仍为72MHz。* v& T2 E0 I0 q+ a" a- q
4)   时钟到达APB2预分频器,由15经过APB2预分频器后速率仍为72MHz。9 X' U/ F7 t4 p
5)   时钟到达APB2总线外设。
# Y2 u6 [- x- u* I$ y% J; y$ R因此STM32的APB2总线外设,所能达到的最大速率为72MHz。依据以上方法读者可以搜寻出APB1总线外设时钟、RTC外设时钟、独立看门狗等外设时钟的来龙去脉。接下来从程序的角度分析时钟树的设置,程序清单如下:/ Y8 q" V5 m8 P: P* }8 @
void RCC_Configuration(void)  {- d9 ?- g) {5 {, Y( ^& B
{
, @  |# |" {% G. C  b$ j        ErrorStatus HSEStartUpStatus;                                                                                                     (1)
+ b5 g; g8 a/ }) w- P" [        RCC_DeInit();                                                             (2)8 T2 V1 U: }) H; J& P5 G3 \1 [5 W) X
        RCC_HSEConfig(RCC_HSE_ON);                                                                                                   (3)! n( r# b2 @! ~5 z9 q
        HSEStartUpStatus = RCC_WaitForHSEStartUp();                                                                     (4)
) ~0 I" [$ J0 g5 M' S  M        if(HSEStartUpStatus == SUCCESS)                                                                                                (5): ^. r. B% r" C: e. V3 X
        {+ ]$ l  E; s' c/ T; C
                   RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                              (6): ]8 f# E2 k) {6 a+ u0 N
                     RCC_PCLK2Config(RCC_HCLK_Div1);                                                                               (7)' g( u* S3 f# j+ }* e/ i6 t
                     RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                (8)
2 q! ?0 D- B# [+ m) a                    FLASH_SetLatency(FLASH_Latency_2);                                                                             (9)
) ^: @# U+ v. v' b$ N  g! i                    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);                                      (10)1 z' n0 @% j4 |$ Q7 T/ ^% M
                  RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                                         (11)
0 ~+ i" @+ t3 R# {" s2 T                  RCC_PLLCmd(ENABLE);                                      (12)
5 t, U1 W- V! C' e4 Z. y3 V& G; q; k$ i                  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);                                                       (13)
/ t' a$ `: E7 q/ J5 p                  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                               (14)
  u. P  t+ O4 z" l8 B7 O                  while(RCC_GetSYSCLKSource() != 0x08);                                                                               (15)8 y9 F, d! F! @9 D$ |, V/ D8 L1 b
        }
" u1 u$ l/ e; t
作者: Haiting32451    时间: 2016-6-4 15:48
学习中,谢谢分享
/ _. t1 s" m. I7 r




欢迎光临 EDA365电子工程师网 (https://bbs.elecnest.cn/) Powered by Discuz! X3.2