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

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

[复制链接]
TLLED 发布时间:2018-12-8 14:43
本帖最后由 TLLED 于 2018-12-8 14:42 编辑 8 L! L" u$ w0 K$ V9 v( ?' q
8 A/ b9 P* q9 W! c% P: h
    通过第16章节 -- RCC-使用HSE/HSI配置时钟  的学习来重新认识系统总线和外设时钟的配置。
- H; m4 P& u* s) u  z

1 I$ g6 _4 a, |* V# m' Y    一、手册中有关时钟配置的内容1 ^+ G" V, o+ Z3 d

" i0 f  n- u: [: \

2 T- L$ M# Y. I  ]2 G: q    1.1、系统时钟框图: ! d0 m7 A% B0 E" U' K3 B; D" ^
         里面显示出STM32芯片所有时钟和有关配置的寄存器位              1.png
: @6 A- H, K8 F4 ?# f- _; |- p! W. E! z8 I/ H
   
) C2 B+ ~, R# y    二、系统启动有关时钟配置代码
3 f5 a% w% ?; U  T. @

/ M6 z: U: [$ {; A    2.1、系统启动分析
, O$ P, B/ @" G# X- L        上篇介绍启动代码分析,会执行Reset Handler服务处理程序。  S0 ~0 C% a$ m, F
         100.png 8 _" C* S+ Z# t/ Y4 ^, h6 Z$ u
         里面有执行SystemInit系统初始化程序0 I% D! i9 w) P6 x, u, P
        
101.png & |/ \5 x0 v, k% P; U1 e
         102.png
. ]7 j# [" T& U# j( o& _         103.png
       里面调用SetSysClock函数设置系统时钟
4 O! E, B7 K, e. o       104.png       
" d/ h/ k1 ?$ N# v1 M  `       SetSysClock函数配置为72MHz后调用SetSysClockTo72函数
4 s, j% \9 I/ H# H. s9 S       105.png ! D; _* @* c& _* j
       106.png
* a0 M% q/ g. {: x       107.png

* S0 n2 j: o  H8 v3 X- D       108.png $ s# {0 d5 x2 `* W( Q8 C1 h
        上面是系统上电启动中,系统初始化和系统时钟配置过程,已经把总线时钟配置为72MHz。
( G9 L: ^) T% _: _& J
   
4 i+ X" J; a* M$ ~* x' s    三、时钟配置实例
# |! S* c" e$ Q/ L$ H7 L, \: ]$ s$ g3 @4 e+ B# n
6 s$ l! {( c/ g0 c
    3.1、配置HSE时钟  9 d; K; U9 b# j! E9 F
        了解系统时钟配置流程后,来实践使用时钟配置。: f( b7 b" Z+ z# h9 R
        在系统时钟框图中,HSE时钟配置
0 s# }; u' f' |; z5 w) B& |) g         109.png 1 ]' \+ h1 R5 P( B/ ?
    >选择外部时钟OSC32_IN和OSC32_OUT两个引脚上接的8MHz无源晶振
0 b4 A: \" j3 f/ J9 ~    >通过PLLXTPRE来选择HSE时钟不分频还是2分频。
$ t# r9 g/ t& Q* W1 X- Y6 g" B    >通过PLLSRC来选择内部时钟HSI和外部时钟HSE时钟选择。$ v3 |! o- J$ l3 @
    >通过PLLMUL来选择倍频设置,如系统总线72MHz,晶振频率8M*倍频9=72MHz
: V2 j9 ]) M& S0 ]. @4 x& u7 I
    >通过SW来选择时钟源HSI,PLLCLK和HSE时钟源。
  V8 ]# y1 a" F. {" x
