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

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

[复制链接]
TLLED 发布时间:2018-12-8 14:43
本帖最后由 TLLED 于 2018-12-8 14:42 编辑 1 x! o5 O- }. `# d/ H8 Y; U

$ j! F, U4 ?) b9 h) j9 G    通过第16章节 -- RCC-使用HSE/HSI配置时钟  的学习来重新认识系统总线和外设时钟的配置。
0 d0 u1 ^1 _# C4 M8 [

1 t  G6 O( k) F7 {% S/ O    一、手册中有关时钟配置的内容
& o, H, o4 T, x* P+ a
9 e* ?7 D  J( ]" ~0 A
& W7 I! o- }) a
    1.1、系统时钟框图:
+ @0 e! w" `  r/ R         里面显示出STM32芯片所有时钟和有关配置的寄存器位              1.png
9 J3 X7 m! z8 M0 g. b4 ]5 W% L
1 U. M/ a' @1 t5 n" O3 ~3 g    % |+ g) q$ ]* f; z5 \* W
    二、系统启动有关时钟配置代码
* W9 m  c2 i8 [4 r
/ F$ G4 S8 P3 S0 ?" M' V( U
    2.1、系统启动分析
0 Y; i0 w. V4 f        上篇介绍启动代码分析,会执行Reset Handler服务处理程序。
6 [; {1 K6 t  G! v5 }) G6 ^         100.png 5 A! w3 A' L+ f
         里面有执行SystemInit系统初始化程序% s$ T6 W; P4 J* F. O! h& q- e. }
        
101.png
. w1 e/ g/ U1 W, |" }! K         102.png ; J) @- E& S9 j" u$ u5 m
         103.png
       里面调用SetSysClock函数设置系统时钟
" Y2 J* _1 h5 G$ E+ L* B, b       104.png       + R4 ]/ S  b, Z( s6 E) K
       SetSysClock函数配置为72MHz后调用SetSysClockTo72函数
