你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32库开发实战指南F103 -- 3、RCC-使用HSE/HSI配置时钟

[复制链接]
TLLED 发布时间:2018-12-8 14:43
本帖最后由 TLLED 于 2018-12-8 14:42 编辑
) R, f/ M- k6 `8 @1 ?6 k' r* T
$ W+ l9 b( @/ v& W! Y% I( Y    通过第16章节 -- RCC-使用HSE/HSI配置时钟  的学习来重新认识系统总线和外设时钟的配置。
. m/ l* d1 M8 e! A7 c- c8 D

' \% a: y0 F1 W+ b: d    一、手册中有关时钟配置的内容: a: z8 |" x( Q5 X% P

- _' k- ~9 U* X" ?# N
9 \# `4 {+ ]6 w; `$ M
    1.1、系统时钟框图:
: y4 {8 T& l" v. n3 |6 U/ r, {         里面显示出STM32芯片所有时钟和有关配置的寄存器位              1.png 0 }. a0 f; ~! |" n

7 H0 c% U& N! \   
- d+ ~' O+ d. H' g+ e    二、系统启动有关时钟配置代码
8 V8 t6 W+ s6 V  X) ]
1 S9 @0 C2 f6 A! C/ p4 h' Z
    2.1、系统启动分析
- b. T4 i5 k; c        上篇介绍启动代码分析,会执行Reset Handler服务处理程序。
  G/ j2 k) J; W9 z! p         100.png
2 E8 t0 ~1 C1 ~8 S  {+ Z9 y         里面有执行SystemInit系统初始化程序. V2 n* J+ u# }6 \/ F3 [# O8 F
        
101.png 0 ~; O( d/ G; m% `" N1 m' S& x4 x: ?# i7 H
         102.png * C+ w9 b' K; A* B# P' f! T
         103.png
       里面调用SetSysClock函数设置系统时钟