6 i7 T3 O* [" @, I
( B6 `! a- K( |
    3.2、程序源码' i, a6 w9 g4 c4 }- K  a, ^5 {* {
         3.2.1、HSE时钟初始化
2 ^- i0 g' l# E/ r& i$ j         PLL时钟倍频到72MHz
) U. q# o5 h$ R, y! K! N8 F7 Z   
  1. static void HSE_SetSysClock(void)
    8 b1 T8 ~! F  `3 Z$ Y* L2 z0 S
  2. {' B$ u; s  ~0 S4 Y
  3.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;6 w9 _. _9 Z" f( ]7 u* O3 ~8 _
  4.   ; z9 n" s! Z* |7 f0 |
  5.   RCC_DeInit();                                                                                        //RCC恢复默认状态  , w5 l8 u& P0 m  _
  6.         RCC_HSEConfig(RCC_HSE_ON);                                //打开HSE时钟  R* G, a! x5 s
  7.         4 U7 j0 x" t- I4 e; g8 |8 H# @
  8.         HSEStatus=RCC_WaitForHSEStartUp();   //等待HSE时钟稳定6 i$ A; k4 {% j& g' o  I. W' }
  9.   j# f. E: \& F# ]8 \" H: l
  10.   if (HSEStatus == SUCCESS)8 i2 C6 x2 c3 v5 X
  11.   {! I" s# l- F( j$ C# h
  12.     /* Enable Prefetch Buffer */4 |9 F% Q2 h1 v* E
  13.                 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);            //使能FLASH预存取缓冲区, M( a% l3 ^( \# @5 P9 P
  14.                 FLASH_SetLatency(FLASH_Latency_2);                                                                                               
    ( ]* b1 i( V. N

  15. 8 N- n$ e/ ~& z# M) z  T; w! J$ g
  16.                 RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                                                        //AHB - HCLK=SYSCLK) u+ V. A' O& S4 d) V
  17.                 RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                                                //APB1 -- PCLK1=HCLK/2- ~3 O# f$ U1 s* j. R% \
  18.                 RCC_PCLK2Config(RCC_HCLK_Div1);                                                                                                                //APB2 -- PCLK2=HCLK1 s) g' L+ _5 \+ h
  19. 3 Y7 O, t6 \0 @1 a. K
  20.                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频0 y/ v3 [( N1 a* r
  21.                 RCC_PLLCmd(ENABLE);                                                                                                                                                                //使能PLL
    * V* Z$ J( t4 F6 l3 G- K
  22.                         . K2 }* O; ~& R9 J) b: Z. V: R
  23.                 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)                                        //等待PLL稳定
    4 P/ ^6 A/ I; T. T3 o8 C) W
  24.                 {
    " M+ |% S2 `  V# k. U
  25.                 }
    ' J0 E2 h: V2 |/ N- K/ U
  26.                 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                                //PLL稳定后,时钟切换到SYSCLK  G% A2 x- S& ^
  27.                
    6 C8 L/ q! f5 x9 k5 n: G3 @
  28.                
    7 {- }- v  Y+ Q8 C5 D' t: C
  29.                 while(RCC_GetSYSCLKSource()!=0x08)                                                                                                //读取时钟切换状态位,确保PLLCLK被选为系统时钟
    + R, w- k- y4 Q* x6 d3 j
  30.                 {
    , S& G" Q$ f# B+ C& x
  31.                 }
      q; ]) e& z7 a; s8 O. C
  32.   }. U$ q+ q# ~. U( c- K
  33.   else
    2 `  [8 v4 c+ `' g) O! _
  34.   {
    & F5 z; u8 O1 i- Q% |2 @- q
  35.   }
    * `& z8 h" I# C7 G3 j
  36. }
复制代码
       3.2.2、MCO引脚初始化1 X. R0 q) H) d$ x
  1. //MCO引脚配置
    ( S+ f9 q* \$ _' E2 I8 B  v  y
  2. void MCO_GPIO_Config(void)
    % R3 h$ i) C7 m; M8 c
  3. {+ D0 L; |2 k4 U2 ]% m. E% r
  4.         GPIO_InitTypeDef  GPIO_InitStructure;
    3 t3 z) F8 @( B; z5 i' r0 C
  5.         ! I8 r- P* g1 c0 E5 P8 C; o" o
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                 //使能PA端口时钟/ ^1 C: I6 j7 O3 U5 x: t9 s( F
  7.        
    3 [5 k+ ]! M3 i' U, w
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;                                                                
    8 K: ~6 X4 ]7 `
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                          " e6 o1 ^8 f" G# a1 ^) y
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz
    2 u& v; Z1 |7 d% y
  11.         GPIO_Init(GPIOA, &GPIO_InitStructure);                                                                
    ) m& I$ a3 Z( U4 A
  12. }
复制代码
       3.2.3、LED引脚初始化
8 J! b) [" z8 i7 j4 X0 m
  1. ' a- _" N: y  N. X: q- h6 f
  2. void LED_GPIO_Config(void)
    / Y' e& Y. \" Q6 ~# G4 g; {" E- H( j( W
  3. {. j) O  p2 B( m) J2 }
  4.         GPIO_InitTypeDef  GPIO_InitStructure;  m8 j& j3 K0 f: q; z  C: y
  5.         9 P; \& ?, U$ b7 Y3 c, o4 b2 [
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                 //使能PA端口时钟: \" E9 m7 j. d6 o
  7.         $ E' N( q. }) r
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                                                
    ) i( t7 B9 L) K7 v  {& x6 a
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                          1 `; _# M5 I( o, T- k
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz  E6 _9 V2 o0 q4 r6 G, E; ~( C  f) ]7 ?
  11.         GPIO_Init(GPIOB, &GPIO_InitStructure);       
    / B6 W: L# {* @: v6 y# E3 {
  12. }
复制代码
       3.2.4、主程序
9 f( U9 `' m8 ~6 a
  1. int main(void)3 b1 t& u. v% ^; M
  2. {
    7 {' F7 ]' d) p" }8 N
  3.         uint32_t i;/ z* R& F+ y# Y8 o0 H5 c* Q& j
  4.         HSE_SetSysClock();
    4 ^/ g1 K$ ^0 W3 L# E
  5.         MCO_GPIO_Config();! x( a: a2 j* f" a8 C
  6.         RCC_MCOConfig(RCC_MCO_SYSCLK);       
    & x- Z& |: t* G- z6 h/ V
  7.         LED_GPIO_Config();       
    3 c. C: n: G# i8 P3 [, d' ]
  8.   while (1)3 w+ H0 d& v2 |  H6 v
  9.   {: m( P: |* J/ y
  10.                
    # |3 V4 H! K1 _  X/ n. j, D9 f
  11.                 for(i=0;i<0xffff;i++);+ E' W( s) W1 g5 k9 t$ f" q
  12.                 GPIO_SetBits(GPIOB,  GPIO_Pin_9);- G$ Q1 A1 w& u) _- o
  13.                 for(i=0;i<0xffff;i++);
    7 m  W7 w+ Y! N
  14.                 GPIO_ResetBits(GPIOB, GPIO_Pin_9);% T6 M) Q& u- I& L. G2 u! M  }
  15.   }
    1 ?/ n9 k# j- K& f5 Q8 f
  16. }