+ D$ s- ]8 p) m       105.png
9 Y( `1 \: _( Z6 Z       106.png + s/ D3 e2 n6 p0 I
       107.png

- J- d  ^7 b- K$ @5 ?       108.png
4 ]. A, V! X4 O4 |$ d0 F9 \, W        上面是系统上电启动中,系统初始化和系统时钟配置过程,已经把总线时钟配置为72MHz。

4 ?2 [/ g4 [0 X( Z: c. u$ j   
3 ?* Q4 P& w* c9 S7 N    三、时钟配置实例2 @( J& A9 G6 S$ j
( q1 a( }7 J  R3 Q& Q

) J8 y6 w, j$ q! w- ?' u    3.1、配置HSE时钟  
7 w! Z. g! d( \) E& q1 ]; W+ i        了解系统时钟配置流程后,来实践使用时钟配置。) b6 X2 N* b4 J5 ?6 T& a
        在系统时钟框图中,HSE时钟配置+ D8 `% H' S8 t
         109.png
( q4 O8 e# ]+ A4 j3 s8 G4 w! h    >选择外部时钟OSC32_IN和OSC32_OUT两个引脚上接的8MHz无源晶振
% n+ L7 j% ~- T7 u# t" U5 k  ~/ ~* }4 J    >通过PLLXTPRE来选择HSE时钟不分频还是2分频。8 H6 J/ Z! T; m! h" j6 @8 K
    >通过PLLSRC来选择内部时钟HSI和外部时钟HSE时钟选择。
/ r+ t& I2 V( \" M    >通过PLLMUL来选择倍频设置,如系统总线72MHz,晶振频率8M*倍频9=72MHz

; [! z' R  p4 ?0 m3 V    >通过SW来选择时钟源HSI,PLLCLK和HSE时钟源。
( g- b4 T! v& Z/ `/ T9 U* O
7 t" q0 S0 v2 z9 l3 `2 K

5 G8 l% `: Y9 }  u" Q    3.2、程序源码  S+ a" q! ~4 ?6 t* ]. L% C, R
         3.2.1、HSE时钟初始化4 Y' L& m8 N% p" \1 B" Q! y+ x! K
         PLL时钟倍频到72MHz  b: m; D" r6 Y9 `; y/ J& N; m
   
  1. static void HSE_SetSysClock(void)/ V: h( d1 f% ^6 h& C3 r
  2. {8 A. f& }! R+ D% |) i
  3.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    & m4 S: {1 ~- x5 k7 |
  4.   
    , n, w' @) e7 K7 {& d* Q! D0 D1 D
  5.   RCC_DeInit();                                                                                        //RCC恢复默认状态  
    - B% L, G# s, K5 z
  6.         RCC_HSEConfig(RCC_HSE_ON);                                //打开HSE时钟) U( {9 v8 x" o) z) l; W& L! F; n
  7.        
    ' ]" U( A$ o) N/ k- b! ~7 c
  8.         HSEStatus=RCC_WaitForHSEStartUp();   //等待HSE时钟稳定
    + i! J) |2 ?) a8 r

  9. . ]6 k+ o& H9 p: B8 w& J
  10.   if (HSEStatus == SUCCESS)# \; f" ^' O$ }1 v# ]; w, b1 R
  11.   {
    3 J0 _# _5 Y8 j: Z4 n
  12.     /* Enable Prefetch Buffer */
    - F" \; z5 I: E8 G
  13.                 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);            //使能FLASH预存取缓冲区
    & @/ \, }! U1 O8 z- Q: g2 }
  14.                 FLASH_SetLatency(FLASH_Latency_2);                                                                                               
    & ~. Q' k5 N7 b

  15.   }2 ?! v) t! W: v5 ?; V/ m: T
  16.                 RCC_HCLKConfig(RCC_SYSCLK_Div1);                                                                                                        //AHB - HCLK=SYSCLK
    & i% k. n* C" a, d1 s
  17.                 RCC_PCLK1Config(RCC_HCLK_Div2);                                                                                                                //APB1 -- PCLK1=HCLK/2
    % x4 m* C3 R% C
  18.                 RCC_PCLK2Config(RCC_HCLK_Div1);                                                                                                                //APB2 -- PCLK2=HCLK) I$ j4 ~+ z, G; i/ J8 P+ m

  19. $ Y/ `; g" f- w: m
  20.                 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频
    0 u! R& A+ N! m& F, K5 z& o4 J- s
  21.                 RCC_PLLCmd(ENABLE);                                                                                                                                                                //使能PLL% O3 v6 v, n( C
  22.                         & O5 `' v4 ^, {0 u5 |- w; V* h
  23.                 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)                                        //等待PLL稳定% ^4 ?. U% [3 q
  24.                 {2 b1 X5 h6 _0 \# Y
  25.                 }
    7 u: B1 e" u3 T' H! _$ a& H* @& a
  26.                 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                                                                //PLL稳定后,时钟切换到SYSCLK" @# \) W/ {: R$ G; p2 s  M
  27.                 + u" w; }# ^" P! Y) S/ b1 a
  28.                
    $ @- |# R) _( |, k! y) @% C! M0 F
  29.                 while(RCC_GetSYSCLKSource()!=0x08)                                                                                                //读取时钟切换状态位,确保PLLCLK被选为系统时钟
    : V- D# [% n* M3 X' R4 O
  30.                 {+ q6 s4 K* |9 I8 p% f2 S7 z
  31.                 }
    5 S. U/ }; F3 Q& Z( N5 k$ h( A. S
  32.   }
    ) L, t1 `6 @, u/ T+ B+ |% g9 T
  33.   else
    " d5 C5 X8 c6 B9 `" V/ Q- c
  34.   {# _  o+ I  l- \2 n$ X3 |9 \$ P
  35.   }
    1 Z0 {3 R) a- G  k: u, t7 B
  36. }
