嵌入式开发九:STM32时钟系统

         时钟对于单片机来说是非常重要的,它为单片机工作提供一个稳定的机器周期从而使系统能够正常运行。时钟系统犹如人的心脏,一旦有问题整个系统就崩溃。我们知道 STM32 属于高级单片机,其内部有很多的外设,但不是所有外设都使用同一时钟频率工作,比如内部看门狗和 RTC,它只需 30 几 KHz 的时钟频率即可工作,所以内部时钟源就有多种选择,不同的时钟源,它们的频率不一样,这样便构成了时钟树。通过前面对于启动过程的分析,我们知道 STM32 系统复位后首先进入 SystemInit 函数进行时钟的设置,将 STM32F407 系统时钟设置为 168MHz,然后进入主函数。那么这个系统时钟大小如何得来,其他外设的时钟又如何划分,这些问题都可以通过一张时钟树图找到答案,只要理解好时钟树,STM32 一切时钟的来龙去脉就会非常清楚。本文详细介绍STM32F407的时钟树,并且知道如何使能外设的时钟。

目录

一、什么是时钟

1.1 时钟对单片机的作用

1.2 为什么要有时钟树

二、时钟树

2.1 时钟源

2.1.1 四个重要的时钟源

(1)外部高速时钟HSE

(2)外部低速时钟LSE

(3)内部高速时钟HSI

(4)内部低速时钟LSI

2.2 锁相环PLL(重要)

2.3 系统时钟 SYSCLK

2.4 AHB 总线时钟 HCLK

2.5 APB2 总线时钟 

2.6 APB1 总线时钟 

2.7 RTC时钟

2.8 独立看门狗时钟

2.9 MCO时钟输出

 2.10 总结    

三、时钟初始化过程及与时钟相关的函数

3.1  STM32F4 时钟初始化配置过程

3.2 STM32F4 时钟使能

3.2.1 时钟使能函数

3.2.1.1 外设时钟使能函数

3.2.1.2 时钟源使能函数

3.2.2 时钟功能函数

3.2.3 外设复位函数


一、什么是时钟

1.1 时钟对单片机的作用

       时钟是由电路产生的具有周期性的脉冲信号,众所周知,时钟系统是 CPU 的脉搏,就像人的心跳一样。所以时钟系统的重要性就不言而喻了。相当于单片机的心脏,要想使用单片机的外设必须开启相应的时钟,因为驱动外设的本质是操作寄存器,而寄存器是由D触发器构成,而触发器需要时钟才能改写值,所以要想操作寄存器必须开启对应外设的时钟。对CPU来说假设CPU在一个时钟周期内执行一条指令(二进制代码),若时钟频率越高,而时钟(周期)等于1/f为频率的倒数,则时钟周期更短代表在相同的时间内,CPU能够执行更多的指令,CPU的运行速度会更快。

1.2 为什么要有时钟树

        一个 MCU 越复杂,时钟系统也会相应地变得复杂,如 STM32F4 的时钟系统比较复杂,不像简单的 51 单片机一个系统时钟就可以解决一切。对于 STM32F4 系列的芯片,正常工作的主频可以达到 168Mhz,但并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及 RTC 只需要几十 Khz 的时钟即可,此外,同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的 MCU 一般都是采取多时钟源的方法来解决这些问题。 STM32 本身非常复杂,外设非常的多,为了保持低功耗工作,STM32 的主控默认不开启这些外设功能。用户可以根据自己的需要决定 STM32 芯片要使用的功能,这个功能开关在 STM32 主控中也就是各个外设的时钟。 

      STM32时钟系统主要的目的就是给相对独立的外设模块提供时钟,主要也是为了降低整个芯片的功耗,所有外设时钟默认都是关闭状态(disable)当我们使用某个外设就要开启这个外设的时钟(enable),不同外设需要的时钟频率不同,没必要所有外设都用高速时钟造成浪费,而且有些外设也接受不了这么高的频率,这也是为什么STM32有四个时钟源的原因,就是兼容不同速度的外设,STM32的四个时钟源分别为:HSE、 LSE、HSI、LSI

