STM32单片机———时钟

写在前面

部分引用:https://blog.csdn.net/as480133937/article/details/98845509 (这篇文章对时钟的介绍更加详细)
写本文的目的是一方面是做笔记,另一方面也是加深自己对时钟树的理解

时钟树一览

数据手册中的时钟树:
STM32单片机———时钟_第1张图片
STM32CubeMX中的时钟配置图:
STM32单片机———时钟_第2张图片

时钟源

四个独立的时钟源
HSE:高速外部时钟
无源晶振或者有源晶振提供,频率从4-16MHZ不等,通常使用8M的无源晶振
HSI:高速内部时钟
来源为RC振荡器,频率为8M,精度不高
LSI:低速内部时钟
RC振荡器,频率为40KHZ,提供低功耗时钟
LSE:低速外部时钟
频率为32.768KHZ的石英晶体

“一个不独立的时钟”
锁相环时钟:来源为HSI/2,HSE或者HSE/2, 该时钟的作用主要是通过锁相环倍频器之后作为系统时钟一个来源

举个例子:Keil编写程序是默认的时钟为72Mhz,其实是这么来的:外部晶振(HSE)提供的8MHz(与电路板上的晶振的相关)通过PLLXTPRE分频器后,进入PLLSRC选择开关,进而通过PLLMUL锁相环进行倍频(x9)后,为系统提供72MHz的系统时钟(SYSCLK)。之后是AHB预分频器对时钟信号进行分频,然后为低速外设提供时钟。

或者内部RC振荡器(HSI) 为8MHz /2 为4MHz 进入PLLSRC选择开关,通过PLLMUL锁相环进行倍频(x18)后 为72MHz

系统时钟SYSCLK
系统时钟来源主要有三个:

  1. HSI振荡器时钟
  2. HSE振荡器时钟
  3. PLL时钟
    最大为72MHZ
    时钟树看起来比较复杂,其实我们以系统时钟为桥梁来理解就行了,在上面的时钟树中,系统时钟左边的时钟是独立的时钟源,右边的部分是外设时钟,通过系统时钟的分频得到各个外设的时钟。
    其他时钟
    我们先看左下方的MCO时钟输出,这个相当于是一个对外输出的时钟,可以用示波器来测试,可以输出的时钟包括:PLLCLK/2、HSI、HSE以及系统时钟SYSCLK

然后是看门狗时钟: 看门狗是单片机里的一种技术(软硬件都可以),其目的是为了保护芯片避免其进入死循环(或者说程序跑飞)。看门狗有一个输入端和一个输出端。看门狗和单片机程序的主体部分连接,如果主体部分运行正常,那么每一段时间就会给看门狗的输入端一个信号,这时候看门狗就会知道程序运行正常,就不会做出反应。如果看门狗较长一段时间内没有收到信号,说明程序运行不正常,此时由看门狗输出一个信号,该信号会让单片机的主体程序复位进而起到保护的作用。**“每一段时间”**指的就是看门狗时钟,只由LSI提供。

RTC时钟(Real_Time Clock),实时时钟,可以由LSI/LSE 或者HSE/128提供

USB时钟:STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取(唯一的),,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz

RCC相关寄存器

RCC 寄存器结构,RCC_TypeDeff,在文件“stm32f10x.h”中定义如下:
 
1059->1081行。:  
typedef struct  
{  
vu32 CR;                 //HSI,HSE,CSS,PLL等的使能  
vu32 CFGR;               //PLL等的时钟源选择以及分频系数设定 
vu32 CIR;                // 清除/使能 时钟就绪中断 
vu32 APB2RSTR;           //APB2线上外设复位寄存器 
vu32 APB1RSTR;           //APB1线上外设复位寄存器 
vu32 AHBENR;             //DMA,SDIO等时钟使能 
vu32 APB2ENR;            //APB2线上外设时钟使能 
vu32 APB1ENR;            //APB1线上外设时钟使能 
vu32 BDCR;               //备份域控制寄存器 
vu32 CSR;             
} RCC_TypeDef; 

RCC初始化函数

RCC初始化:
这里我们使用HSE(外部时钟),正常使用的时候也都是使用外部时钟

使用HSE时钟,程序设置时钟参数流程:
1、将RCC寄存器重新设置为默认值   RCC_DeInit;
2、打开外部高速时钟晶振HSE       RCC_HSEConfig(RCC_HSE_ON);
3、等待外部高速时钟晶振工作      HSEStartUpStatus = RCC_WaitForHSEStartUp();
4、设置AHB时钟         RCC_HCLKConfig;
5、设置高速AHB时钟     RCC_PCLK2Config;
6、设置低速速AHB时钟   RCC_PCLK1Config;
7、设置PLL              RCC_PLLConfig;
8、打开PLL              RCC_PLLCmd(ENABLE);
9、等待PLL工作          while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
10、设置系统时钟        RCC_SYSCLKConfig;
11、判断是否PLL是系统时钟     while(RCC_GetSYSCLKSource() != 0x08)
12、打开要使用的外设时钟      RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()

首先,缺省值就是默认值的意思,默认值可以理解为设计芯片的人认为用这个参数,比较适中,起码不可能耽误你对某一模块进行驱动。然后,为什么除了默认值(缺省值),还有这么多其他的参数可以进行选择呢,那就要看你具体想要怎么开发这款芯片了,比如说你买了一辆自行车,那么自行车的轱辘个数,厂家的默认值(缺省值)是2,但是你买自行车不是用来方便出行的,而是单轮杂技表演的,那你就把轱辘个数设定为1。

最后,不重新设定为缺省值行不行,我建议跟着手册赚芯片设计者让你重设就好好听话,但是我们想要设定该寄存器参数为其他值,那就先重设为缺省,初始化后,延迟一会儿,再改为你想要的寄存器参数。这样做,一是代码规范,二是保险不出错,三是虽然看起来操作步骤变多了,但是耽误不了几个毫秒,开机时机器一般不需要多高的实时性最多开机慢。

你可能感兴趣的:(STM32暑假随笔,stm32)