复制代码
       3.2.2、MCO引脚初始化6 [: l' |- x4 n
  1. //MCO引脚配置
    ; k; ]: l. f; I1 _8 c; s' ]
  2. void MCO_GPIO_Config(void)
    9 x, j" f1 o! C; A+ Z6 X3 g
  3. {
    0 _9 \0 R0 L) H7 Z4 q
  4.         GPIO_InitTypeDef  GPIO_InitStructure;
    : c* j$ J5 }" i  c5 M. U- o+ t
  5.        
    # a0 T3 F% s1 e' K* `1 f6 r
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                 //使能PA端口时钟( }. V# J( {* s
  7.         , y4 C/ x% O/ U/ S2 H% q6 ~! ?; J
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;                                                                
    5 g4 B5 b* x, ~; b; ?3 f/ N
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                          + V" t; n. l3 D, {4 O" \
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz4 c/ U- n. c- O- W" h
  11.         GPIO_Init(GPIOA, &GPIO_InitStructure);                                                                 - |% c* d( z0 c# @
  12. }
复制代码
       3.2.3、LED引脚初始化6 T3 m$ ?, }% C4 m2 x
  1.   g) ~: P$ n6 X+ B- ~
  2. void LED_GPIO_Config(void)
    ( }0 A- d& f5 `/ d
  3. {0 P5 |8 f* k$ i& ~
  4.         GPIO_InitTypeDef  GPIO_InitStructure;( x, W* s, ?' l% k& i5 g
  5.        
    - h) i0 b1 B$ O& t
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);                 //使能PA端口时钟& g( U4 ]5 d5 c: S/ X' P+ H
  7.        
    % [, K% x% }- h0 Q" E: L  x
  8.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                                                
      Y2 X& F  r+ x% y+ K
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                          / {1 L3 X: C4 R* q7 V
  10.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                 //IO口速度为50MHz
    ( J4 [  M6 v) d4 ^7 U: D
  11.         GPIO_Init(GPIOB, &GPIO_InitStructure);        9 g) e$ \+ `4 d
  12. }
复制代码
       3.2.4、主程序/ |1 P" `5 t+ m9 S! z" J' I
  1. int main(void)
    , E2 r4 o: z. k
  2. {; u9 G1 F+ Y. \) O5 K0 Y9 o
  3.         uint32_t i;
    8 p. |9 R* u+ e, T. V4 Q5 N. W
  4.         HSE_SetSysClock();& J' P. @1 j6 q7 \! q, n; `# L2 C/ P
  5.         MCO_GPIO_Config();3 b) I4 {8 `$ Y: S2 C9 S" C
  6.         RCC_MCOConfig(RCC_MCO_SYSCLK);        ! H) g  H1 y5 f3 V; b9 `
  7.         LED_GPIO_Config();       
    3 B( A( m8 L! L" J
  8.   while (1)
    3 R, i6 z& V5 g0 _; c) C
  9.   {: Q$ c, m5 k# d3 ?) g! d/ I
  10.                 9 O5 S2 u: ]5 k' D, d2 _; T
  11.                 for(i=0;i<0xffff;i++);
    ) K) j5 Z1 F$ G2 S2 H, B
  12.                 GPIO_SetBits(GPIOB,  GPIO_Pin_9);. s1 L- S; J7 S$ z
  13.                 for(i=0;i<0xffff;i++);
    ' e( m8 f9 h# b( B$ z1 |2 B
  14.                 GPIO_ResetBits(GPIOB, GPIO_Pin_9);: W$ X0 R/ W: t+ W: w% B5 c
  15.   }
    , M0 T* p# A  |7 Y$ s
  16. }
复制代码