二、时钟树

      首先让我们来看看 STM32F4 的时钟系统图:

先粗略看一下时钟图,STM32F4 时钟系统图看起来有点多且复杂,但是分开几部分各个理解其实没有那么难了,接下来就是分时钟源一一详细讲解(重点)。

       在 STM32F4 中,有 4个最重要的时钟源,为 HSI、HSE、LSI、LSE。从时钟频率来分可以分为高速时钟源和低速时钟源, HSI,HSE 是高速时钟,LSI 和 LSE 是低速时钟。从来源可分为外部时钟源和内部时钟源,外部时钟源就是从外部通过接石英晶体振荡器的方式获取时钟源,其中 HSE 和 LSE 是外部时钟源,LSE和LSI是内部时钟源,它是通过芯片内部的RC振荡电路实现。

2.1 时钟源

2.1.1 四个重要的时钟源

(1)外部高速时钟HSE

         HSE:High Speed External Clock signal,即高速的外部时钟。图标 3 HSE 是外部高速时钟, STM32ZGT6芯片的 23 和 24 引脚即为外部高速晶振管脚。可通过外接一个频率范围是 4-26MHz 的石英/陶瓷谐振器,我们开发板上接的是一个 8MHz 的外部晶振。

HSE 可以作为系统时钟和 PLL 锁相环输入,还可以经过 2-31分频后输入给 RTC。

(2)外部低速时钟LSE

         LSE :Low Speed External Clock signal), 图标 2 LSE 是外部低速时钟,我们开发板上 STM32 芯片的 PC14 和 PC15 即为外部低速时钟管脚。通常在此管脚上外接一个 32.768KHz 的晶振.

LSE主要作用于 RTC 的时钟源。

      以上2 个外部时钟源都是芯片外部晶振产生的时钟频率,故而都有精度高的优点 。

(3)内部高速时钟HSI

     HSI:High Speed Internal Clock signal),图标 4 HSI 是内部高速时钟,由内部 RC 振荡器产生频率为 16MHz。如果我们使用 HSE 或者 HSE 经过 PLL 倍频之后的时钟作为系统时钟SYSCLK, 当 HSE 故障时候,不仅 HSE 会被关闭,PLL 也会被关闭,此时高速的内部时钟时钟信号 HSI 会作为备用的系统时钟,直到 HSE 恢复正常。HSI RC振荡器能够在不需要任何外部器件的条件下提供系统时钟。它的启动时间比HSE晶体振荡器短。然而,即使在校准之后它的时钟频率精度仍较差,如果HSE晶体振荡器失效,HSI时钟会被作为备用时钟源。

可作为系统时钟或 PLL 锁相环的输入。

(4)内部低速时钟LSI

       LSI: low Speed Internal Clock signal,低速的内部时钟。图标 1 LSI 是内部低速时钟,RC 振荡器,频率大约为 32K,LSI 担当一个低功耗时钟源的角色,它可以在停机和待机模式下保持运行

可供独立看门狗和 RTC 使用

      芯片上电时默认由内部的 HSI 时钟启动,如果用户进行了硬件和软件的配置,芯片才会根据用户配置调试尝试切换到对应的外部时钟源,所以同时了解这几个时钟源信号还是很有必要的。

2.2 锁相环PLL(重要)

      锁相环是自动控制系统中常用的一个反馈电路,在 STM32 主控中,锁相环的作用主要有 两个部分:输入时钟净化和倍频。前者是利用锁相环电路的反馈机制实现,后者我们用于使芯片在更高且频率稳定的时钟下工作。 在 STM32 中,锁相环的输出也可以作为芯片系统的时钟源。PLL 的主要作用是对时钟进行倍频,然后把时钟输出到各个功能部件。图标 5 PLL 是锁相环,用于倍频输出,因为开发板外部高速晶振也只有 8M,而我们这块芯片的最大时钟频率是 168M,因此可通过 PLL 锁相环来倍频。 从图标 5 中可以看到,PLL 分两个,最上面一个称为主 PLL,下面那个称为专用 PLL.

