STM32学习笔记--时钟系统

基于正点原子mini开发板、STM32RCT6、库函数

目录:

  • 前言
  • 一、STM32时钟树
  • 二、STM32时钟相关配置

前言

  时钟系统是CPU的脉搏。
  无论是小型单片机还是像STM32这样的高级单片机,它们工作的核心都是大规模的时序逻辑电路,而驱动电路的关键则是准确而且稳定的时钟源。时钟为时序电路提供基本的脉冲信号,用于协调和同步各单元运行。
  51单片机不需要配置时钟,是因为一个时钟开了之后所有的功能都可以用了,而这个时钟是默认开启的。stm32之所以是低功耗,是因为它将所有的外设时钟都默认设置为disable,也就是说用到什么外设,只要打开对应外设的时钟就可以,其他的没用到的可以还是disable,这样耗能就会减少。

一、STM32时钟树

STM32学习笔记--时钟系统_第1张图片
  在 STM32 中,有五个时钟源,为 HSI、HSE、LSI、LSE、PLL。从时钟频率来分可以分为高速时钟源和低速时钟源,在这 5 个中 HIS,HSE 以及 PLL 是高速时钟,LSI 和 LSE 是低速时钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接晶振的方式获取时钟源,其中 HSE 和 LSE 是外部时钟源,其他的是内部时钟源。
1、HSI
  HSI,High Speed Internal Clock Signal,高速内部时钟,由内置RC振荡器产生,频率为8MHz,精度不高,备用时钟。
2、HSE
  HSE,High Speed External Clock Signal,高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4-16MHz(常用8MHz),启动后需要稳定时间才能输出稳定的时钟信号。
3、LSE
  LSE,Low Speed External Clock Signal,低速外部时钟,外接频率为32.768KHz的晶振,启动后需要稳定时间才能输出稳定的时钟信号,主要是RTC(Real Time Clock)实时时钟单元的时钟源。
4、LSI
  LSI,Low Speed Internal Clock Signal,低速内部时钟,内置RC振荡器产生,频率约为40KHz,在30-60KHz范围浮动,精度差,是独立看门狗的时钟源、RTC的时钟源之一。
5、PLL
  PLL,Phase Locked Loop,锁相环对输入信号进行倍频,输入信号:HSE、HSE/2,HIS/2,输出信号:输入信号*倍频系数,倍频系数:2-16,但是其输出频率最大不得超过72MHz。
6、SYSCLK(系统时钟)
  供STM32中绝大部分部件工作的时钟源。输入信号:HSE、HSI、PLLCLK,频率最大不得超过72MHz。经AHB预分频器分频后送给各模块使用。
7、USBCLK(USB时钟)
  频率48MHz,时钟源来自于PLL,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz,经USB预分频器分频后得到48MHz供给USB使用。
8、MCO功能模块(引脚)
  MCO是STM32一个时钟输出的IO口,可选择SYSCLK、HIS、HSE、PLLCLK/2中的一个作为输出,供给其他系统作为输入时钟源。
9、APB1与APB2
  APB1 上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等,APB2 上面连接的是高速外设包括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。

二、STM32时钟相关配置

  RCC相关配置寄存器可查阅官方芯片手册。

typedef struct
{
     
__IO uint32_t CR; //HSI,HSE,CSS,PLL等的使能和就绪标志位
__IO uint32_t CFGR; //PLL等的时钟源选择,分频系数设定
__IO uint32_t CIR; // 清除/使能 时钟就绪中断
__IO uint32_t APB2RSTR; //APB2线上外设复位寄存器
__IO uint32_t APB1RSTR; //APB1线上外设复位寄存器
__IO uint32_t AHBENR; //DMA,SDIO等时钟使能
__IO uint32_t APB2ENR; //APB2线上外设时钟使能
__IO uint32_t APB1ENR; //APB1线上外设时钟使能
__IO uint32_t BDCR; //备份域控制寄存器
__IO uint32_t CSR; //控制状态寄存器
} RCC_TypeDef;

  STM32时钟系统的配置主要在 stm32f10x_rcc.c 文件中,里面有很多时钟设置函数:
1.时钟使能配置:

RCC_LSEConfig() 、RCC_HSEConfig()、 RCC_HSICmd() 、 RCC_LSICmd() 、
RCC_PLLCmd() ……

2. 时钟源相关配置:

RCC_PLLConfig ()、 RCC_SYSCLKConfig() 、 RCC_RTCCLKConfig() …

3. 分频系数选择配置:

RCC_HCLKConfig() 、 RCC_PCLK1Config() 、 RCC_PCLK2Config()…

4. 外设时钟使能:

RCC_APB1PeriphClockCmd(); //APB1线上外设时钟使能

RCC_APB2PeriphClockCmd(); //APB2线上外设时钟使能

RCC_AHBPeriphClockCmd();//AHB线上外设时钟使能

5. 其他外设时钟配置:

RCC_ADCCLKConfig (); RCC_RTCCLKConfig();

6. 状态参数获取参数:

RCC_GetClocksFreq(); RCC_GetSYSCLKSource(); RCC_GetFlagStatus()

7. RCC中断相关函数 :

RCC_ITConfig() 、 RCC_GetITStatus() 、 RCC_ClearITPendingBit()…

  在设置时钟的时候,一定要仔细参考 STM32 的时钟图,做到心中有数。这里需要指明一下,对于系统时钟,默认情况下是在 SystemInit 函数的 SetSysClock()函数中间判断的,而设置是通过宏定义设置的。可以看到SetSysClock()函数体:

static void SetSysClock(void)
{
     
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
 SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
 SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
 SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
 SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
 SetSysClockTo72();
#endif
}

  这段代码就是判断系统宏定义的时钟是多少,然后设置相应值。系统默认宏定义是 72MHz:

#define SYSCLK_FREQ_72MHz 72000000

  如果要设置为 36MHz,只需要注释掉上面代码,然后加入下面代码即可:

#define SYSCLK_FREQ_36MHz 36000000

  同时还要注意的是,当我们设置好系统时钟后,可以通过变量 SystemCoreClock 获取系统时钟值,如果系统是 72M 时钟,那么 SystemCoreClock=72000000。这是在 system_stm32f10x.c 文件中设置的:

#ifdef SYSCLK_FREQ_HSE
 uint32_t SystemCoreClock = SYSCLK_FREQ_HSE;
#elif defined SYSCLK_FREQ_36MHz
 uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz;
#elif defined SYSCLK_FREQ_48MHz
 uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz;
#elif defined SYSCLK_FREQ_56MHz
 uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz;
#elif defined SYSCLK_FREQ_72MHz
 uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz;
#else
 uint32_t SystemCoreClock = HSI_VALUE;
#endif

  总结一下 SystemInit()函数中设置的系统时钟大小:

SYSCLK(系统时钟) =72MHz
AHB 总线时钟(使用 SYSCLK) =72MHz
APB1 总线时钟(PCLK1) =36MHz
APB2 总线时钟(PCLK2) =72MHz
PLL 时钟 =72MHz

你可能感兴趣的:(单片机,STM32,嵌入式,单片机,嵌入式,stm32,mcu)