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

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

[复制链接]
TLLED 发布时间:2018-12-8 14:43
本帖最后由 TLLED 于 2018-12-8 14:42 编辑
* O2 K0 T- [) E
$ E6 B3 l5 P- t" [    通过第16章节 -- RCC-使用HSE/HSI配置时钟  的学习来重新认识系统总线和外设时钟的配置。 ( |/ ~. d# Y5 g$ }
! x% R% n7 e3 D. I
    一、手册中有关时钟配置的内容
/ ]% n" v7 K4 M! W7 o# s8 K
+ N$ J5 @* H2 H& _3 e

% C1 r! |% o# Y$ }5 u5 ]* o' x    1.1、系统时钟框图: 9 X8 {5 Y, n# c9 F
         里面显示出STM32芯片所有时钟和有关配置的寄存器位              1.png ( v0 f$ N# Z" }3 h7 q. j1 C$ N
2 d: S7 j6 k' ?2 g& I; L% r" N
    9 g5 O+ n/ X% h4 c9 H/ d
    二、系统启动有关时钟配置代码
3 X' F- F9 c* J" u' f  g
; b! V1 m' k3 C/ Q6 @8 a
    2.1、系统启动分析
7 z" j( ]" {+ ]        上篇介绍启动代码分析,会执行Reset Handler服务处理程序。6 b/ m5 |. h. R
         100.png & S$ G7 v; H4 \
         里面有执行SystemInit系统初始化程序
1 \+ o8 L1 U0 q        
101.png 5 S/ v! o1 {6 Y. ]) `
         102.png
9 w' C2 {3 l0 C5 P. G) S' ^         103.png
       里面调用SetSysClock函数设置系统时钟1 q2 f/ d# a% S% }* t: u! e* I" |
       104.png       
5 `. \9 y; }0 C  w* e( A' m       SetSysClock函数配置为72MHz后调用SetSysClockTo72函数! F9 w. V  v. `
       105.png , j4 f* D( A+ f. g! m* T0 n
       106.png 0 }1 ]+ Y- q+ {' G3 ^
       107.png

" n$ Z) y# D4 O# i! f       108.png
# s/ [0 s1 P$ u# B9 ?) \        上面是系统上电启动中,系统初始化和系统时钟配置过程,已经把总线时钟配置为72MHz。

& X$ d; k( T! r/ X' e& L# a! B   
/ O+ U: y* C/ l& Q' D/ o/ @0 l8 d- _    三、时钟配置实例* D8 U2 N( K; Y+ v
: f6 {  ?. X6 i3 [

* J1 o' K! J$ U: z. q$ @$ x    3.1、配置HSE时钟  ) g, t) t# @9 ]5 |0 t9 t( S0 h  h. c6 j
        了解系统时钟配置流程后,来实践使用时钟配置。1 Y2 v* a# V: H+ p
        在系统时钟框图中,HSE时钟配置
3 j% K& s: e$ }1 n) ^# j- q         109.png   H' u) L! ?1 u
    >选择外部时钟OSC32_IN和OSC32_OUT两个引脚上接的8MHz无源晶振  O$ S$ [0 q; I4 u; \5 M
    >通过PLLXTPRE来选择HSE时钟不分频还是2分频。9 d. Q. l" m9 L2 U5 A3 R1 _9 \
    >通过PLLSRC来选择内部时钟HSI和外部时钟HSE时钟选择。  U3 H9 y% q9 g1 ~( o* Q
    >通过PLLMUL来选择倍频设置,如系统总线72MHz,晶振频率8M*倍频9=72MHz

" K$ D3 Y0 ~" ?# ?    >通过SW来选择时钟源HSI,PLLCLK和HSE时钟源。
& h( s. d/ K3 j' s0 |, H1 z* l( i. Y9 t( U
7 |1 c, H1 \7 E& u4 \9 B7 {- d
    3.2、程序源码. ~  l" v) a; {9 a; g' d
         3.2.1、HSE时钟初始化
- O: ]0 g6 S2 ?( c9 ]! o         PLL时钟倍频到72MHz$ m+ m" E3 E8 q$ s" A
   
  1. static void HSE_SetSysClock(void)) h0 B0 \$ z* @0 J; Z) _
  2. {
    " y3 d( m6 u, I
  3.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;) I2 }# L( @# j# u
  4.   9 K9 s; l6 G+ \& w
  5.   RCC_DeInit();                                                                                        //RCC恢复默认状态  
    * M& ]- q/ s$ }4 q* W# `( ^
  6.         RCC_HSEConfig(RCC_HSE_ON);                                //打开HSE时钟, U6 X( h4 Y4 L4 V: g; c
  7.         ! w0 s1 J2 n, A8 O4 R/ _  b
  8.         HSEStatus=RCC_WaitForHSEStartUp();   //等待HSE时钟稳定
    % @" B5 J1 s- O1 Z
  9. , B6 J% Z9 `) U
  10.   if (HSEStatus == SUCCESS)+ f5 S" z  C9 R- Q0 L
  11.   {
    3 r4 }' P8 X  z8 n6 d: h8 B, L
  12.     /* Enable Prefetch Buffer */
    , m3 N' z+ v7 l; C( y2 P! @3 f
  13.                 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);            //使能FLASH预存取缓冲区3 C' x0 n+ A! x
  14.                 FLASH_SetLatency(FLASH_Latency_2);                                                                                                , }4 H& ^6 Z/ N/ k) F# j
  15. " ^1 j& W0 M, e8 e" n& H
  16.                 RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                                                        //AHB - HCLK=SYSCLK
    ( j6 F; |- b: K$ N4 h
  17.                 RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                                                //APB1 -- PCLK1=HCLK/2& i  h1 ], ?  [" i" r! ]
  18.                 RCC_PCLK2Config(RCC_HCLK_Div1);                                                                                                                //APB2 -- PCLK2=HCLK) x0 B0 K6 b# b4 q, o9 Z

  19. ' u: V6 }2 O% p
  20.                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频
    + X: M  m5 X4 P! `% U- y
  21.                 RCC_PLLCmd(ENABLE);                                                                                                                                                                //使能PLL
    ' s0 k7 Z7 B  _4 g5 R
  22.                         & w7 b4 |* J8 p4 A: e
  23.                 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)                                        //等待PLL稳定
      ?- R4 f; X2 S2 Y6 c' g
  24.                 {( W; c9 Q6 Z+ ]4 y
  25.                 }; S4 |4 ?8 A# f
  26.                 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                                //PLL稳定后,时钟切换到SYSCLK- L/ ?& s! {1 ?) h6 F- f. {
  27.                
    8 N3 [# o" w: Z  [( c$ b# D
  28.                 1 r8 j, K' M9 {* M9 Y  w2 L
  29.                 while(RCC_GetSYSCLKSource()!=0x08)                                                                                                //读取时钟切换状态位,确保PLLCLK被选为系统时钟
    1 ]1 Q5 s8 Z3 E
  30.                 {
    % `& n3 b* e6 H
  31.                 }  a* `+ a' I; V0 \8 a
  32.   }' `, P8 x0 Y2 Y9 n2 i8 H; t  b
  33.   else% S0 G/ G  V% q
  34.   {% |+ e5 F$ o" d  H0 G/ @5 t
  35.   }
    / B( M' g8 a7 v4 x' o2 `
  36. }
复制代码
       3.2.2、MCO引脚初始化$ r) x4 }2 w$ E" f! @
  1. //MCO引脚配置* A3 t% ^: U& V  J9 e/ ]
  2. void MCO_GPIO_Config(void)
    * [4 N, N$ p3 {; v" @( s1 K
  3. {
    * Z$ {# R0 o" a* N4 B1 N: Z5 `
  4.         GPIO_InitTypeDef  GPIO_InitStructure;
    3 @) @* k0 i  e* q4 E, q  j
  5.         . M0 t) P0 d0 e" u, K- L
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                 //使能PA端口时钟
    $ o' u9 |. f! }' L  E
  7.         + P! v7 ^- a& x$ w5 a0 J
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;                                                                
    * L. v0 H$ [% \8 c
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                          3 f/ U2 V6 I) S) M) Z9 a
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz  ~6 R' I" _) L/ G8 S9 i! @3 Z
  11.         GPIO_Init(GPIOA, &GPIO_InitStructure);                                                                 ; l# o" t! ^7 P4 D- x
  12. }