PLL 为锁相环倍频输出。STM32F4 有两个 PLL:

1) 主 PLL(PLL)由 HSE 或者 HSI 提供时钟信号,并具有两个不同的输出时钟。 第一个输出 PLLP 用于生成高速的系统时钟(最高 168MHz) 第二个输出 PLLQ 用于生成 USB OTG FS 的时钟(48MHz),随机数发生器的时钟和 SDIO 时钟。

2)专用 PLL(PLLI2S)用于生成精确时钟,从而在 I2S 接口实现高品质音频性能。

从上面我们可以知道,PLL可以由HSE或者HSI通过倍频,从而产生168MHZ的系统时钟,那么它是怎么倍频产生 168MHz 系统时钟的呢?我们看到在主 PLL 内有倍频器和分频器,如下图所示。

从上图可以看出,它有两种可选择的输入源:一个是内部时钟 HSI 信号,另一个是外部时钟 HSE 信号。主 PLL 时钟源的输入信号要先经过一个分频系数为 M 的分频器,将 HSE 或 HSI 分频 M 值后输入给 VCO,经过一个倍频系数为 N 的倍频器, 再经过分频系数为 P 和 Q 的分频器,最终输出主 PLL 时钟和专用 PLL 时钟。

因此可以推倒出一个 PLL 时钟的计算公式:PLL=(HSE(HSI)/M)*N/P

 因为我们开发板上 HSE 是 8M 的晶振,如果将 M 值设置为 8,N 值为 336,P 值为 2,最后计算就可以得到主 PLL 为 168MHz。如果我们选择 HSE 是 PLL 的时钟源,PLL 是 SYSCLK 的时钟源,即 SYSCLK 为 168MHz,这个也是我们创建库函数模板所配置的最终系统时钟。

2.3 系统时钟 SYSCLK

     STM32 的系统时钟 SYSCLK 为整个芯片提供了时序信号。我们已经大致知道 STM32 主控 是时序电路链接起来的。对于相同的稳定运行的电路,时钟频率越高,指令的执行速度越快, 单位时间能处理的功能越多。STM32 的系统时钟是可通过寄存器配置的,在 STM32F4 系列中,它可以为 HSI、PLLCLK、HSE 中的一个。我们这里设置系统时钟:SYSCLK = PLLCLK = 168M。如果系统时钟是由 HSE 经过 PLL 倍频之后的 PLLCLK 得到的。

2.4 AHB 总线时钟 HCLK

       根据我们开发板的资源,可以把主频通过 PLL 设置为 168MHz。 从上面的时钟树图可知,AHB、APB1、APB2、内核时钟等时钟通过系统时钟分频得到。

  • 作用:为AHB总线的外设提供时钟、为Cortex系统定时器提供时钟(SysTick)、为内核提供时(FCLK)

        系统时钟 SYSCLK 经过 AHB 预分频器分频之后得到时钟叫 AHB 总线时钟,即 HCLK, 分频因子可以是:[1,2,4,8,16,64,128,256,512],具体的由时钟配置寄存器配置,在这里,我们选择不分频,所以 AHB 总线时钟达到最大的 168MHz。经过 8 分频后给 Cortex 系统定时器 Systick 提供时钟。系统定时器(基本定时器)在后面的章节中会介绍。

2.5 APB2 总线时钟 

       通过 AHB 分频器可以分出 AHB、APB1 和 APB2 时钟,它们都是由系统时钟经过分频得来。 APB2 总线时钟,由 HCLK 经过高速 APB2 预分频器得到,分频因子可以选择 1, 2,4,8,16,这里我们选择的是 2 分频,所以 APB2 总线时钟频率为 84M。

2.6 APB1 总线时钟 

       APB1 总线时钟,由 HCLK 经过低速 APB1 预分频器得到,分频因子可以选择 1, 2,4,8,16,这里我们选择的是 4 分频,所以 APB1 总线时钟为 42M。

AHB 时钟频率最大为 168MHz,APB2 时钟频率最大为 AHB 的 2 分频即 84MHz,APB1 时钟频率最大为 AHB 的 4 分频即 42MHz。从时钟频率大小来看,我们也就知道 AHB 的总线速度要比 APB2 快,APB2 的总线速度又比 APB1 快。

