我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 2029|回复: 6

[资料贡献] STM32的时钟树解析

[复制链接]

该用户从未签到

886

主题

902

回帖

537

积分

二级逆天

积分
537

社区居民忠实会员社区劳模原创达人终身成就奖金点子奖

QQ
发表于 2015-11-12 10:08:57 | 显示全部楼层 |阅读模式
[/free]STM32的时钟树  |6 `1 R. v7 q0 P) {
          对于广大初次接触STM32的读者朋友(甚至是初次接触ARM器件的读者朋友)来说,在熟悉了开发环境的使用之后,往往“栽倒”在同一个问题上。这问题有个关键字叫:时钟树。
& C6 B& _2 c8 J1 A6 F- @! h: P   众所周知,微控制器(处理器)的运行必须要依赖周期性的时钟脉冲来驱动——往往由一个外部晶体振荡器提供时钟输入为始,最终转换为多个外部设备的周期性运 作为末,这种时钟“能量”扩散流动的路径,犹如大树的养分通过主干流向各个分支,因此常称之为“时钟树”。在一些传统的低端8位单片机诸如 51,AVR,PIC等单片机,其也具备自身的一个时钟树系统,但其中的绝大部分是不受用户控制的,亦即在单片机上电后,时钟树就固定在某种不可更改的状 态(假设单片机处于正常工作的状态)。比如51单片机使用典型的12MHz晶振作为时钟源,则外设如IO口、定时器、串口等设备的驱动时钟速率便已经是固 定的,用户无法将此时钟速率更改,除非更换晶振。
$ k2 l+ ]( Z2 p% u1 G% [         而STM32微控制器的时钟树则是可配置的,其时钟输入源与最终达到外设处的时钟速率不再有固定的关系,本文将来详细解析STM32微控制器的时钟树。图1是STM32微控制器的时钟树,表1是图中各个标号所表示的部件。
4 g- P$ l& c# ]3 t  [  _; q7 f标号            图1标号释义
0 M' |2 h8 d1 t% G1     内部低速振荡器(LSI,40Khz)
+ X6 [4 b2 |  n, p+ U/ Q, _3 ~) x2     外部低速振荡器(LSE,32.768Khz)0 ]& |* f' J/ @$ D
3    外部高速振荡器(HSE,3-25MHz)
/ M9 {& {" D  E: u# Y4    内部高速振荡器(HIS,8MHz)2 ~/ a+ i+ S9 z3 U
5    PLL输入选择位
+ ~' F' z3 B& I, Y  P: F6    RTC时钟选择位
" X) N3 [5 q8 ^' o1 F' n7    PLL1分频数寄存器& k" T2 C" N2 B  S- \
8    PLL1倍频寄存器
+ r7 G5 a* I! v& {% n9    系统时钟选择位
$ ?  h3 D' T  @( x: p10            USB分频寄存器
4 v" b1 q/ {/ V5 |' u& [0 _11            AHB分频寄存器! R- F9 \' N' T# q( E# V# _
12            APB1分频寄存器
0 F1 w4 W& M, B8 N5 a: f" J6 S13            AHB总线4 w5 Q  d" ^4 v8 P! p2 V
14            APB1外设总线
5 j2 q2 ]0 J; U/ y, @15            APB2分频寄存器+ G( ?8 p5 j! H. K  [
16       APB2外设总线
+ y: n( y" E5 ]/ q' y4 `17            ADC预分频寄存器
8 x# t4 \  c! J! C6 y" b18            ADC外设
4 x) n, u) H& u* k" t8 k+ O" V19            PLL2分频数寄存器! m( j3 E4 y% q1 w9 {" ^
20            PLL2倍频寄存器0 w" ?0 B  y# o4 n# {
21            PLL时钟源选择寄存器5 @  @( u8 K. ~% v- a  ~& q
22            独立看门狗设备
7 k. }( F% e5 t% Q% F6 @4 e23       RTC设备3 z- e/ O! K+ N. r7 D; ~
STM32时钟树.jpg! h2 D3 @+ D3 V2 R
图1  STM32的时钟树
* F* x# q% i2 q. Z) e6 k   在认识这颗时钟树之前,首先要明确“主干”和最终的“分支”。假设使用外部8MHz晶振作为STM32的时钟输入源(这也是最常见的一种做法),则这个 8MHz便是“主干”,而“分支”很显然是最终的外部设备比如通用输入输出设备(GPIO)。这样可以轻易找出第一条时钟的“脉络”:
. b: e5 A  }+ \% ]) J" I3——5——7——21——8——9——11——13+ T6 p. ]  Y' A3 N. s
对此条时钟路径做如下解析:0 J) u; z3 \0 Q" }: H
对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;& T" \7 R+ k5 d: D# r! T2 }2 m; k
对于5,通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);& B) O2 D' O# R" d' g4 `% H# w: i
对于7,设置外部晶振的分频数(假设1分频);$ T. s. \# t4 W) i$ Z, \
对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);& }, z" d+ O5 L
对于8,设置PLL倍频数(假设9倍频);* o2 U# v1 {6 Z; Y
对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);
3 `$ G7 v4 V! ?. r2 z" j; S对于11,设置AHB总线分频数(假设1分频);6 @1 e) R9 m$ P2 A* a
对于13,时钟到达AHB总线;
/ |0 D' b! |; z; _$ n: H在上一章节中所介绍的GPIO外设属于APB2设备,即GPIO的时钟来源于APB2总线,同样在图1中也可以寻获GPIO外设的时钟轨迹:7 {/ r0 O" t) k- t" U  J
3——5——7——21——8——9——11——15——16
& n2 B5 p0 n, F1 {  ?5 p对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;
5 Z  g% l& J1 }( Z对于5, 通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);; a; R$ ]/ `5 P7 ^' F
对于7,设置外部晶振的分频数(假设1分频);3 f- H! R0 Z. m+ \$ s3 }) L; s
对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);
- _( H% v" ~! ~, U: T- h对于8,设置PLL倍频数(假设9倍频);
  k- P* X% V5 T对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);, `; @5 d9 p1 y3 Z( x
对于11,设置AHB总线分频数(假设1分频);
: j+ @- z' o. C+ T0 Z& v4 s对于15,设置APB2总线分频数(假设1分频);7 p, }6 U$ K3 L1 w% i
对于16,时钟到达APB2总线;  o4 T! {! ~$ m- I2 Z' ]
现在来计算一下GPIO设备的最大驱动时钟速率(各个条件已在上述要点中假设):+ P  d' G; z- J% y; R  G
1)   由3所知晶振输入为8MHz,由5——21知PLL的时钟源为经过分频后的外部晶振时钟,并且此分频数为1分频,因此首先得出PLL的时钟源为:8MHz / 1 = 8MHz。9 b. K) \- v* h6 J) v( \7 T
2)   由8、9知PLL倍频数为9,且将PLL倍频后的时钟输出选择为系统时钟,则得出系统时钟为 8MHz * 9 = 72MHz。5 _6 V+ ?$ g+ n% P, a8 h
3)   时钟到达AHB预分频器,由11知时钟经过AHB预分频器之后的速率仍为72MHz。  Y5 l/ a6 z; r0 B! i
4)   时钟到达APB2预分频器,由15经过APB2预分频器后速率仍为72MHz。9 t) |& ]% E6 p3 W" _# W) A0 y0 k8 j
5)   时钟到达APB2总线外设。
" V/ l& M  d( ?0 e7 L: y9 g9 l4 c因此STM32的APB2总线外设,所能达到的最大速率为72MHz。依据以上方法读者可以搜寻出APB1总线外设时钟、RTC外设时钟、独立看门狗等外设时钟的来龙去脉。接下来从程序的角度分析时钟树的设置,程序清单如下:
8 t, }: t( x% S; V$ |/ Cvoid RCC_Configuration(void)7 E, D- h+ L9 ~, ]" {3 B1 E8 Z- F
{
6 O3 e6 A5 P5 R) A! |        ErrorStatus HSEStartUpStatus;                                                                                                     (1)/ L6 Z: `, {4 _; |; b1 N4 v# m. O6 u
         RCC_DeInit();                                                             (2)
8 M4 e8 s& |" O, X, P, Z9 l        RCC_HSEConfig(RCC_HSE_ON);                                                                                                   (3)
$ B4 t3 ]+ }7 e+ a0 i" m        HSEStartUpStatus = RCC_WaitForHSEStartUp();                                                                     (4)
+ G6 Q+ ]" ^; ~9 q3 ~- Q# c2 }) }& c        if(HSEStartUpStatus == SUCCESS)                                                                                                (5)
# l2 U' O  V. I$ B5 w1 T        {# _! j. m! y$ c/ m
                    RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                              (6)
' U4 M; `: D4 J5 g: M                     RCC_PCLK2Config(RCC_HCLK_Div1);                                                                               (7)0 p" x" a$ U1 \) K: S4 \. L5 j4 B
                      RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                (8)3 ]6 ]* a& [4 m; F7 y
                     FLASH_SetLatency(FLASH_Latency_2);                                                                             (9)
6 Z% l5 n6 u( ^8 l8 o                    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);                                      (10)
0 Y0 J) W0 k& L                  RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                                         (11)' ^2 k: s8 M  o
                   RCC_PLLCmd(ENABLE);                                      (12)
