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

STM32----系统时钟实验

[复制链接]
feixiang20 发布时间:2018-1-15 20:47
上次实验,我们学习了 STM32 内部系统滴答定时器,该滴答定时器产生的延时非常精确。在本次实验中,我们将自定义 RCC 系统时钟,通过改变其倍频与分频实现延时时间变化,实现 LED 灯闪烁效果。通过本次实验,你将了解 RCC 系统时钟的使用。本次实验的目标:% m7 _  V& Z( D3 p
1、了解 STM32 的系统构架。
& o/ z% A- J4 G# b) _0 y+ v1 b. i2、了解 STM32 的时钟构架。
# L4 x7 |% i: ]+ D* L& i4 h3、了解 RCC 时钟的配置步骤。
  [+ b- U% l8 o) r0 z* t+ E1 y9 x6 Y$ g1 f
STM32  的系统构架0 T- W7 w& ~# r) A; t
STM32 的时钟比较复杂,它可以选择多种时钟源,也可以选择不一样的时钟频率,而且在系统总线上面,每条系统的时钟选择都是有差异的。所以想要清楚的了解 STM32 的时钟分配,我们先来了解一下 STM32 的系统构架是什么样的。
/ e5 ^+ x  z6 l! Z: S
5 e; l) U/ T  a4 d4 t从图中我们知道,RCC 时钟输出时钟出来,然后经过 AHB 系统总线,分别分配给其他外设时钟,而不一样的外设,是先挂在不一样的桥上的。比如: ADC1、ADC2、 SPI1、GPIO 等都是挂在 APB2 上面,而有些是挂在 APB1 上面,所以,虽然它们都是从 RCC 获取的时钟,但是它们的频率有时候是不一样的。
; w( i& f( s' j" M) B1 N
4 k, d; J4 H8 g7 c  M' c) U 1.jpg
' d4 t2 O9 ~+ m7 \& o3 ]. X4 v2 k8 p* b/ l  l' P
STM32  的时钟树
1 ~/ s& W) n) O% \# \STM32 单片机上电之后,系统默认是用的时钟是单片机内部的高速晶振时钟,而这个晶振容易受到温度的影响,所以晶振跳动的时候不是有一定的影响,所以一般开发使用的时候都是使用外部晶振,而且单片机刚启动的时候,它的时钟频率是 8MHZ,而 STM32 时钟的最高频率是 72MHZ,所以单片机一般开机之后运行的程序是切换时钟来源,并设置时钟频率。其实在使用库函数的时候,其实在库函数启动文件里面,是帮助我们把时钟频率设置到 72MHZ 了。
1 J1 f9 j; Z% @4 {7 G, r" ]' v: u7 D6 f0 _& F- P4 @+ B# ]+ l. [
库函数调用系统时钟该成72M
) p3 r7 \8 T0 l& L: l4 S$ m#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (definedSTM32F10X_HD_VL)
8 o  p7 D1 v! _4 @! e7 i+ V7 Z; `/* #define SYSCLK_FREQ_HSE HSE_VALUE */
4 l8 j% L5 g. ^) C. n; F#define SYSCLK_FREQ_24MHz 24000000
1 b+ F2 ~" p0 I% V7 K#else! w# {- H" O( \+ N. g" C
#define SYSCLK_FREQ_72MHz 72000000
6 s% ]: L7 `; j然后在下面的程序中,根据这个 SYSCLK_FREQ_72MHz 定义,它默认设置成72MHZ
* S0 p0 v6 C& B2 s3 f
/ {( B8 ^+ y# `9 U接下来我们来看一下 RCC 时钟树
$ P! B% {/ f1 I$ D% ]( ^
; S5 |& S9 D6 J' J* A& Y2 B 2.jpg
" G& M' A. F$ v3 `) S3 ^" a7 `; W  X$ q+ Y" S& W  c* z5 ~
从时钟树图我们可以看出,STM32 的时钟一共有可以有 4 个晶振源:
* G+ J' u1 X: t1 z) Z0 {1) 内部自带的高速时钟:HIS。单片机启动之后默认使用的时钟来源。. Z, q& i8 x3 C3 A( J6 y, h2 r
2) 外部高速时钟:HSE。大多数时钟时钟的是 8MHZ 的晶振。
% f' g1 r2 r! O; h% G7 e" N: N3) 外部低速时钟:LSE。主要用来给单片机内部的 RTC 提供时钟。, c# ?- g! z9 x3 z% U. W7 J
4) 内部的低速时钟:LSI。主要用来给单片机内部的 RTC 和看门狗提供时钟。2 e+ ?( m8 N/ B
而 STM32 的系统时钟源,有 3 个时钟来源:! ?: @  D) Z5 G- h7 M
1) 直接来自内部的高速时钟 HIS。
% s! P4 T' p: z& s4 D- [# X# ~2) 直接来自外部的高速时钟 HSE。# n- d7 z( H+ i/ ~' d
3) 将 HIS 或者 HSE 进行处理,倍频之后的 PLL 时钟。
$ A" L& {8 ?# i4 h' c" \0 c% J) |7 O
STM32  配置 RCC  时钟的过程8 b& j5 d; n. ?& h' V$ V- r7 s
1) 复位 RCC 时钟。
, R! t5 I7 U2 G9 T2) 打开 HSE 外部高速时钟。3 l1 b: o2 C7 n- O. w
3) 检测 HSE 外部高速时钟是否开启成功。+ i' q6 O9 b, {2 `: ~% m( A- E
4) 设置 FLASH 的读写。
9 r, p( B7 Q% M$ u/ w5) 设置 AHB 总线的分频,还有 APB1 和 APB2 的分频。注意,AHB 和 APB2 最
5 A6 v9 ]  u% n$ w7 {6 P大频率是 72MHZ,APB1 的最大频率是才 36MHZ。
7 L% G3 j0 F- V5 A4 u  _6) 设置 HSE 外部高速时钟作为 PLL 时钟的时钟输入
* W, i. `" q9 O* [7) 设置 PLL 时钟的倍频的倍数。
: b. ]+ l# u3 E) R2 Y. e. F8 W& j) {4 _8) 打开 PLL 时钟的使能。
  R4 R! ]1 O, s: k% p$ f9) 等待 PLL 时钟开启成功。7 ?& ?4 S; I2 I  v8 n" U
10) 将系统时钟源设置为 PLL 时钟。
' T+ q1 z: @" }( j8 e% f11) 等待时钟源切换成功 。6 H+ E* a" I- l, K; @5 {) o
! T! y. h% @9 R5 `
RCC相关库函数介绍
5 e5 E8 U! F: h! S1.RCC_DeInit() 复位函数是将 RCC 时钟复位为内部高速时钟作为输入,让我们能够进行时钟设置操作。2.RCC_HSEConfig() 函数  设置 HSE 外部高速时钟的函数,可以开启、关闭、和旁路
$ ]2 h7 M+ U0 I8 E. A3 I( l- B3.RCC_WaitForHSEStartUp() 函数$ Y8 P! ~# H0 S. i3 R5 F  W5 q
4 .RCC_HCLKConfig() 函数- H1 A6 _6 ^4 [; o4 M: C
5 .RCC_PCLK2Config()/ h& W0 A/ ?6 ]) t- M
6 .RCC_PCLK1Config() 函数
; Q8 W# A4 z. r. |# F8 、RCC_PLLCmd() 函数
" U5 L1 ]$ n2 `% c0 k1 G9 、RCC_GetFlagStatus() 函数  这个函数可以用来获取各种状态标志,以检测设置是否成功。
6 G, k9 j, K3 Q! @* S1 O* n10 、 RCC_SYSCLKConfig() 函数
% ^& c6 R( K9 o6 Z+ Z11 、 RCC_GetSYSCLKSource()
! ?! b/ o( I4 `% I' d. Z0 i5 O- s+ f8 D+ x, y
RCC  时钟设置函数8 n( b- x0 |: X3 g
void RCC_HSE_Configuration() //自定义系统时间(可以修改时钟)
/ z/ ^' g5 G; D* f0 K) i' N0 m{* e9 p; Q- l% X# _# D2 F
RCC_DeInit(); //将外设 RCC 寄存器重设为缺省值5 z" |0 k5 U. w4 v, ?# R
RCC_HSEConfig(RCC_HSE_ON);//设置外部高速晶振(HSE)% p3 o6 ^  @0 c9 U  e7 Y! E/ c
if(RCC_WaitForHSEStartUp()==SUCCESS) //等待 HSE 起振9 s! [( |* W6 B8 `# I
{6 @$ R+ \: U6 T" L$ M/ y# K& s
RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置 AHB 时钟(HCLK)
, z4 O/ ^9 C5 v4 u( d; N3 ]2 _RCC_PCLK1Config(RCC_HCLK_Div2);//设置低速 AHB 时钟(PCLK1); r+ E  I+ Z% m6 S2 w" N
RCC_PCLK2Config(RCC_HCLK_Div1);//设置高速 AHB 时钟(PCLK2)
1 }7 v" Z6 K: c! y% V6 t  g4 \RCC_PLLConfig(RCC_PLLSource_HSE_Div2,RCC_PLLMul_9);//设置 PLL 时钟源及倍频系' j9 [+ @2 T" N2 T0 o1 R
数, _( ?1 x" B" s4 _8 |/ H
RCC_PLLCmd(ENABLE); //使能或者失能 PLL% V. u* @+ ^1 c/ y
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);//检查指定的 RCC 标志位设置: m6 u) ~9 _3 [' }7 `( q+ s) |
与否,PLL 就绪
5 f1 h0 |) {7 S' z+ zRCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK)# h3 X5 f8 s: v5 j
while(RCC_GetSYSCLKSource()!=0x08);//返回用作系统时钟的时钟源,0x08:PLL 作为
! q  |# L* C0 S9 W# @. t& f/ F系统时钟) ]: r1 D- X/ C+ }: L4 S
}
! A! `4 K" g% V6 `% Y6 U: M}
+ V- O2 e1 P# S$ F( f" T; {
' G, ~, w$ }! C) f* ~) ?* ~4 x这个函数的作用是:设置单片机的时钟来源为 HSE 外部高速时钟,并根据输入频率参数设置相应的频率。 要注意的是设置的输入频率参数一定要是 8 的倍数,并且是从 4 倍到 9 倍的频率数值。* ?7 _8 x: T' b$ ?4 f

/ J3 J0 i' t- c! hint main()
- j* o4 r6 U- j$ a0 _{
* L5 Y1 ^; _" \" G8 yled_Init();  //LED 端口初始化0 |* Q6 q5 O" a  ?4 _
RCC_HSE_Configuration();// 自定义系统时间,可修改分频
( b$ f9 j( h7 X7 {$ D) |while(1)
& d& T' A2 F7 s. N* Z' E& ~{ 9 s" O3 ~( q# e4 x5 M/ x# F# `
GPIO_SetBits(GPIOB,LED);% ]. d' h& E% D+ h1 l
delay_ms(500);//精确延时为 0.5s  A6 c0 ^' W0 n, Z7 f
GPIO_ResetBits(GPIOB,LED);% h# Q) v$ l  Z$ t: F/ W- ^* b
delay_ms(500);//精确延时为 0.5s" [( E) a. [( A0 y# Z0 A0 f
}
  B5 m( m0 x+ |' X" C8 C}  M/ ~0 B: R4 o$ O$ {" @
这次的系统实验就到这里了。
! r! u) r$ M1 n' B, b2 ]; ^) P/ v
赞 收藏 评论1 发布时间:2018-1-15 20:47

举报

1个回答
anywill 回答时间:2018-1-15 21:45:16
消灭0回复
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版