2.7 RTC时钟

      RTC 时钟。从图中线的流向可知,RTC 时钟来源可以是内部低速的 LSI 时钟,外部低速 LSE 时钟(32.768K),还可以通过 HSE 分频后得到,分频系数是 2-31。

2.8 独立看门狗时钟

     看门狗时钟。从图中线的流向可知,看门狗时钟源只能是低速的 LSI 时钟。

2.9 MCO时钟输出

      STM32 时钟输出管脚。可以把时钟信号输出供外部使用,也可以用示波器检测时钟信号的参数(峰峰值,频率…),这里是 STM32F4 输出时钟 MCO1 和 MCO2。MCO1 是向芯片的 PA8 引脚输出时钟。它有四个时钟来源分别为:HSI,LSE,HSE 和 PLL 时钟。MCO2 是向芯片的PC9 输出时钟,它同样有四个时钟来源分别为:HSE,PLL,SYSCLK 以及 PLLI2S 时钟。MCO 输出时钟频率最大不超过 100MHz。

 2.10 总结    

     

通过以上内容的介绍,我们知道 STM32F407 的时钟设计的比较复杂,各个时钟基本都是可控的,任何外设都有对应的时钟控制开关,这样的设计,对降低功耗是非常有用的,不用的外设不开启时钟,就可以大大降低其功耗。在时钟树图中我们还可以得到一个重要信息,大多数有关时钟输出部分都有 一个使能控制,比如 AHB 总线、APB1 外设、APB2 外设、内核时钟等。当需要使用某个时钟的时候一定要开启它的使能,否则将不工作。比如点亮一个 LED 实验就需要使能 GPIO 的外设时钟,如果不开启,LED 将不工作。

三、时钟初始化过程及与时钟相关的函数

3.1  STM32F4 时钟初始化配置过程

     上一节我们知道,STM32单片机上电,就会执行启动文件(汇编代码编写)中的复位程序。

执行复位程序
1.调用SystemInit系统初始化函数完成系统时钟的配置(配置成168MHZ)
2.调用_main函数初始化堆栈指针,然后再调用C库函数main函数,去到C语言的世界
所以跳转到C语言的main函数时,已经完成了系统时钟(SYSCLK)的配置。

STM32F4 时钟系统初始化是在 system_stm32f4xx.c 中的 SystemInit()函数中完成的。对于系统时钟关键寄存器设置主要是在 SystemInit 函数中调用 SetSysClock()函数来设置的。

      SystemInit 函数开始先进行浮点运算单元设置,然后是复位 PLLCFGR,CFGR 寄存器,同时 通过设置 CR 寄存器的 HSI 时钟使能位来打开 HSI 时钟。默认情况下如果 CFGR 寄存器复位, 那么是选择 HSI 作为系统时钟,这点大家可以查看 RCC->CFGR 寄存器的位描述最低 2 位可以 得知,当低两位配置为 00 的时候(复位之后),会选择 HSI 振荡器为系统时钟。也就是说,调用 SystemInit 函数之后,首先是选择 HSI 作为系统时钟。在设置完相关寄存器后,接下来 SystemInit 函数内部会调用 SetSysClock 函数。先使能外部时钟 HSE,等待 HSE 稳定之后,配置 AHB,APB1,APB2 时钟相关的分频因子,也就是相关外设的时钟。等待这些都配置完成之后, 打开主 PLL 时钟,然后设置主 PLL 作为系统时钟 SYSCLK 时钟源。如果 HSE 不能达到就绪状 态(比如外部晶振不能稳定或者没有外部晶振),那么依然会是 HSI 作为系统时钟。

        在设置主 PLL 时钟的时候,会要设置一系列的分频系数和倍频系数参数。这些参数是通过宏定义标识符的值来设置的。默认的配置在 System_stm32f4xx.c 文件开头的地 方配置。对于我们开发板,我们的设置参数值如下:

