
上次实验,我们学习了 STM32 内部系统滴答定时器,该滴答定时器产生的延时非常精确。在本次实验中,我们将自定义 RCC 系统时钟,通过改变其倍频与分频实现延时时间变化,实现 LED 灯闪烁效果。通过本次实验,你将了解 RCC 系统时钟的使用。本次实验的目标: 1、了解 STM32 的系统构架。$ _' T2 E( q/ A# D! `2 z 2、了解 STM32 的时钟构架。 3、了解 RCC 时钟的配置步骤。% {5 x! s; y' ? \( _6 Z c! A 8 @" c( W+ }" S: e STM32 的系统构架 STM32 的时钟比较复杂,它可以选择多种时钟源,也可以选择不一样的时钟频率,而且在系统总线上面,每条系统的时钟选择都是有差异的。所以想要清楚的了解 STM32 的时钟分配,我们先来了解一下 STM32 的系统构架是什么样的。 : u2 B8 E) \+ o& t- @ 从图中我们知道,RCC 时钟输出时钟出来,然后经过 AHB 系统总线,分别分配给其他外设时钟,而不一样的外设,是先挂在不一样的桥上的。比如: ADC1、ADC2、 SPI1、GPIO 等都是挂在 APB2 上面,而有些是挂在 APB1 上面,所以,虽然它们都是从 RCC 获取的时钟,但是它们的频率有时候是不一样的。 + ?! c# ~9 }. c! X: U% x% a ![]() # n0 f9 H" F2 ^$ h STM32 的时钟树 STM32 单片机上电之后,系统默认是用的时钟是单片机内部的高速晶振时钟,而这个晶振容易受到温度的影响,所以晶振跳动的时候不是有一定的影响,所以一般开发使用的时候都是使用外部晶振,而且单片机刚启动的时候,它的时钟频率是 8MHZ,而 STM32 时钟的最高频率是 72MHZ,所以单片机一般开机之后运行的程序是切换时钟来源,并设置时钟频率。其实在使用库函数的时候,其实在库函数启动文件里面,是帮助我们把时钟频率设置到 72MHZ 了。7 V5 J, i1 p0 i! G% W2 Z9 t; T* S) q 库函数调用系统时钟该成72M9 M6 y3 b7 A; o' _6 U8 L #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (definedSTM32F10X_HD_VL)7 d) _$ k& v. _1 v0 }/ y /* #define SYSCLK_FREQ_HSE HSE_VALUE *// m0 ~; M3 u, f2 v #define SYSCLK_FREQ_24MHz 24000000 #else #define SYSCLK_FREQ_72MHz 720000009 }" c) Y% r. i/ t" f 然后在下面的程序中,根据这个 SYSCLK_FREQ_72MHz 定义,它默认设置成72MHZ 5 m, g3 e5 [% ]4 R( H1 Y 接下来我们来看一下 RCC 时钟树9 k( s! _& d v7 `* G6 L ![]() # l0 w8 h' a& }. h( P% n 从时钟树图我们可以看出,STM32 的时钟一共有可以有 4 个晶振源:( v$ J& R4 n" S% Z8 B. k1 ~5 T 1) 内部自带的高速时钟:HIS。单片机启动之后默认使用的时钟来源。 2) 外部高速时钟:HSE。大多数时钟时钟的是 8MHZ 的晶振。/ y) W* i% b4 F 3) 外部低速时钟:LSE。主要用来给单片机内部的 RTC 提供时钟。1 x# ~) R, S% b0 e7 X, [' n 4) 内部的低速时钟:LSI。主要用来给单片机内部的 RTC 和看门狗提供时钟。4 Q, b# R8 {" x- k7 e& S: G4 M 而 STM32 的系统时钟源,有 3 个时钟来源: 1) 直接来自内部的高速时钟 HIS。 2) 直接来自外部的高速时钟 HSE。 3) 将 HIS 或者 HSE 进行处理,倍频之后的 PLL 时钟。 ) \! p9 t5 B: X3 Q/ J' T STM32 配置 RCC 时钟的过程 1) 复位 RCC 时钟。: i' r/ j% r2 q2 u 2) 打开 HSE 外部高速时钟。: _( ?! S6 e& D' M8 f7 i6 k& e 3) 检测 HSE 外部高速时钟是否开启成功。 4) 设置 FLASH 的读写。 ) a% ^; ^6 Y9 D# Q: p 5) 设置 AHB 总线的分频,还有 APB1 和 APB2 的分频。注意,AHB 和 APB2 最 大频率是 72MHZ,APB1 的最大频率是才 36MHZ。 6) 设置 HSE 外部高速时钟作为 PLL 时钟的时钟输入 7) 设置 PLL 时钟的倍频的倍数。; H; T" u3 B- j& k4 c3 l( d 8) 打开 PLL 时钟的使能。 9) 等待 PLL 时钟开启成功。 10) 将系统时钟源设置为 PLL 时钟。 11) 等待时钟源切换成功 。 RCC相关库函数介绍1 J- j4 A% z6 p3 u 1.RCC_DeInit() 复位函数是将 RCC 时钟复位为内部高速时钟作为输入,让我们能够进行时钟设置操作。2.RCC_HSEConfig() 函数 设置 HSE 外部高速时钟的函数,可以开启、关闭、和旁路 3.RCC_WaitForHSEStartUp() 函数( E7 v, J' B0 ]5 y 4 .RCC_HCLKConfig() 函数 5 .RCC_PCLK2Config() 6 .RCC_PCLK1Config() 函数4 K' q$ K! Y* f$ Y- z4 Z 8 、RCC_PLLCmd() 函数 9 、RCC_GetFlagStatus() 函数 这个函数可以用来获取各种状态标志,以检测设置是否成功。 10 、 RCC_SYSCLKConfig() 函数 11 、 RCC_GetSYSCLKSource() & r) Q/ o) l8 N8 n RCC 时钟设置函数0 n: W* Y# U/ K5 n2 H. t0 ] ^1 } void RCC_HSE_Configuration() //自定义系统时间(可以修改时钟) { RCC_DeInit(); //将外设 RCC 寄存器重设为缺省值 RCC_HSEConfig(RCC_HSE_ON);//设置外部高速晶振(HSE) if(RCC_WaitForHSEStartUp()==SUCCESS) //等待 HSE 起振% R4 ]$ ]6 \5 d' Q% T {: w* C+ I) s9 ?; d$ `' j RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置 AHB 时钟(HCLK) RCC_PCLK1Config(RCC_HCLK_Div2);//设置低速 AHB 时钟(PCLK1) RCC_PCLK2Config(RCC_HCLK_Div1);//设置高速 AHB 时钟(PCLK2) RCC_PLLConfig(RCC_PLLSource_HSE_Div2,RCC_PLLMul_9);//设置 PLL 时钟源及倍频系 数4 `& [- x# u( a# [! B( I3 i v4 z0 ~; G! R! l RCC_PLLCmd(ENABLE); //使能或者失能 PLL: E+ r; F) l' i; \, | while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);//检查指定的 RCC 标志位设置 与否,PLL 就绪; H! M, @9 ]: Q6 B RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK) while(RCC_GetSYSCLKSource()!=0x08);//返回用作系统时钟的时钟源,0x08:PLL 作为3 n, c4 W( S: S9 \# m* q 系统时钟1 f; c6 F9 Y/ ^6 R } }4 v, A2 U% x, Z+ O3 [* D4 Z 这个函数的作用是:设置单片机的时钟来源为 HSE 外部高速时钟,并根据输入频率参数设置相应的频率。 要注意的是设置的输入频率参数一定要是 8 的倍数,并且是从 4 倍到 9 倍的频率数值。3 c' K+ J \" m) E& {$ d' V int main()$ v9 e/ D) k6 K) j2 a { led_Init(); //LED 端口初始化 RCC_HSE_Configuration();// 自定义系统时间,可修改分频0 o/ |2 \: t' Q8 l, o' Y( }# p while(1) { GPIO_SetBits(GPIOB,LED); delay_ms(500);//精确延时为 0.5s GPIO_ResetBits(GPIOB,LED);, D% j9 W3 e# Q/ A! p0 b delay_ms(500);//精确延时为 0.5s0 m/ C! M& z7 i } } 这次的系统实验就到这里了。. j0 \8 \/ w% H0 m l% W7 w, m |
消灭0回复![]() |