: i+ F3 t- b) x# E5 _( R4 y       104.png       
0 H2 [( N6 v8 H       SetSysClock函数配置为72MHz后调用SetSysClockTo72函数# M$ `8 E) F/ E/ `& A0 T
       105.png
% E5 x8 ?8 _+ B, d) P       106.png 2 G2 ?' |9 Z& @2 ]; Z7 C- W4 f
       107.png

  |* m( F. @+ e& i       108.png * t, E7 o, I2 T# @1 D/ ~* M
        上面是系统上电启动中,系统初始化和系统时钟配置过程,已经把总线时钟配置为72MHz。
1 y) |8 K: r- {. Z
    : E, m& f3 o" k( p! m& o# G
    三、时钟配置实例
" s0 _% E6 N% r3 j8 s
) B' P- y- G! ?/ c0 j5 S0 l% U/ e5 Y
. S' R& o) T5 n9 A" x2 A
    3.1、配置HSE时钟  
$ \1 X3 W- |, M" r$ h0 v9 N        了解系统时钟配置流程后,来实践使用时钟配置。
9 [- ?2 A, e  c" b7 C9 i        在系统时钟框图中,HSE时钟配置/ b9 X2 W2 B2 G& e& E1 c
         109.png $ U+ ~0 J! H  M
    >选择外部时钟OSC32_IN和OSC32_OUT两个引脚上接的8MHz无源晶振
5 Q5 F% {( A( Y    >通过PLLXTPRE来选择HSE时钟不分频还是2分频。0 ^3 A8 ~8 l% T* y1 [& m4 G
    >通过PLLSRC来选择内部时钟HSI和外部时钟HSE时钟选择。
! I& J6 A$ r6 V; R7 ], D$ G& E4 }    >通过PLLMUL来选择倍频设置,如系统总线72MHz,晶振频率8M*倍频9=72MHz

2 d: O" {' n) I6 V# I1 ?! O    >通过SW来选择时钟源HSI,PLLCLK和HSE时钟源。
: |- P! s7 |+ A7 `0 Y
3 e# w4 q1 z3 G5 X. Y" `$ G
0 K- I* v+ ~4 l! @/ O" [2 a% ]
    3.2、程序源码
2 [6 L9 {. A4 s; L5 N9 F         3.2.1、HSE时钟初始化7 H  l; a, i- h/ {7 H
         PLL时钟倍频到72MHz( G0 e9 l3 c" x. k
   
  1. static void HSE_SetSysClock(void)+ P5 `2 k, Z' x/ T8 G' ?
  2. {
    " H7 j) I3 u4 \
  3.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    9 N9 U1 l4 u. h+ G
  4.   6 s! t: Q$ U& \* g$ H- D, W
  5.   RCC_DeInit();                                                                                        //RCC恢复默认状态  
    4 l; x. B+ ?& q8 i
  6.         RCC_HSEConfig(RCC_HSE_ON);                                //打开HSE时钟; h5 R5 a( |# P3 c% H; C; C
  7.        
      i; a8 }" Y2 @
  8.         HSEStatus=RCC_WaitForHSEStartUp();   //等待HSE时钟稳定- d  o. A8 @! y  N; y
  9. " d4 T" C! _5 i) p: O4 @  y0 i- e
  10.   if (HSEStatus == SUCCESS)
    ; i* S. C  L4 T$ o7 j8 Q% B4 _
  11.   {1 E% [9 S5 R. K! X8 s; o& _
  12.     /* Enable Prefetch Buffer */
    ' V" n& }# m& @! j# S, h
  13.                 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);            //使能FLASH预存取缓冲区- w( k, P- |2 C' ~* k9 k% r
  14.                 FLASH_SetLatency(FLASH_Latency_2);                                                                                               
    9 e) I; x7 G9 k5 q7 M, Q
  15. 8 e* h/ B6 r, @2 h" D
  16.                 RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                                                        //AHB - HCLK=SYSCLK
    , H9 i1 S& O1 y* h7 j$ C  E8 r
  17.                 RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                                                //APB1 -- PCLK1=HCLK/2
    / R* V8 F& z9 Y! M4 p$ U+ m; R
  18.                 RCC_PCLK2Config(RCC_HCLK_Div1);                                                                                                                //APB2 -- PCLK2=HCLK
    : G* c& x2 v$ J, z' J0 C
  19. ' j- l+ N( d/ I+ s- l9 \: ~8 A: q
  20.                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频8 R0 m0 H3 I7 ?2 D; C8 t
  21.                 RCC_PLLCmd(ENABLE);                                                                                                                                                                //使能PLL( v4 l' E2 b7 N  L" m- i. v
  22.                         * F: @' R; p' E: ~! F$ n; `7 ]
  23.                 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)                                        //等待PLL稳定1 u1 E# t6 x4 T5 y
  24.                 {& p  ~5 d8 X" C' i
  25.                 }
    ; x2 z5 R/ R7 [+ w7 ]0 ]& J
  26.                 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                                //PLL稳定后,时钟切换到SYSCLK
    3 p3 k+ _, X8 r5 ]/ B2 O
  27.                 ( `+ Y; @: f% {* g$ u5 r, Q
  28.                
    5 T4 [7 u" C0 ]4 _
  29.                 while(RCC_GetSYSCLKSource()!=0x08)                                                                                                //读取时钟切换状态位,确保PLLCLK被选为系统时钟
    ( z/ i& P8 O% [4 F4 c
  30.                 {1 H) a" J& k2 @9 u0 T
  31.                 }
    2 Y5 n. v6 _, R. y3 v
  32.   }
    8 Z7 g+ v. b! B9 Y# R
  33.   else
    * G4 t+ B: {6 }) z0 n8 D
  34.   {
    * f: @. U, Q! N; E+ d0 `
  35.   }# o9 w4 h2 P4 p% K; A  r7 K
  36. }
复制代码
       3.2.2、MCO引脚初始化' k( K% w" y/ ?& F# h1 L- U
  1. //MCO引脚配置; I* H$ P# z  P2 j) Y
  2. void MCO_GPIO_Config(void)
    6 f. y. N; a" f, k4 u; x2 g) v
  3. {5 c) E! m+ w0 d9 T2 s
  4.         GPIO_InitTypeDef  GPIO_InitStructure;
    / F1 y& e+ e# o
  5.        
    4 Q& F1 r- z( k7 B9 n
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                 //使能PA端口时钟
    7 i; a( x6 ^% |2 Q
  7.         , W/ h8 j* c+ J% v0 F6 X
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;                                                                
    ! `6 p  |8 u8 k- u2 f; x& }
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                          - e, E( D5 ^  B  Q
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz
    9 q; x. @% ]. F# d$ e" K; ]
  11.         GPIO_Init(GPIOA, &GPIO_InitStructure);                                                                 ( @% y2 r3 J5 z  S4 k( J
  12. }
复制代码
       3.2.3、LED引脚初始化; n4 i% e( o" D" Q

  1. - ?: e) J3 b0 U
  2. void LED_GPIO_Config(void)' k9 I5 g& y, \7 g
  3. {
    5 k5 E. \+ B( W0 ]4 h
  4.         GPIO_InitTypeDef  GPIO_InitStructure;% ~5 h; ^) [  v9 R, E) e
  5.        
    ! }$ {) U6 ?" {  L5 Q$ l/ Q9 _
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                 //使能PA端口时钟7 M1 r/ P! ?0 [/ F  W0 g  i% f
  7.         " J& T! j) A3 N5 b9 z* S/ v
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                                                
    " p& l/ O6 H& {
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                         
    : }: L& U# ?- ~* u) g$ I
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz% ~6 k+ Y- @& M1 p) F8 z
  11.         GPIO_Init(GPIOB, &GPIO_InitStructure);       
    ( Y. G# ]* Y& {5 N) A8 ]
  12. }
复制代码
       3.2.4、主程序
1 Z% s  F# C; @4 u8 W& _) I& V' {; i
  1. int main(void)
    ( o' o! i# K3 ~* Z' R, Z2 t
  2. {
    % v5 k- O% O, }
  3.         uint32_t i;
    ' }( q; b' m5 P) k- \% |
  4.         HSE_SetSysClock();
    7 S3 T" `! \3 v: {8 Q5 C' f
  5.         MCO_GPIO_Config();
    . p7 J0 N& F% `
  6.         RCC_MCOConfig(RCC_MCO_SYSCLK);        9 H; x9 Y1 ]1 Y" J& b8 f
  7.         LED_GPIO_Config();       
    ; r  ?" G% F" Y$ B1 Y, O
  8.   while (1)
    : B; W* ]3 C0 P. l- M+ x' B
  9.   {9 l# Z2 B3 A, }8 g$ C
  10.                
    ' ~. Q! R9 V! S
  11.                 for(i=0;i<0xffff;i++);
    1 S/ I' ]8 a4 g4 L3 L" S5 O' n6 s
  12.                 GPIO_SetBits(GPIOB,  GPIO_Pin_9);7 l4 w& U% S3 c3 n
  13.                 for(i=0;i<0xffff;i++);
    ) |8 W1 u: g9 C# L: ~+ O
  14.                 GPIO_ResetBits(GPIOB, GPIO_Pin_9);
    + ~/ T, O* h) V# s
  15.   }
    # O% e7 p& L7 Q" q, w* Q/ r' H9 h$ y* O
  16. }
复制代码

2 I: ]% B) i* R, m3 n- ?! J% \    四、程序执行结果1 ?7 ?! _5 J: A. C9 ~

. {; C; q! K& S: ]$ d
: K0 L" k7 k: M0 w, z& J7 R# T
    4.1、PLL时钟设置为72MHz,倍频系数设置为9
, l8 y" `( C' x6 B5 o( W$ n        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频5 F+ b* ~: x( U
        4.1.1、MCO输出时钟频率72M
: C& M4 |. A1 N1 w1 f        
F0002TEK.png # Z9 H( s* M% \9 d* L
        4.1.2、LED引脚输出

; g+ W: I/ R2 Z0 |# v5 k* U5 v" b         F0003TEK.png 5 c; D& {7 W& ^% p+ m/ @
" X; r, r8 i4 z( d$ J; s
   
4.2、PLL时钟设置为56MHz,倍频系数设置为7        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);                        //PLL倍频
1 j2 e6 ?' @5 U0 n  t+ P  u        4.2.1、MCO输出时钟频率56M
3 [$ a$ e; ~( s& u& v         F0005TEK.png 8 Z# b. I- b# Q: G0 x  e. G
        4.2.2、LED引脚输出( a5 ]+ w; f/ Y
        
F0004TEK.png   |5 _7 S8 j) k+ i* O' S/ q
        LED输出宽度比72M时钟时,宽度变宽1 W+ X; i7 |" s
    4.3、PLL时钟设置为88MHz,倍频系数设置为11        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_11);                        //PLL倍频
* Y! w$ G* W/ @& x2 G        4.3.1、MCO输出时钟频率88M( u6 c5 P8 \7 x+ x& D- Y5 P7 H
         F0006TEK.png 1 R/ o/ @2 A# O. ]- v/ C& @
        4.3.2、LED引脚输出
. k9 {$ ?$ |  L- B        
F0007TEK.png
+ f. @& n; w/ h3 R        LED输出宽度比72M时钟时,宽度变窄

0 ~/ P  T' V0 [0 B1 {  i$ H6 z- z* H2 G
    五、结论
3 n, r3 E" Z9 Q2 B4 Z5 {

% d4 m- J. H4 E, E3 W& K" }' j: Z

0 M) Z9 N6 h5 r7 k9 U" K9 ]         使用外部时钟时,通过改变PLL的倍频系统可以改变SYSCLK时钟频率,来降频或超频工作。HSI配置和HSE差不多,就不在列出。
+ f6 A! G4 \% `) Q! U4 @& j
$ k3 O& y. ^4 C  e* U: t5 y8 Z( T
, ?7 K* M  _' W% ^1 X% l3 f) q, {* j' f; g, T; x; \4 k( t

2 o' m# S2 Q9 |- Q3 g
9 z' {+ m; V( |; H) t  r
9 ^9 @& |, i8 Z6 t( M- g
: R9 F6 c- G4 G/ G6 a( Z

( T* \$ u6 I* W( S; ~! {  E+ C6 o

评分

参与人数 1 ST金币 +20 收起 理由
STMCU + 20

查看全部评分

收藏 评论4 发布时间:2018-12-8 14:43

举报

4个回答
STMCU-管管 回答时间:2018-12-10 10:15:27
支持
hhhhhhhaa 回答时间:2020-4-29 15:05:17
您的配置里有这样一句& c( p8 d' r# ?7 X' t
RCC->CFGR &= (uint32_t)((uint32_t) ~(RCC_CFGR_PLLSRC |RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
, [7 u6 H" Q5 U这句话是把第16-21位清零
hhhhhhhaa 回答时间:2020-4-29 15:06:54
PLLSRC:PLL输入时钟源 (PLL entry clock source)  位16
" s$ p* E1 O6 {9 \( c5 |由软件置’1’或清’0’来选择PLL输入时钟源。只能在关闭PLL时才能写入此位。, l3 p5 {0 G% _
0:HSI振荡器时钟经2分频后作为PLL输入时钟
2 w+ R5 Y6 X) f1:HSE时钟作为PLL输入时钟。2 v# U: O) C; Q: k( w+ K+ g
以上是手册里说的
hhhhhhhaa 回答时间:2020-4-29 15:16:47
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE| RCC_CFGR_PLLMULL9);; N! l; I. [; i4 K4 I. n5 }. C! d
这句话是不是把相应的位置1 这样就能配置了

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版