这里还有个特别需要注意的地方,就是我们还要同步修改 stm32f4xx.h 中宏定义标识符 HSE_VALUE 的值为我们的外部时钟:

#if !defined (HSE_VALUE) 
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */#endif /* HSE_VALUE */

        这里默认固件库配置的是 25000000,我们外部时钟为 8MHz,所以我们根据我们硬件情况修改 为 8000000 即可。 

      讲到这里,大家对 SystemInit 函数的流程会有个比较清晰的理解。那么 SystemInit 函数是怎么被系统调用的呢?SystemInit 是整个设置系统时钟的入口函数。这个函数对于我们使用 ST 提供的 STM32F4 固件库的话,会在系统启动之后先执行 main 函数,然后再接着执行 SystemInit 函数实现系统相关时钟的设置。这个过程设置是在启动文件 startup_stm32f40_41xxx.s 中间设置的,我们接下来看看启动文件中这段启动代码:

; Reset handler
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT SystemInitIMPORT __mainLDR R0, =SystemInitBLX R0LDR R0, =__mainBX R0ENDP

        这段代码的作用是在系统复位之后引导进入 main 函数,同时在进入 main 函数之前,首先 要调用 SystemInit 系统初始化函数完成系统时钟等相关配置。 最后我们总结一下 SystemInit()函数中设置的系统时钟大小:

SYSCLK(系统时钟) =168MHz
AHB 总线时钟(HCLK=SYSCLK) =168MHz
APB1 总线时钟(PCLK1=SYSCLK/4) =42MHz
APB2 总线时钟(PCLK2=SYSCLK/2) =84MHz
PLL 主时钟 =168MHz

3.2 STM32F4 时钟使能

     上小节我们讲解了系统复位之后调用 SystemInit 函数之后相关时钟的默认配置。如果在系统初始化之后,我们还需要修改某些时钟源配置,或者我们要使能相关外设的时钟该怎么设置 呢?这些设置实际是在 RCC 相关寄存器中配置的。因为 RCC 相关寄存器非常多,有兴趣的同学可以直接打开《STM32F4 中文参考手册》查看所有 RCC 相关寄存器的配置。所以这里我们不直接讲解寄存器配置,而是通过 STM32F4 标准固件库配置方法给大家讲解。

        在 STM32F4 标准固件库里,时钟源的选择以及时钟使能等函数都是在 RCC 相关固件库文 件 stm32f4xx_rcc.h 和 stm32f4xx_rcc.c 中声明和定义的。大家打开 stm32f4xx_rcc.h 文件可以看 到文件开头有很多宏定义标识符,然后是一系列时钟配置和时钟使能函数申明。这些函数大致 可以归结为三类,一类是外设时钟使能函数,一类是时钟源和分频因子配置函数,还有一类是外设复位函数。当然还有几个获取时钟源配置的函数。下面我们以几种常见的操作来简要介绍一下这些库函数的使用。

3.2.1 时钟使能函数

     首先是时钟使能函数。时钟使能相关函数包括外设时钟使能和时钟源使能两类。首先我们来看看外设时钟使能相关的函数:

3.2.1.1 外设时钟使能函数
void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

       这里主要有 5 个外设时钟使能函数。5 个函数分别用来使能 5 个总线下面挂载的外设时钟,这些总线分别为:AHB1 总线,AHB2 总线,AHB3 总线,APB1 总线以及 APB2 总线。要使能某个外设,调用对应的总线外设时钟使能函数即可。 这里我们要特别说明一下,STM32F4 的外设在使用之前,必须对时钟进行使能,如果没有使能时钟,那么外设是无法正常工作的。

         对于哪个外设是挂载在哪个总线之下,虽然我们也可以查手册查询到,但是这里如果大家使用的是库函数的话,实际上是没有必要去查询手册的, 这里我们给大家介绍一个小技巧。比如我们要使能 GPIOA,我们只需要在 stm32f4xx_rcc.h 头文件里面搜索 GPIOA,就可以搜索到对应的时钟使能函数的第一个入口参数为 RCC_AHB1Periph_GPIOA,从这个宏定义标识 符一眼就可以看出,GPIOA 是挂载在 AHB1 下面。同理,对于串口 1 我们可以搜索 USART1, 找到标识符为RCC_APB2Periph_USART1,那么很容易知道串口 1 是挂载在 APB2 之下。这个知识在我们后面的快速组织代码技巧也有讲解,这里顺带提一下。 如果我们要使能 GPIOA,那么我们可以在头文件 stm32f4xx_rcc.h 里面查看到宏定义标识 符 RCC_AHB1Periph_GPIOA,顾名思义 GPIOA 是挂载在 AHB1 总线之下,所以,我们调用 AHB1 总线下外设时钟使能函数 RCC_AHB1PeriphClockCmd 即可。具体调用方式入如下:

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能 GPIOA 时钟

