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

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

[复制链接]
TLLED 发布时间:2018-12-8 14:43
本帖最后由 TLLED 于 2018-12-8 14:42 编辑
- T+ c/ Y& M; B6 y$ t1 m0 ^: A
7 i/ E7 Q* z4 a    通过第16章节 -- RCC-使用HSE/HSI配置时钟  的学习来重新认识系统总线和外设时钟的配置。 # L1 X( t6 C" A2 f- }9 y  R) b& o

+ F2 J$ w( ~: A9 s" n  e    一、手册中有关时钟配置的内容; K) V8 o* E9 d7 L

/ g$ }( o& i4 L9 Z* u  }4 _

7 W: Y  ]6 }2 `3 V3 f    1.1、系统时钟框图: + f1 K. y$ G. O5 D  R
         里面显示出STM32芯片所有时钟和有关配置的寄存器位              1.png
( s4 U8 V4 ]. Z. n
- Q( B) M9 D" z0 @  n5 d4 p    9 l2 A6 |+ V- O: u9 n$ e% X
    二、系统启动有关时钟配置代码

* }8 h- X6 I" P' o+ R# j2 J8 r. V, a7 k; Z0 V' w% k2 }3 D
    2.1、系统启动分析3 S, o& ~% k) R* s! F3 F
        上篇介绍启动代码分析,会执行Reset Handler服务处理程序。
8 M: v8 _2 p. y2 y8 r" @1 K- f8 \; J         100.png 3 ?' S  `7 V0 s4 H! J
         里面有执行SystemInit系统初始化程序
  ?# f* |/ ~! g+ A        
101.png : q! E  [9 o) }
         102.png " S0 }' p9 y: `6 T$ n/ E: E
         103.png
       里面调用SetSysClock函数设置系统时钟3 |' c: Y9 |: T* A2 @
       104.png       " x# g2 k4 q' J0 R
       SetSysClock函数配置为72MHz后调用SetSysClockTo72函数, B* [4 o4 g& V# k/ D% t
       105.png ' @% ]9 }. ^- v- b1 k
       106.png * Z0 h& V: F% l8 m' v. S+ z) a( \
       107.png

/ c. j5 T$ p% V  F3 |       108.png
' k: b$ n4 l7 N        上面是系统上电启动中,系统初始化和系统时钟配置过程,已经把总线时钟配置为72MHz。
8 W5 r# h- S7 |8 Z! k9 t
    0 o) {' {' a: H4 p8 D+ |+ [
    三、时钟配置实例
, w' D1 ]$ {! _# t4 Y: ?$ k' ]
1 T) ^% r3 k5 f! j. K
    3.1、配置HSE时钟  
3 U1 Q; s* ?  i' [- d$ `& ]$ u        了解系统时钟配置流程后,来实践使用时钟配置。* f+ ?7 z, m( z( c
        在系统时钟框图中,HSE时钟配置
) l7 v$ M, Z5 s  L0 t, L         109.png , \* |: B# ^* P6 Z5 Q: d
    >选择外部时钟OSC32_IN和OSC32_OUT两个引脚上接的8MHz无源晶振  R# D& U$ r+ B7 I# U: ?, g
    >通过PLLXTPRE来选择HSE时钟不分频还是2分频。4 Y8 k9 Z: G& a- m1 b8 J! n9 J
    >通过PLLSRC来选择内部时钟HSI和外部时钟HSE时钟选择。