; A4 N+ |" `  x8 V, X                  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);                                                       (13)' q6 g7 X5 n0 V& `/ k
                   RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                               (14)
# |  @' e; N% ]                  while(RCC_GetSYSCLKSource() != 0x08);                                                                               (15)9 c0 p1 P' o- q2 d
         }[sub][/sub][sup][/sup][strike][/strike]
[free]
购买主题 本主题需向作者支付 1 枚金币 才能浏览
回复

使用道具 举报

  • TA的每日心情
    慵懒
    2024-6-14 16:03
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    0

    主题

    1万

    回帖

    7618

    积分

    二级逆天

    积分
    7618

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2018-2-2 19:23:18 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    3 小时前
  • 签到天数: 110 天

    [LV.6]常住居民II

    2

    主题

    8570

    回帖

    9888

    积分

    二级逆天

    积分
    9888

    社区居民终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2018-2-7 08:48:30 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    1157

    回帖

    6

    积分

    二级逆天

    积分
    6

    终身成就奖

    QQ
    发表于 2019-3-10 08:37:49 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    348

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖

    发表于 2019-3-11 08:59:18 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    8

    主题

    2158

    回帖

    0

    积分

    二级逆天

    积分
    0

    社区居民终身成就奖

    QQ
    发表于 2019-3-11 08:59:47 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    29

    主题

    1427

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2023-2-3 08:46:57 | 显示全部楼层
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    论坛开启做任务可以
    额外奖励金币快速赚
    积分升级了


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    平平安安
    TOP
    快速回复 返回顶部 返回列表