同理,如果我们要使能串口 1 的时钟,那么我们调用的函数为:

void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); 
具体的调用方法是: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
3.2.1.2 时钟源使能函数

      还有一类时钟使能函数是时钟源使能函数,前面我们已经讲解过 STM32F4 有 5 大类时钟 源。这里我们列出来几种重要的时钟源使能函数:

void RCC_HSICmd(FunctionalState NewState);
void RCC_LSICmd(FunctionalState NewState);
void RCC_PLLCmd(FunctionalState NewState);
void RCC_PLLI2SCmd(FunctionalState NewState);
void RCC_PLLSAICmd(FunctionalState NewState);
void RCC_RTCCLKCmd(FunctionalState NewState);

这些函数是用来使能相应的时钟源。比如我们要使能 PLL 时钟,那么调用的函数为:

void RCC_PLLCmd(FunctionalState NewState); 
具体调用方法如下: RCC_PLLCmd(ENABLE); 我们要使能相应的时钟源,调用对应的函数即可。

3.2.2 时钟功能函数

      接下来我们要讲解的是第二类时钟功能函数:时钟源选择和分频因子配置函数这些函数是用来选择相应的时钟源以及配置相应的时钟分频系数。比如我们之前讲解过系统时钟 SYSCLK,我们可以选择 HSI,HSE 以及 PLL 三个中的一个时钟源为系统时钟。那么到底选择哪 一个,这是可以配置的。下面我们列举几种时钟源配置函数:

void RCC_LSEConfig(uint8_t RCC_LSE);
void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource);
void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
void RCC_PCLK1Config(uint32_t RCC_HCLK);
void RCC_PCLK2Config(uint32_t RCC_HCLK);
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource);
void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, 
uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ);

比如我们要设置系统时钟源为 HSI,那么我们可以调用系统时钟源配置函数:

void RCC_HCLKConfig(uint32_t RCC_SYSCLK);
具体配置方法如下:
RCC_HCLKConfig(RCC_SYSCLKSource_HSI);//配置时钟源为 HSI

又如我们要设置 APB1 总线时钟为 HCLK 的 2 分频,也就是设置分频因子为 2 分频,那么 如果我们要使能 HSI,那么调用的函数为:

void RCC_PCLK1Config(uint32_t RCC_HCLK);
具体配置方法如下:
RCC_PCLK1Config(RCC_HCLK_Div2);

3.2.3 外设复位函数

       接下来我们看看第三类外设复位函数,

void RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);
void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState);
void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState);
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);

这类函数跟前面讲解的外设时钟函数使用方法基本一致,不同的是一个是用来使能外设 钟,一个是用来复位对应的外设。这里大家在调用函数的时候一定不要混淆。 对于这些时钟操作函数,我们就不一一列举出来,大家可以打开 RCC 对应的文件仔细了解。

        以上便是STM32时钟系统的全部内容,如有兴趣,感谢点赞、关注、收藏,若有不正地方,还请各位大佬多多指教!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/834554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算安全扩展要求解析

云计算技术的信息系统&#xff0c;称为云计算平台&#xff0f;系统。 云计算平台&#xff0f;系统由设施、硬 件、资源抽象控制层、虚拟化计算资源、软件平台和应用软件等组成。 软件即服务(SaaS)、平台即服务 (PaaS) 、基础设施即服务ClaaS)是三种基本的云计算服务模式。在不同…