" {+ s( i$ x$ x) O    四、程序执行结果
4 m$ h4 s) G- x, z( k3 e- v& v9 @1 {  Q6 y

& ~. D# z- N0 _* h    4.1、PLL时钟设置为72MHz,倍频系数设置为9
/ K8 M. C1 [* N% \) a6 A& C        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);                        //PLL倍频0 x; G9 N" ?- H/ q  g; h
        4.1.1、MCO输出时钟频率72M, c3 c" ^9 u7 o. @$ b
        
F0002TEK.png
9 t8 L: h6 o, F5 Y- T" \0 t9 O        4.1.2、LED引脚输出

, r2 B- u$ l" e+ l% D% t( P  v         F0003TEK.png
# q4 O- p0 W6 j4 R% O- [
4 W! ?0 ?! L/ z2 W3 V# Q   
4.2、PLL时钟设置为56MHz,倍频系数设置为7        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);                        //PLL倍频, T3 K9 q% [8 V1 B1 U3 N2 ?& I- j
        4.2.1、MCO输出时钟频率56M7 ]4 H9 Y$ n- Z/ n) I# ^
         F0005TEK.png 2 A8 P! L  V2 Q- d
        4.2.2、LED引脚输出
0 H; }- a( H: ]2 J2 p        
F0004TEK.png 3 g. z5 y: d% W3 h3 X+ @! G
        LED输出宽度比72M时钟时,宽度变宽
* v" d" n' \6 S" @- N
    4.3、PLL时钟设置为88MHz,倍频系数设置为11        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_11);                        //PLL倍频
" [# f! }3 G; [; j. j- G3 i' f, p        4.3.1、MCO输出时钟频率88M
) w/ W- _( F+ L% _- G         F0006TEK.png
0 _. n* A$ I8 h$ t. A/ v& I' F        4.3.2、LED引脚输出
/ ~0 ^( n* v9 v9 P; k        
F0007TEK.png
. p" Z  {8 W( N1 K7 u        LED输出宽度比72M时钟时,宽度变窄
5 G1 m* j4 m% A: M2 Y  ?
& K  d) O6 K2 W9 M+ x1 @
    五、结论
: R1 b: m. P$ d* T/ V' V3 e6 M
% ~. O+ Y: G. h# r: N: `, L, |

0 }& o0 y2 N4 [  u: z         使用外部时钟时,通过改变PLL的倍频系统可以改变SYSCLK时钟频率,来降频或超频工作。HSI配置和HSE差不多,就不在列出。, r8 ^! M, _( y; K

8 d3 {5 j) J2 I9 J, w9 J  {9 H% R' |
; b7 Y- \; `7 Y" h; w+ T
  Z4 h( V1 R; l' \/ N* g9 {6 _

; |1 D) V, p, Q& o) b! B) v) E$ t; U8 J

# c  M9 B& a0 s0 M! w$ `
  ?2 ?4 K6 J8 w3 G" A

评分

参与人数 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
您的配置里有这样一句+ P; M9 t0 ~% I" }1 R: j4 i
RCC->CFGR &= (uint32_t)((uint32_t) ~(RCC_CFGR_PLLSRC |RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));4 Q& m0 U0 e4 k8 j
这句话是把第16-21位清零
hhhhhhhaa 回答时间:2020-4-29 15:06:54
PLLSRC:PLL输入时钟源 (PLL entry clock source)  位16
" e5 i: _& T1 H  w3 J; l3 f由软件置’1’或清’0’来选择PLL输入时钟源。只能在关闭PLL时才能写入此位。) E% `8 Z5 L1 f9 y. P9 l
0:HSI振荡器时钟经2分频后作为PLL输入时钟8 c9 K* k3 X8 b6 Z. l2 e
1:HSE时钟作为PLL输入时钟。
" ^% p: ^0 }" }/ c/ t以上是手册里说的
hhhhhhhaa 回答时间:2020-4-29 15:16:47
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE| RCC_CFGR_PLLMULL9);
1 I" y( g/ p, H这句话是不是把相应的位置1 这样就能配置了

所属标签

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