
上次实验,我们学习了 STM32 内部系统滴答定时器,该滴答定时器产生的延时非常精确。在本次实验中,我们将自定义 RCC 系统时钟,通过改变其倍频与分频实现延时时间变化,实现 LED 灯闪烁效果。通过本次实验,你将了解 RCC 系统时钟的使用。本次实验的目标: 1、了解 STM32 的系统构架。" n3 W5 y5 u' }* p9 t$ z& h 2、了解 STM32 的时钟构架。0 t& T0 M3 O. ^) S% Q( h+ P% [ 3、了解 RCC 时钟的配置步骤。 ' N" [5 m2 l1 R# ]1 K STM32 的系统构架! f! ]+ T; c& D1 A9 M, J+ s STM32 的时钟比较复杂,它可以选择多种时钟源,也可以选择不一样的时钟频率,而且在系统总线上面,每条系统的时钟选择都是有差异的。所以想要清楚的了解 STM32 的时钟分配,我们先来了解一下 STM32 的系统构架是什么样的。 , v2 A: K0 C; w9 n& |6 I3 L 从图中我们知道,RCC 时钟输出时钟出来,然后经过 AHB 系统总线,分别分配给其他外设时钟,而不一样的外设,是先挂在不一样的桥上的。比如: ADC1、ADC2、 SPI1、GPIO 等都是挂在 APB2 上面,而有些是挂在 APB1 上面,所以,虽然它们都是从 RCC 获取的时钟,但是它们的频率有时候是不一样的。+ a* Z/ p; q; Y; A ) C) f9 x0 y- a" U+ d ![]() & A8 t7 g+ f4 R" { STM32 的时钟树 STM32 单片机上电之后,系统默认是用的时钟是单片机内部的高速晶振时钟,而这个晶振容易受到温度的影响,所以晶振跳动的时候不是有一定的影响,所以一般开发使用的时候都是使用外部晶振,而且单片机刚启动的时候,它的时钟频率是 8MHZ,而 STM32 时钟的最高频率是 72MHZ,所以单片机一般开机之后运行的程序是切换时钟来源,并设置时钟频率。其实在使用库函数的时候,其实在库函数启动文件里面,是帮助我们把时钟频率设置到 72MHZ 了。 库函数调用系统时钟该成72M' G- Q- F" T* p+ G8 @ #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (definedSTM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE_VALUE */ #define SYSCLK_FREQ_24MHz 24000000 #else #define SYSCLK_FREQ_72MHz 72000000 然后在下面的程序中,根据这个 SYSCLK_FREQ_72MHz 定义,它默认设置成72MHZ 接下来我们来看一下 RCC 时钟树 ![]() $ s. G# ?# F: L d 从时钟树图我们可以看出,STM32 的时钟一共有可以有 4 个晶振源: 1) 内部自带的高速时钟:HIS。单片机启动之后默认使用的时钟来源。- o' R7 T+ y2 R 2) 外部高速时钟:HSE。大多数时钟时钟的是 8MHZ 的晶振。 3) 外部低速时钟:LSE。主要用来给单片机内部的 RTC 提供时钟。 4) 内部的低速时钟:LSI。主要用来给单片机内部的 RTC 和看门狗提供时钟。 而 STM32 的系统时钟源,有 3 个时钟来源: 1) 直接来自内部的高速时钟 HIS。+ q- n1 Y* u( h0 C: G 2) 直接来自外部的高速时钟 HSE。 3) 将 HIS 或者 HSE 进行处理,倍频之后的 PLL 时钟。: r+ N6 Y2 Q" i( ], d( Z9 n 6 E: H3 B& w% E6 g) l STM32 配置 RCC 时钟的过程 1) 复位 RCC 时钟。4 p/ l6 V- E7 O7 d 2) 打开 HSE 外部高速时钟。 3) 检测 HSE 外部高速时钟是否开启成功。 4) 设置 FLASH 的读写。 9 [$ M5 I* R; f' g8 a7 C( b7 G 5) 设置 AHB 总线的分频,还有 APB1 和 APB2 的分频。注意,AHB 和 APB2 最 大频率是 72MHZ,APB1 的最大频率是才 36MHZ。4 A0 D* v$ u2 b5 Z/ V% |" G 6) 设置 HSE 外部高速时钟作为 PLL 时钟的时钟输入 " C- u6 q8 \2 i; W" J G* N 7) 设置 PLL 时钟的倍频的倍数。+ y4 ]! i* h3 t1 j4 e, h/ q 8) 打开 PLL 时钟的使能。 9) 等待 PLL 时钟开启成功。+ y8 G( @# I8 [7 Q. S9 ] 10) 将系统时钟源设置为 PLL 时钟。6 N4 e2 [) {" V0 C7 p4 s 11) 等待时钟源切换成功 。7 X a! @! B& W$ _$ f! I" P * F1 m% i+ D e RCC相关库函数介绍: Y9 z: @! t! B1 t% n 1.RCC_DeInit() 复位函数是将 RCC 时钟复位为内部高速时钟作为输入,让我们能够进行时钟设置操作。2.RCC_HSEConfig() 函数 设置 HSE 外部高速时钟的函数,可以开启、关闭、和旁路 3.RCC_WaitForHSEStartUp() 函数" i: j! \# d3 V% Y* W0 S' b 4 .RCC_HCLKConfig() 函数; W9 j: f6 |/ S# a 5 .RCC_PCLK2Config()8 Q" F5 S: P% r7 Q3 \( u/ y- i% G 6 .RCC_PCLK1Config() 函数9 C3 a! T2 N* h/ W 8 、RCC_PLLCmd() 函数. q+ P" k& L6 b) `$ \$ ? 9 、RCC_GetFlagStatus() 函数 这个函数可以用来获取各种状态标志,以检测设置是否成功。- b' A5 q* \2 Q7 z7 K 10 、 RCC_SYSCLKConfig() 函数 11 、 RCC_GetSYSCLKSource() RCC 时钟设置函数/ N4 X8 J' Z/ M+ t void RCC_HSE_Configuration() //自定义系统时间(可以修改时钟) {) Z2 N1 O4 J7 Y0 e1 O RCC_DeInit(); //将外设 RCC 寄存器重设为缺省值( z; s: w' ]2 Y5 Y X! T, p6 P RCC_HSEConfig(RCC_HSE_ON);//设置外部高速晶振(HSE)6 i8 f+ m+ g5 W if(RCC_WaitForHSEStartUp()==SUCCESS) //等待 HSE 起振" F9 b1 d) ~3 U( D+ i5 [& l8 ^( d { RCC_HCLKConfig(RCC_SYSCLK_Div1);//设置 AHB 时钟(HCLK) RCC_PCLK1Config(RCC_HCLK_Div2);//设置低速 AHB 时钟(PCLK1)1 b& N' J" E, I0 {! s$ `) f& f& t# U RCC_PCLK2Config(RCC_HCLK_Div1);//设置高速 AHB 时钟(PCLK2)1 @% c5 q( l% g) T RCC_PLLConfig(RCC_PLLSource_HSE_Div2,RCC_PLLMul_9);//设置 PLL 时钟源及倍频系 数 RCC_PLLCmd(ENABLE); //使能或者失能 PLL0 [/ i( A6 |. h) |! R6 R while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);//检查指定的 RCC 标志位设置 与否,PLL 就绪 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//设置系统时钟(SYSCLK) while(RCC_GetSYSCLKSource()!=0x08);//返回用作系统时钟的时钟源,0x08:PLL 作为3 a5 x( H6 h9 _7 v7 ~! F9 J 系统时钟4 Y; m p4 y' ~; l/ i }/ ^! ]; b# ]4 Y" B, f) ]7 I }& V6 I Q' V4 |# C 这个函数的作用是:设置单片机的时钟来源为 HSE 外部高速时钟,并根据输入频率参数设置相应的频率。 要注意的是设置的输入频率参数一定要是 8 的倍数,并且是从 4 倍到 9 倍的频率数值。 l5 }+ _ L7 K8 W" u4 f int main() { . ~! C( I$ ~" ]% ?/ p6 I led_Init(); //LED 端口初始化0 h/ b* P2 D7 z RCC_HSE_Configuration();// 自定义系统时间,可修改分频3 B6 `! W" |1 q1 h$ [. f3 i' y+ t# j while(1) { GPIO_SetBits(GPIOB,LED); delay_ms(500);//精确延时为 0.5s GPIO_ResetBits(GPIOB,LED); delay_ms(500);//精确延时为 0.5s0 M) v" w; k% K7 N; @. S+ J" s } }" i6 L2 R* J. B0 n& S' k; H 这次的系统实验就到这里了。1 T# d$ [1 m5 B+ o! u+ ?+ | |
消灭0回复![]() |