实验10配置 IPv4 和 IPv6 静态和 默认路由(课内实验)

上面这个是实验描述 下面是给的实验图 接下来我们跟着实验一步一步进行下去 第 1 部分&#xff1a;配置 IPv4 静态和 浮动静态默认路由配置ipv4静态路由&#xff1a;配置 IPv4静态和 浮动静态默认路由 步骤 1&#xff1a;配置一条 IPv4 静态 默认路由。在 Edge_Router 上&am…

ASP.NET校园新闻发布系统的设计与实现

摘 要 校园新闻发布系统是在学校区域内为学校教育提供资源共享、信息交流和协同工作的计算机网络信息系统。随着网络技术的发展和Internet应用的普及&#xff0c;互联网已成为人们获取信息的重要来源。由于现在各大学校的教师和学生对信息的需求越来越高&#xff0c;校园信息…

Linux-笔记 修改开发板默认时区

1. 时区文件 使用命令date -R查看当前的默认时区&#xff0c;date - R命令会自动解析/etc/localtime 文件&#xff0c;而该文件又是指向“ /usr/share/zoneinfo/$主时区/$次时区 ”&#xff0c;当需要更改到指定的时区只要将/etc/localtime 文件软链接到 ”/usr/share/zoneinf…

13 华三三层链路聚和

13 华三三层链路聚和 AI 解析 华三三层静态路由是指在华三交换机上配置的一种路由方式。它通过在交换机上手动配置路由表&#xff0c;将不同网络之间的数据进行转发。 华三三层静态路由的配置步骤如下&#xff1a; 1. 配置交换机接口的IP地址&#xff1a;在交换机上选择要配…

95、动态规划-编辑距离

递归暴力解法 递归方法的基本思想是考虑最后一个字符的操作&#xff0c;然后根据这些操作递归处理子问题。 递归函数定义&#xff1a;定义一个递归函数 minDistance(i, j)&#xff0c;表示将 word1 的前 i 个字符转换成 word2 的前 j 个字符所需的最小操作数。 递归终止条件…

【计算机毕业设计】基于SSM++jsp的蜀都天香酒楼网站【源码+lw+部署文档+讲解】

目录 摘要 Abstract 目 录 1绪论 1.1研究背景与意义 1.2国内外研究现状 1.3研究内容 1.4论文结构 2相关技术介绍 2.1 B/S模式 2.2 MyEclipse开发环境 2.3 MySQL数据库 2.4 Java语言 2.5 JSP技术 2.6 Tomcat服务器 3系统分析 3.1需求分析 3.2可行性分析 3.2.1经济可行性 3.2.2技…

[Linux深度学习笔记5.9]

5.9笔记 DNS: 软硬链接&#xff1a; 软链接&#xff1a; 软链接&#xff1a;ln -s /源文件 /目标位置/链接名称》创建软链接1.既可以对目录使用&#xff0c;也可以对文件使用2.删除源文件&#xff0c;软链接不可用3.软链接可以跨文件系统使用4.源文件和软链接的inode号不同5.…

短信平台群发服务有什么优点

短信平台群发服务有什么优点 提高营销效率 短信平台群发服务利用自动化技术&#xff0c;可以帮助企业迅速向大量潜在客户营销信息。相比传统的逐一方式&#xff0c;群发服务可以同时大批目标客户&#xff0c;大大提高了营销效率。企业可以轻松地在短时间内覆盖更多的潜在客户&…

B/S模式的web通信

这里写目录标题 目标实现的目标 服务器代码&#xff08;采用epoll实现服务器&#xff09;整体框架main函数init_listen_fd函数&#xff08;负责对lfd初始化的那一系列操作&#xff09;epoll_run函数 一级目录二级目录二级目录二级目录 目标 实现的目标 我们要实现&#xff0c;…

数据结构-二叉树-AVL树(平衡二叉树)

