找回密码
 注册
关于网站域名变更的通知
查看: 548|回复: 1
打印 上一主题 下一主题

送给新手:STM32的时钟树解析

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2015-11-12 09:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
STM32的时钟树* O% e) v% W2 L! i' I9 ]
         对于广大初次接触STM32的读者朋友(甚至是初次接触ARM器件的读者朋友)来说,在熟悉了开发环境的使用之后,往往“栽倒”在同一个问题上。这问题有个关键字叫:时钟树。
( `& `- J3 G6 s$ C& Y   众所周知,微控制器(处理器)的运行必须要依赖周期性的时钟脉冲来驱动——往往由一个外部晶体振荡器提供时钟输入为始,最终转换为多个外部设备的周期性运 作为末,这种时钟“能量”扩散流动的路径,犹如大树的养分通过主干流向各个分支,因此常称之为“时钟树”。在一些传统的低端8位单片机诸如 51,AVR,PIC等单片机,其也具备自身的一个时钟树系统,但其中的绝大部分是不受用户控制的,亦即在单片机上电后,时钟树就固定在某种不可更改的状 态(假设单片机处于正常工作的状态)。比如51单片机使用典型的12MHz晶振作为时钟源,则外设如IO口、定时器、串口等设备的驱动时钟速率便已经是固 定的,用户无法将此时钟速率更改,除非更换晶振。* q& t4 Z. V/ O' ]) x
         而STM32微控制器的时钟树则是可配置的,其时钟输入源与最终达到外设处的时钟速率不再有固定的关系,本文将来详细解析STM32微控制器的时钟树。图1是STM32微控制器的时钟树,表1是图中各个标号所表示的部件。
; O, Z0 L" p' F+ Z# R; p0 Q* j- B& l0 w标号            图1标号释义# z3 ]9 P  n; @3 J% S0 W
1     内部低速振荡器(LSI,40Khz)
9 n, }6 l( ]1 K  B3 u) A; O2     外部低速振荡器(LSE,32.768Khz)
" _. V( l  q- c5 U: K5 D2 i3    外部高速振荡器(HSE,3-25MHz)
# z+ F+ c& i! B& A4    内部高速振荡器(HIS,8MHz)
1 ^, D% L6 ]8 f1 w+ J. t' e5    PLL输入选择位
+ }, ~# R! T# q3 D) z: v6    RTC时钟选择位
3 e2 r$ S; U% \4 p4 {4 n' `7    PLL1分频数寄存器, c8 G* |! R5 ~/ E9 c/ M
8    PLL1倍频寄存器
# ^6 [3 @) c" i; T$ _9    系统时钟选择位
- w0 Z# {- ]! I10            USB分频寄存器
. `% Y% }- [- J. a! P. A11            AHB分频寄存器2 ?2 G) x8 j) k- s8 s( K/ n
12            APB1分频寄存器
, {, w1 z: ?! z* g; q13            AHB总线$ T1 S& v; |! `( \1 P/ R) ]2 u8 a
14            APB1外设总线
) h; M4 f; o3 h15            APB2分频寄存器
2 `+ d6 l$ R4 v1 n. ]' C9 Z+ Z3 i, `16       APB2外设总线
9 J2 j8 @  F! ]* S( ?! U17            ADC预分频寄存器: ?9 S8 Y1 ^6 n; o" i9 n" |
18            ADC外设
/ i- u. H( a) s+ ?; F$ L19            PLL2分频数寄存器
% s' }& a& L" i& B$ x20            PLL2倍频寄存器8 T; V' u! o- u4 C
21            PLL时钟源选择寄存器  f- l7 `( V, g8 }1 w# o
22            独立看门狗设备
1 B& E$ N5 b& b  Z  o6 y/ v23       RTC设备
* x& o9 X/ Z5 g3 t; mSTM32时钟树.jpg
$ Z8 A' U" l* |! Q* \图1  STM32的时钟树! q) q: {: U1 e4 r0 y8 |/ p
   在认识这颗时钟树之前,首先要明确“主干”和最终的“分支”。假设使用外部8MHz晶振作为STM32的时钟输入源(这也是最常见的一种做法),则这个 8MHz便是“主干”,而“分支”很显然是最终的外部设备比如通用输入输出设备(GPIO)。这样可以轻易找出第一条时钟的“脉络”:2 Z5 g8 A* [& b: i: M7 O( p  ?. `
3——5——7——21——8——9——11——13
4 ?% {! ]% d$ s/ C% b2 ?* p% ?; z0 q对此条时钟路径做如下解析:0 _1 ^* o. d& x+ Q, Q2 T
对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;. Z( W/ t& O- `8 Z
对于5,通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);: A6 Z4 T% V4 `
对于7,设置外部晶振的分频数(假设1分频);
2 K1 Y* I# d4 g& C# |% P- x对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);: z4 R: I# r1 L/ l* L( j! U
对于8,设置PLL倍频数(假设9倍频);
! K, T# W% }3 J/ \$ e0 m/ e( T对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);
3 I7 o) Z. W% S, D对于11,设置AHB总线分频数(假设1分频);7 f& d6 n3 T7 r* }" p
对于13,时钟到达AHB总线;
2 _, l9 A0 ]5 ]0 `9 v* Y; J在上一章节中所介绍的GPIO外设属于APB2设备,即GPIO的时钟来源于APB2总线,同样在图1中也可以寻获GPIO外设的时钟轨迹:
9 \' `9 x$ z7 @7 e' Z3——5——7——21——8——9——11——15——16- `9 g3 Y1 ]* w' S1 V& P( s, V
对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;
0 x; R) C9 B1 V对于5, 通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);
1 e0 k! |# C; b) p5 `$ o# J$ e对于7,设置外部晶振的分频数(假设1分频);4 {* k* R% i7 e) f% c7 I. ^/ w- Y2 E: j
对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);" W6 @9 Q! {4 E
对于8,设置PLL倍频数(假设9倍频);
5 p" k8 }3 O+ ?对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);8 l& N, |  u$ G# p; G) ~, w; z
对于11,设置AHB总线分频数(假设1分频);
& b+ A8 @3 W& p; c对于15,设置APB2总线分频数(假设1分频);9 L5 z9 W# N. w/ O: f: j
对于16,时钟到达APB2总线;
! k. G6 b! C* r现在来计算一下GPIO设备的最大驱动时钟速率(各个条件已在上述要点中假设):
% ]8 S1 G; L9 ]+ u% T1 g3 u* v1)   由3所知晶振输入为8MHz,由5——21知PLL的时钟源为经过分频后的外部晶振时钟,并且此分频数为1分频,因此首先得出PLL的时钟源为:8MHz / 1 = 8MHz。
6 a, ~& o' u" g/ _, G* h) h2)   由8、9知PLL倍频数为9,且将PLL倍频后的时钟输出选择为系统时钟,则得出系统时钟为 8MHz * 9 = 72MHz。
! r% m5 h5 u. R' F# W3 k3)   时钟到达AHB预分频器,由11知时钟经过AHB预分频器之后的速率仍为72MHz。
/ k. v; s* m/ H4 E4)   时钟到达APB2预分频器,由15经过APB2预分频器后速率仍为72MHz。
! Y" {) a4 k4 c! [5)   时钟到达APB2总线外设。2 B  L9 `# i4 C
因此STM32的APB2总线外设,所能达到的最大速率为72MHz。依据以上方法读者可以搜寻出APB1总线外设时钟、RTC外设时钟、独立看门狗等外设时钟的来龙去脉。接下来从程序的角度分析时钟树的设置,程序清单如下:5 ]  S  K8 p, m" f! F8 G- C  I% \* T, u
void RCC_Configuration(void)
' x) H; F8 W; k% {{
8 M2 E) e0 n8 L. u  X. g  j        ErrorStatus HSEStartUpStatus;                                                                                                     (1)
3 E3 |4 |+ e3 o& K6 p        RCC_DeInit();                                                             (2)2 U) M. h% A& t+ g6 F3 `/ r
        RCC_HSEConfig(RCC_HSE_ON);                                                                                                   (3)5 s/ a' y+ X5 L; I9 |
        HSEStartUpStatus = RCC_WaitForHSEStartUp();                                                                     (4)
& Q9 n- e# p# t7 n8 l        if(HSEStartUpStatus == SUCCESS)                                                                                                (5)
; {8 U0 i6 I7 d0 ?; ?) k        {
* _4 s; R5 Z6 S  x                   RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                              (6)9 a1 L6 D* ^. K( y! M# [2 ~
                     RCC_PCLK2Config(RCC_HCLK_Div1);                                                                               (7)
0 s1 F7 m# e# r3 I0 ?4 W* T& V+ T$ E% {                     RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                (8)
/ {6 S9 I, f5 D7 `                    FLASH_SetLatency(FLASH_Latency_2);                                                                             (9)
% w: L  h* b( ?! a& G2 i                    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);                                      (10)
7 T6 |9 Q  X' R                  RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                                         (11)
: w7 |! ^1 v. P- n8 E+ E+ U                  RCC_PLLCmd(ENABLE);                                      (12)) o. |  p, z  C- m- _
                  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);                                                       (13)% U( K. n5 [8 ]' B7 v
                  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                               (14)
( m7 q* ^( R9 J. z& b                  while(RCC_GetSYSCLKSource() != 0x08);                                                                               (15)
" ~$ U$ b$ s& d: g1 S+ G2 J        }! b: \# `2 [+ `( C+ Z, k3 W

该用户从未签到

2#
发表于 2016-6-4 15:48 | 只看该作者
学习中,谢谢分享
4 a/ B4 {) [& _5 p1 U( n
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-16 19:18 , Processed in 0.078125 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表