复制代码
1 r6 D2 }" E( k) D) O% E7 A
    四、程序执行结果
. A) E3 E( m& n/ H, u: t' F& y- q" B/ {- I) r) j
) E7 u* @# w, p: ]
    4.1、PLL时钟设置为72MHz,倍频系数设置为9, Q- d/ [" H9 y
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频
8 ?  H/ @; h1 X4 k% h( y/ I        4.1.1、MCO输出时钟频率72M
( L$ g0 y1 }4 f! @0 f        
F0002TEK.png
/ y* x* B8 `- q. n  S        4.1.2、LED引脚输出

; K$ ~3 y8 J( X1 {$ |9 `         F0003TEK.png
" N  S; d7 m9 Y8 \2 o& V1 I4 N. T" u, t! B* D) R  M
   
4.2、PLL时钟设置为56MHz,倍频系数设置为7        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);                        //PLL倍频
! t6 d9 g' F) U' i$ |( Q        4.2.1、MCO输出时钟频率56M
) X4 S" Y# A# v( |9 D* A0 o         F0005TEK.png
9 V) L, g, B! k5 x2 T        4.2.2、LED引脚输出
5 S' S$ O" _- X4 ~        
F0004TEK.png ; i- [4 g7 ]! S9 m4 W" R
        LED输出宽度比72M时钟时,宽度变宽
8 e* x( k0 h1 T' [% b, r3 x
    4.3、PLL时钟设置为88MHz,倍频系数设置为11        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_11);                        //PLL倍频9 g$ }; A  b4 d- t
        4.3.1、MCO输出时钟频率88M
( f9 B/ H6 X2 A) z  _         F0006TEK.png
$ C' N' y5 V8 Y- p; Q- e+ s        4.3.2、LED引脚输出/ S* t8 f- S) ?0 C, _
        
F0007TEK.png
: j  u; P/ p' x! N8 f. N& U        LED输出宽度比72M时钟时,宽度变窄
/ i  I0 d) `0 A% e+ y- g4 Q* l. s
; _3 o5 H/ Y- Y; O
    五、结论
. e4 N5 H' E! {  }8 s

( O. {; L' V( V1 [( y. z1 n$ b3 d

: U* Z+ H  M6 c! A% l         使用外部时钟时,通过改变PLL的倍频系统可以改变SYSCLK时钟频率,来降频或超频工作。HSI配置和HSE差不多,就不在列出。( B% M; ]* e+ [# U  \! o
# V5 x* y. g0 E* c" d* M7 ?9 B
3 Z" i' f5 H7 c7 r$ c- }1 r
; Q& }+ N4 N: q. L- S* c

  Q1 H+ E5 p2 a0 R4 u9 P# O
" x' f& I/ ~4 L+ i1 ~8 y

4 L1 z( J6 `, A9 e: z# {
4 Q; a1 S0 C: L$ f) m
' u& j. c3 q4 S' D3 I+ I6 g: Y

评分

参与人数 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
您的配置里有这样一句2 l/ G) M8 D, Y- i8 f1 w
RCC->CFGR &= (uint32_t)((uint32_t) ~(RCC_CFGR_PLLSRC |RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));& o( H* m% C8 V0 h+ J5 |, f9 q
这句话是把第16-21位清零
hhhhhhhaa 回答时间:2020-4-29 15:06:54
PLLSRC:PLL输入时钟源 (PLL entry clock source)  位16
4 Z2 H) T& T" s" j& w由软件置’1’或清’0’来选择PLL输入时钟源。只能在关闭PLL时才能写入此位。5 v" N3 u# K( {2 e
0:HSI振荡器时钟经2分频后作为PLL输入时钟; V4 q! E8 l* M" U
1:HSE时钟作为PLL输入时钟。
# o; X; c: W- A; i以上是手册里说的
hhhhhhhaa 回答时间:2020-4-29 15:16:47
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE| RCC_CFGR_PLLMULL9);
$ k6 a8 q5 P; P) g4 C4 S5 I这句话是不是把相应的位置1 这样就能配置了

所属标签

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