* c9 i, z6 }% q; `$ T" a/ o    >通过PLLMUL来选择倍频设置,如系统总线72MHz,晶振频率8M*倍频9=72MHz
  A. l6 C& a+ Z
    >通过SW来选择时钟源HSI,PLLCLK和HSE时钟源。" [5 O+ u1 i- }3 i0 f/ U) X/ J9 O8 @

5 r5 _' v2 _6 Q: w
6 y) ]3 O! Z0 R0 S8 ~
    3.2、程序源码
% f. b8 T; i; v0 m  f) ^$ S         3.2.1、HSE时钟初始化4 q5 X+ U2 ?3 E+ ~2 C# J+ l$ b
         PLL时钟倍频到72MHz
* v. g6 s+ n/ ^. Q6 r7 v% M   
  1. static void HSE_SetSysClock(void)
    7 ?- K7 c6 w+ D6 q
  2. {. M6 Q, w" }$ ~1 B$ x' m# T9 b
  3.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;; M( E. r* B8 ~! H5 E- L
  4.   
    $ G- Q8 l9 o; t6 I- z( F0 m
  5.   RCC_DeInit();                                                                                        //RCC恢复默认状态  " S( D) [2 g: U8 K  ?
  6.         RCC_HSEConfig(RCC_HSE_ON);                                //打开HSE时钟
    $ W' g+ S" ]$ e* y5 h
  7.        
    6 M; |4 j! `( v. |- a1 S
  8.         HSEStatus=RCC_WaitForHSEStartUp();   //等待HSE时钟稳定) U0 ?( i* n+ _4 i6 |7 m

  9. : s0 |* U) S+ h' _6 v" a- q% D3 J
  10.   if (HSEStatus == SUCCESS)0 Q: F! ?1 s+ d0 L* Y0 X
  11.   {/ a0 B9 ~5 `1 y( b
  12.     /* Enable Prefetch Buffer */
    + I. C1 H' y9 S6 b$ z4 N
  13.                 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);            //使能FLASH预存取缓冲区
    ! b8 B& @! T' ?7 U: R0 l* b
  14.                 FLASH_SetLatency(FLASH_Latency_2);                                                                                                % L! N8 _/ ]8 y' B" x' l& w

  15. , V, \1 B' t0 ^( @# L$ p/ \2 f
  16.                 RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                                                        //AHB - HCLK=SYSCLK
    7 x7 L$ {' n$ m8 u
  17.                 RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                                                //APB1 -- PCLK1=HCLK/2
    $ [7 H: c& l6 L# w: w0 i, B9 J
  18.                 RCC_PCLK2Config(RCC_HCLK_Div1);                                                                                                                //APB2 -- PCLK2=HCLK
    & `- t3 e1 e- f5 F; D8 ?- o

  19. 8 c$ t, I/ e: q
  20.                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频- g; H/ s: F: B* W4 a  T8 u( M1 {7 O
  21.                 RCC_PLLCmd(ENABLE);                                                                                                                                                                //使能PLL! R* ~+ ?- j( S8 y* v. O0 e
  22.                         ( W( [+ E& @# E' p) U4 `4 u- w/ _$ v
  23.                 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)                                        //等待PLL稳定# z! l* v3 e0 M  T9 o% R" }
  24.                 {: ~1 F) `( o3 X$ H1 I
  25.                 }
    + O  [) M( c/ k9 \3 p
  26.                 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                                //PLL稳定后,时钟切换到SYSCLK4 _2 q9 Q  L  E
  27.                 - k6 Q' [2 }$ ]; q, y* Y
  28.                 6 W; y. u  S  n+ _; m+ t0 u4 F
  29.                 while(RCC_GetSYSCLKSource()!=0x08)                                                                                                //读取时钟切换状态位,确保PLLCLK被选为系统时钟: D1 _7 R) d( x* u: D+ \
  30.                 {! D% a0 m3 t. v/ E+ ~' X) s7 y. d
  31.                 }. E: \6 `  K( ^' q0 e0 r6 W
  32.   }1 j- B( Q4 l, \6 M2 k+ u
  33.   else% ^( f8 ?( c4 I/ R# |# \
  34.   {0 d) g- y) H1 k
  35.   }' j. G; S  v9 v3 ~, R" Y
  36. }
复制代码
       3.2.2、MCO引脚初始化
' S5 \) P# q8 i2 F) J4 Q
  1. //MCO引脚配置
    7 H8 m: x* r: h1 r
  2. void MCO_GPIO_Config(void)
    , _+ p8 p/ o' v( W
  3. {
    2 j3 H& U9 }/ g
  4.         GPIO_InitTypeDef  GPIO_InitStructure;2 W* _! I: R) }9 L
  5.        
    9 R( j$ F2 E7 r0 f' l% P3 x8 w
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                 //使能PA端口时钟' j* A# [/ w/ j  y# G* T- H
  7.        
    7 D3 ^% {8 }; P& A8 I" C/ r/ G
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;                                                                
    / j! W; V& ^' s. }
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                         
    1 x6 U; c4 Q! g& N7 `
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz' e2 g2 V+ r8 L: G4 `
  11.         GPIO_Init(GPIOA, &GPIO_InitStructure);                                                                
    4 c$ x) L, c# n* U# P$ }
  12. }
复制代码
       3.2.3、LED引脚初始化9 h2 M; _8 C4 R" j. _7 y# t: f

  1. 3 `, G6 n# V3 T, Z0 N8 z
  2. void LED_GPIO_Config(void)
    8 d0 Z- U5 d! V$ B' w5 f/ g# A
  3. {9 F" z# l2 N' p- W1 G
  4.         GPIO_InitTypeDef  GPIO_InitStructure;7 e3 ~$ M! ?0 g$ t$ I
  5.         : B* z% y  F: P2 u
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                 //使能PA端口时钟, j; x1 q6 T+ w. y; j! x& m
  7.         , W8 v7 c$ i0 ~
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                                                
    * u  r6 j8 E2 g# P) n8 {
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                          / U" e0 Q5 Z2 Q, M
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz2 i! K9 v! o8 Y# S% X, Z
  11.         GPIO_Init(GPIOB, &GPIO_InitStructure);       
    0 h5 |* N+ i- j0 j/ s# |+ r
  12. }
复制代码
       3.2.4、主程序
" j+ |5 `6 H0 r* r3 E! E
  1. int main(void)
    ; e6 b; R+ O' V& F9 R- }$ O+ N
  2. {: {3 K! t3 _# E$ n! @& L" A
  3.         uint32_t i;
    " O" U3 ^- X! Z" W
  4.         HSE_SetSysClock();3 V+ B+ c( x; m; C/ W3 w% z$ @; M
  5.         MCO_GPIO_Config();
    8 S/ Z' I* t( p5 I& t) u) \5 v
  6.         RCC_MCOConfig(RCC_MCO_SYSCLK);       
    ) ~- C+ g. C1 t0 l$ i
  7.         LED_GPIO_Config();        5 D8 y. l+ _6 H/ W3 m6 j7 |- l! S
  8.   while (1), e$ g8 Q& `# x) h) ?
  9.   {" _: q9 A& x8 X- k# c
  10.                
    6 n$ Z0 \! f/ n9 m4 H. O
  11.                 for(i=0;i<0xffff;i++);" E  Z  c; Y  t) V. x" R
  12.                 GPIO_SetBits(GPIOB,  GPIO_Pin_9);
    ; w( K5 ?* k' }
  13.                 for(i=0;i<0xffff;i++);% o9 t# S$ K; f- v, I8 w* i
  14.                 GPIO_ResetBits(GPIOB, GPIO_Pin_9);6 B! s5 r5 _, O. u% {- I' z
  15.   }. a3 v' Z8 s. ~9 P9 _
  16. }
复制代码
! a( O% T3 X1 Q2 T+ ^  u% S1 k
    四、程序执行结果
) s5 [- k+ `% T2 d3 S* l6 {+ I, j- w& ~3 Y2 \. ]* z
+ n6 l! |( {2 d# r7 G" L$ s
    4.1、PLL时钟设置为72MHz,倍频系数设置为9
6 Z% \; m! o0 h3 h        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频# P* [4 x  \0 S5 M% O8 I& q) c
        4.1.1、MCO输出时钟频率72M# {  [$ r4 a: K4 x4 [+ R5 f( f
        
F0002TEK.png
7 {. u! S/ F. P; t& W- _) @9 `        4.1.2、LED引脚输出
7 z8 X; P, \6 Y" \
         F0003TEK.png ) K' L7 b6 z6 s- ~: A$ V* c

3 Y. d5 A( }+ p9 O  ^# I   
4.2、PLL时钟设置为56MHz,倍频系数设置为7        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);                        //PLL倍频
3 g& q' ~8 H9 M  q& C1 @4 z        4.2.1、MCO输出时钟频率56M
- v8 p3 M9 \# H& O) T% U5 W' U         F0005TEK.png 4 _: G9 s" n! t8 r# O
        4.2.2、LED引脚输出
$ e) v4 |4 }0 r) Q2 Z- ~        
F0004TEK.png
$ [* p, W+ _0 s+ O! ~        LED输出宽度比72M时钟时,宽度变宽
" X# p' o, ]" |6 f+ h
    4.3、PLL时钟设置为88MHz,倍频系数设置为11        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_11);                        //PLL倍频) e$ o; y' p# G4 a& Q+ z- Q
        4.3.1、MCO输出时钟频率88M
* ^8 Y# P1 k( b% |2 x$ Y         F0006TEK.png ! T' g7 b( |! t( E- ^9 f2 y
        4.3.2、LED引脚输出, k$ h/ o4 ]* i# z, r( P) b  n% s, d
        
F0007TEK.png ) F9 l1 ~4 z" r# X6 E) V
        LED输出宽度比72M时钟时,宽度变窄
3 e! i* W# r. R: v( L3 h7 j2 V
6 X5 G, D: [6 _/ R
    五、结论
3 b& v; O" L9 }! x' o7 E1 ^

. r8 u; u* i  a5 A# {

: y! V( S( B- F" w6 ^; Z- L         使用外部时钟时,通过改变PLL的倍频系统可以改变SYSCLK时钟频率,来降频或超频工作。HSI配置和HSE差不多,就不在列出。
9 c5 u! h) A7 K4 c" r
+ u4 z  o3 P6 o9 d9 i" Q" S- B2 x0 m7 L- }, z! |

/ v7 k$ t2 \7 W( A* u2 ^9 @& p% {# X" g9 I" }6 M
  v9 e0 F4 n2 R- m

2 I; k: l6 Q: q+ l/ }
* T, _% M) e$ V+ q# N9 ^+ |
9 J- P8 B' L$ q' H9 i

评分

参与人数 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
您的配置里有这样一句
+ u  E+ M( b% e7 bRCC->CFGR &= (uint32_t)((uint32_t) ~(RCC_CFGR_PLLSRC |RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));) O* I5 R: s* H2 ?/ d/ Z& o
这句话是把第16-21位清零
hhhhhhhaa 回答时间:2020-4-29 15:06:54
PLLSRC:PLL输入时钟源 (PLL entry clock source)  位16
: e+ X; k2 z, e4 U由软件置’1’或清’0’来选择PLL输入时钟源。只能在关闭PLL时才能写入此位。% c. w3 A" o. m/ u7 [
0:HSI振荡器时钟经2分频后作为PLL输入时钟6 g+ l/ C  f! \1 T2 t
1:HSE时钟作为PLL输入时钟。
8 {/ T) I3 N9 a& `3 t以上是手册里说的
hhhhhhhaa 回答时间:2020-4-29 15:16:47
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE| RCC_CFGR_PLLMULL9);/ U% x& N& D: \& o1 ?; R
这句话是不是把相应的位置1 这样就能配置了

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版