复制代码
       3.2.3、LED引脚初始化% ^3 E/ B1 |2 P( Z' B8 t/ U/ r! P
  1. # \& Z0 j: {, l( Q7 z
  2. void LED_GPIO_Config(void); B$ y; ]) q, D
  3. {1 }5 \) K! m8 H1 h9 X' A' j
  4.         GPIO_InitTypeDef  GPIO_InitStructure;, W1 j; o' l& @9 e$ S+ X
  5.         5 \! j. R; P. Z2 m. I  s7 m
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                 //使能PA端口时钟3 U6 O/ o: X% H9 b! c
  7.         9 x) c6 m! e, Y, ^" F4 M$ H
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                                                 9 i2 @& o0 p8 ]* e- F9 t
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                          1 k( }  n- [( L5 A
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz, O) ]+ y; t0 m
  11.         GPIO_Init(GPIOB, &GPIO_InitStructure);        : g! k0 v; T  W, k5 F
  12. }
复制代码
       3.2.4、主程序2 V2 \9 h: Y! m3 H0 _
  1. int main(void)- l/ W5 T4 i% f& }* l% t  z3 c
  2. {
    7 K. a9 L" P$ E
  3.         uint32_t i;8 R, Q6 ]4 @; g5 p, v
  4.         HSE_SetSysClock();6 i/ ]7 h! J+ a8 v+ q. j/ `/ s
  5.         MCO_GPIO_Config();# L9 h. p' J  w3 M1 I2 Z; Y4 E
  6.         RCC_MCOConfig(RCC_MCO_SYSCLK);        0 {8 ^/ l1 ]. Y& c! C5 y7 i6 e
  7.         LED_GPIO_Config();        / P1 t- [4 C# ?4 O# i" D9 I
  8.   while (1)( {& o6 x1 H% h: M8 K' O
  9.   {6 x$ s$ w; d6 B3 x3 n- d5 k  Z
  10.                
    8 C- W, `, w$ h( {# e( F
  11.                 for(i=0;i<0xffff;i++);
    ' o, K% m9 g- ~  k
  12.                 GPIO_SetBits(GPIOB,  GPIO_Pin_9);1 }7 h, P) j5 z* P6 S
  13.                 for(i=0;i<0xffff;i++);
    3 w; }6 q0 j5 W  u- s
  14.                 GPIO_ResetBits(GPIOB, GPIO_Pin_9);% l0 B& U9 L$ G6 B& ^4 G* H8 [7 C
  15.   }9 A& ^; ]& e% L* G& f- x, i0 `
  16. }
复制代码
4 l6 a9 n# y8 I0 \% X* s" V
    四、程序执行结果: P) @* g2 d+ e4 b, b; j3 ^

& U  w$ J) g  A
9 A+ }) `7 u* f$ q9 t
    4.1、PLL时钟设置为72MHz,倍频系数设置为9" O. N( l: t+ F: S
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频
0 N1 e6 b' D- A9 k! q        4.1.1、MCO输出时钟频率72M
4 @$ p0 z+ O; x( X        
F0002TEK.png
1 c  f- [% A4 S, R& E5 b% N6 H! H6 g        4.1.2、LED引脚输出
6 p1 _8 n9 E* e( Q2 n0 h
         F0003TEK.png
1 @( A+ R# H2 g9 Y/ S5 r' k
9 M4 _( q% t" _: R4 f   
4.2、PLL时钟设置为56MHz,倍频系数设置为7        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);                        //PLL倍频  I& g0 h3 t; S- a: }8 W
        4.2.1、MCO输出时钟频率56M# Y$ Q8 {% h) S5 `# J, E
         F0005TEK.png
- S7 W7 {* }# b, E! A3 J: R        4.2.2、LED引脚输出
" [! I! v5 m- F4 v9 X) m        
F0004TEK.png ; a; \8 `- l! c5 ^$ f' h
        LED输出宽度比72M时钟时,宽度变宽2 T4 t8 _; J7 r  @+ r* A
    4.3、PLL时钟设置为88MHz,倍频系数设置为11        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_11);                        //PLL倍频4 f( W& @2 u% V0 t) _* S
        4.3.1、MCO输出时钟频率88M
: K0 N- k( U  O7 g! V$ U$ A3 `         F0006TEK.png & e% [: X  K# v) C7 \
        4.3.2、LED引脚输出. f: y) ]# j* [$ b0 x+ F
        
F0007TEK.png ! z3 o: N# B  a$ P" L& ?4 v& o) g
        LED输出宽度比72M时钟时,宽度变窄
# T9 J7 A+ {8 r7 M. J

6 a3 P' V& ~* J7 }4 x    五、结论

5 `4 ^: ~  z/ r  @/ z( W/ e9 w' d* ~  c$ [

6 ~# C( F4 ?, e3 J% K1 \+ B: ]& c         使用外部时钟时,通过改变PLL的倍频系统可以改变SYSCLK时钟频率,来降频或超频工作。HSI配置和HSE差不多,就不在列出。
0 Z0 @: ?2 Z4 D" C: T1 O# o* Y; y# g  O/ X

/ H5 b: M/ a  B& W
! c6 K9 f  l9 S9 h: P% K& Z  _+ @9 e

7 k; H1 t* B, G4 Y' }1 _, `7 i; w! o8 l- _1 c7 V
# p4 g7 ?/ C, ]% C3 Z  j! k
8 C% K: T, e! M6 e! l

评分

参与人数 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
您的配置里有这样一句
5 V1 ^" Z0 c. W$ I! VRCC->CFGR &= (uint32_t)((uint32_t) ~(RCC_CFGR_PLLSRC |RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));% g* {& g( {: l9 s! w
这句话是把第16-21位清零
hhhhhhhaa 回答时间:2020-4-29 15:06:54
PLLSRC:PLL输入时钟源 (PLL entry clock source)  位16& p& L  F9 w, `( |
由软件置’1’或清’0’来选择PLL输入时钟源。只能在关闭PLL时才能写入此位。. `/ s% R' A# [7 C" @8 i
0:HSI振荡器时钟经2分频后作为PLL输入时钟" o1 _; k) L+ D& S( E% A5 a) U
1:HSE时钟作为PLL输入时钟。
* b% H' s3 T7 ^. c0 @以上是手册里说的
hhhhhhhaa 回答时间:2020-4-29 15:16:47
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE| RCC_CFGR_PLLMULL9);1 ]4 R* \& N. o" D! g9 L. k
这句话是不是把相应的位置1 这样就能配置了

所属标签

相似分享

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