红黑树是平衡二叉树的一个变种。 一、 产生平衡二叉树的原因。 二叉搜索树的问题在于极端场景下退化为类似链表的结构&#xff0c;所以搜索的时间复杂度就变成了O(N)。为了保证二叉树不退化为链表&#xff0c;我们必须保证二叉树的的平衡性。 二叉平衡搜索树就是解决上面的问…

web API设计笔记

Hello , 我是小恒。今晚就讲讲我在开发维护API后的经验分享&#xff0c;当然我知识有限&#xff0c;暂时也不会写实际操作。GitHub项目仓库有一堆还在前期开发&#xff0c;我的时间很多时间投在了开源上。 推荐书籍 我认为一个好的 API 设计是面向用户的&#xff0c;充分隐藏底…

深入探索Android应用数据共享之ContentProvider

本文将深入探讨Android开发中非常重要的数据共享机制 - ContentProvider。 主要内容包括: ContentProvider的基本定义及特点如何实现一个自定义的ContentProviderContentProvider对外提供的功能以及对外部应用的权限控制对ContentProvider的一些常见使用场景使用ContentProvi…

OpenGL入门第一步:创建窗口、重写虚函数

1、创建一个QOpenGLWidget 子类 2、重写虚函数 initializeGL&#xff1a;设置OpenGL资源和状态。在第一次调用resizeGL()或paintGL()之前被调用一次。 resizeGL &#xff1a;窗口尺寸变化时调用。 paintGL&#xff1a; 窗口更新时调用&#xff0c;渲染 OpenGL 场景。 makeCu…

最详尽的网络安全学习路线!涵盖所有技能点,带你成为网安专家!

目录 零基础小白&#xff0c;到就业&#xff01;入门到入土的网安学习路线&#xff01; 建议的学习顺序&#xff1a; 一、夯实一下基础&#xff0c;梳理和复习 二、HTML与JAVASCRIPT&#xff08;了解一下语法即可&#xff0c;要求不高&#xff09; 三、PHP入门 四、MYSQL…

Marin说PCB之国产电源芯片方案 ---STC2620Q

随着小米加入的造车大家庭&#xff0c;让这个本来就卷的要死的造车大家庭更加卷了。随之带来的蝴蝶效应就是江湖上各个造成门派都开始了降本方案的浪潮啊&#xff0c;开始打响价格战了。各家的新能源车企也是不得不开始启动了降本方案的计划了&#xff0c;为了应对降价的浪潮。…

Window7镜像注入USB驱动,解决系统安装后无法识别USB

Window7镜像注入usb驱动 Window7镜像注入usb驱动方法一方法二 Window7镜像注入usb驱动 一般4代酷睿之后的主机需要安装usb驱动才能驱动usb&#xff0c;导致很多Windows原版镜像安装后无法识别usb键盘 方法一 1.直接采购PS2 接口键盘、PS2 接口鼠标 方法二 使用联想镜像注入…

李飞飞团队 AI4S 最新洞察:16 项创新技术汇总,覆盖生物/材料/医疗/问诊……

不久前&#xff0c;斯坦福大学 Human-Center Artificial Intelligence (HAI) 研究中心重磅发布了《2024年人工智能指数报告》。 作为斯坦福 HAI 的第七部力作&#xff0c;这份报告长达 502 页&#xff0c;全面追踪了 2023 年全球人工智能的发展趋势。相比往年&#xff0c;扩大了…

AOF持久化是怎么实现的?

AOF持久化是怎么实现的&#xff1f; AOF 日志三种写回策略AOF 重写机制AOF 后台重写总结参考资料 AOF 日志 试想一下&#xff0c;如果 Redis 每执行一条写操作命令&#xff0c;就把该命令以追加的方式写入到一个文件里&#xff0c;然后重启 Redis 的时候&#xff0c;先去读取这…

在k8s中部署hadoop后的使用,包括服务端及客户端(客户端的安装及与k8s服务的对接)

&#xff08;作者&#xff1a;陈玓玏&#xff09; 在https://blog.csdn.net/weixin_39750084/article/details/136744772?spm1001.2014.3001.5502和https://blog.csdn.net/weixin_39750084/article/details/136750613?spm1001.2014.3001.5502这两篇文章中&#xff0c;说明…