【STM32单片机学习】第9章 基础重点—时钟系统

发布者:ShimmeringMoon最新更新时间:2025-11-04 来源: bilibili关键字:STM32  单片机  时钟系统 手机看文章 扫描二维码
随时随地手机看文章

9.1 关于时钟

时钟对于一款芯片非常重要,其作用相当于人的心脏,人只有在心率正常稳定的情况下才能健康生活,同样的,芯片只有工作在合法正常的时钟频率下才能保证程序得到正常的运行。

本章就将从时钟树开始分析STM32F103的时钟系统,其中包括内部高速/低速时钟源、外部高速/低速时钟源、PLL(锁相环)和系统滴答定时器。以高屋建瓴的形式让用户对STM32F103的时钟系统有一个整体的认识,并在后续的时钟配置实验中让用户进一步的了解HAL库下的时钟配置流程。

首先读者要学会如何读STM32F103系列的时钟树,如图 9.1.1 所示,左侧的①HSI(内部高速时钟)、②HSE(外部高速时钟)、③LSE(外部低速时钟)、④LSI(内部低速时钟)为时钟源,右侧的各种片上外设。图中矩形框内用“/”加数字表示分频器,数字表示几分频;矩形框内用“X”加数字表示的为锁相环,数字表示几倍频;倒梯形表示选择器,长边表示多个输入,短边表示选择其中一个输出。

⑥系统时钟SYSCLK最高为72MHz,从图中左侧的选择器SW可以看到来源有三个,分别是:①内部高速时钟HSI(绿色)、⑤锁相环时钟PLLCLK(紫色)和②外部高速时钟HSE(黄色),而锁相环时钟PLLCLK由内部高速时钟HSI和外部高速时钟HSE,经过分频和PLL锁相环倍频而来。

内部高速时钟HSI可直接经过选择器SW给系统时钟SYSCLK,此时系统时钟SYSCLK为8MHz;内部高速时钟HSI先2分频,再经过选择器PLLSRC进入锁相环PLLMUL,最大倍频为16倍,得到64MHz的锁相环时钟PLLCLK给系统时钟SYSCLK;当外部高速时钟HSE(假设外接晶振为8MHz时)直接给选择器SW,则系统时钟SYSCLK为8MHz;当外部高速时钟HSE(假设外接晶振为8MHz时)直接经过选择器PLLXTPRE给PLLSRC,再经过PLLMUL 9倍频,得到72MHz的PLLCLK给系统时钟SYSCLK。

⑩RTCCLK(实时时钟)的时钟源也有三个,分别是②外部高速时钟HSE的128倍分频(黄色)、③外部低速时钟LSE的32.768kHz(蓝色)、④内部低速时钟LSI的40kHz(橙色)。

11.WDGCLK(独立看门狗)的时钟来源于④内部低速时钟LSI的40kHz(橙色)。

 

理清各个时钟来源后,再来看各总线的时钟。⑦高速接口总线AHB由⑥SYSCLK系统时钟分频得到,最高是系统时钟的72MHz。⑧外设总线APB1和⑨外设总线APB2,来源于⑦高速接口总线AHB,APB1的输出时钟最高是36MHz,APB2的输出时钟最高是72MHz。APB1和APB2下有各种外设,比如GPIO、USART等。

图 9.1.1 时钟树

                                                                                  

9.2 硬件设计

内部时钟HSI不涉及硬件,外部时钟HSE参考前面最小系统的时钟电路,“5.2.2 时钟电路”。

 

9.3 软件设计

9.3.1 软件设计思路

实验目的:分别使用内部时钟HSI和外部时钟HSE作为系统时钟。

1) 使用内部时钟HSI配置系统时钟到最大值64Mhz;

2) 调用库函数读取系统时钟值以验证;

3) 使用外部时钟HSE配置系统时钟到最大值72Mhz;

4) 调用库函数读取系统时钟值以验证;

本实验配套代码位于“5_程序源码3_基础重点—时钟系统”。

 

9.3.2 软件设计讲解

1) 使用内部时钟源HSI作为PLL的时钟源,然后将PLL作为系统时钟源

内部时钟HSI配置如代码段 9.3.1 所示,HAL库定义了两个结构体,只需要设置这两个结构体成员,就完成对时钟的设置。

代码段 9.3.1 使用HSI作为系统时钟(stm32f1xx_clk.c)


/**


  * @brief  System Clock Configuration


  *         The system Clock is configured as follow :


  *            System Clock source            = PLL (HSI)


  *            SYSCLK(Hz)                     = 64000000


  *            HCLK(Hz)                       = 64000000


  *            AHB Prescaler                  = 1


  *            APB1 Prescaler                 = 2


  *            APB2 Prescaler                 = 1


  *            PLLMUL                         = 16


  *            Flash Latency(WS)              = 2


  * @param  None


  * @retval None


  */


void SystemClock_Config(void)


{


    RCC_OscInitTypeDef RCC_OscInitStruct = {0};


    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};




    RCC_OscInitStruct.OscillatorType    = RCC_OSCILLATORTYPE_HSI;


    RCC_OscInitStruct.HSEState          = RCC_HSE_OFF;


    RCC_OscInitStruct.HSEPredivValue    = RCC_HSE_PREDIV_DIV1;


    RCC_OscInitStruct.HSIState          = RCC_HSI_ON;


    RCC_OscInitStruct.PLL.PLLState      = RCC_PLL_ON;


    RCC_OscInitStruct.PLL.PLLSource     = RCC_PLLSOURCE_HSI_DIV2;


    RCC_OscInitStruct.PLL.PLLMUL        = RCC_PLL_MUL16;


    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)


    {


        while(1);


    }




    /** Initializes the CPU, AHB and APB busses clocks


    */


    RCC_ClkInitStruct.ClockType         = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK  | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;


    RCC_ClkInitStruct.SYSCLKSource      = RCC_SYSCLKSOURCE_PLLCLK;


    RCC_ClkInitStruct.AHBCLKDivider     = RCC_SYSCLK_DIV1;


    RCC_ClkInitStruct.APB1CLKDivider    = RCC_HCLK_DIV2;


    RCC_ClkInitStruct.APB2CLKDivider    = RCC_HCLK_DIV1;




    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)


    {


        while(1);


    }


}


  • 17行:定义RCC_OscInitTypeDef结构体变量,该结构体主要是选择时钟源、设置时钟开关状态、PLL倍频;

  • 20行:设置时钟来源为内部高速时钟HSI;

  • 21行:不使用外部高速时钟,则HSE关闭;

  • 22行:设置HSE预分频,这里没用上HSE,默认为1分频即可;

  • 23行:内部高速时钟HSI打开;

  • 24行:锁相环PLL打开;

  • 25行:选择PLL时钟源,为HSI的二分频;

  • 26行:PLL的倍频为16倍频;

  • 27行:使用“HAL_RCC_OscConfig()”函数设置RCC_OscInitStruct;

  • 18行:定义RCC_ClkInitTypeDef结构体变量,该结构体主要是配置系统时钟、AHB、APB1、APB2的分频;

  • 34-35行:设置哪些时钟将被设置;

  • 36行:设置系统时钟SYSCLK的来源为PLLCLK;

  • 37行:设置HCLK时钟(AHB Clock)为1分频(不能超过最大72MHz);   

  • 38行:设置PCLK1时钟(APB1 Clock)为2分频(不能超过最大36MHz);

  • 39行:设置PCLK2时钟(APB2 Clock)为1分频(不能超过最大72MHz);

  • 41行:用“HAL_RCC_ClockConfig()”函数设置RCC_ClkInitStruct;不同的系统时钟需要设置不同的等待周期(LATENCY),这里设置为2,原因参考后面的“29.1 关于内部FLASH”读Flash部分,也可先跳过,不去深究;

将代码和时钟树进行对照,如图 9.3.1 所示,红色数字为对应代码行号,蓝色数字为时钟频率,红色线段为时钟走向。内部高速时钟HSI经过二分频为4MHz,再经过PLL 16倍频为64MHz,作为系统时钟SYSCLK,再1分频给AHB,AHB再2分频给APB1,1分频给APB2。

图 9.3.1 设置HSI和时钟树对照示意图



2) 获取系统时钟的函数


主函数里调用HAL库提供的“HAL_RCC_GetSysClockFreq()”函数获取系统时钟验证。


代码段 9.3.2 获取系统时钟(main.c)


// 此处定义全局变量以便在debug的时候可以看到这个变量的值


uint32_t sys_clk = 0;




int main(void)


{




    // 初始化HAL库函数必须要调用此函数


    HAL_Init();




    /*


     * 系统时钟即AHB/APB时钟配置


     * 当使用内部高速时钟HSI(8MHz)配置系统时钟时,使用PLL前会默认先二分频得到4MHz的PLL分频输入频率


     * 然后经过锁相环放大,最大放大倍数为16,即4*16=64MHz是能配置的最大系统频率,F103的最大系统频率为72MHz,64MHz显然是合法的系统频率


    */


    SystemClock_Config();




    // 调用库函数来检验自己的配置是否成功配置为系统频率64MHz


    sys_clk = HAL_RCC_GetSysClockFreq();


    while(1);


}



3) 使用外部时钟源HSE作为PLL的时钟源,然后将PLL作为系统时钟源


与前面类似,这里设置外部高速时钟HSE作为系统时钟,仍是设置两个结构体。


代码段 9.3.3 使用HSE作为系统时钟(stm32f1xx_clk.c)


/**


  * @brief  System Clock Configuration


  *         The system Clock is configured as follow :


  *            System Clock source            = PLL (HSE)


  *            SYSCLK(Hz)                     = 72000000


  *            HCLK(Hz)                       = 72000000


  *            AHB Prescaler                  = 1


  *            APB1 Prescaler                 = 2


  *            APB2 Prescaler                 = 1


  *            PLLMUL                         = 9


  *            Flash Latency(WS)              = 2


  * @param  None


  * @retval None


  */


void SystemClock_Config(void)


{


    RCC_OscInitTypeDef RCC_OscInitStruct = {0};


    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};




    RCC_OscInitStruct.OscillatorType    = RCC_OSCILLATORTYPE_HSE;


    RCC_OscInitStruct.HSEState          = RCC_HSE_ON;


    RCC_OscInitStruct.HSEPredivValue    = RCC_HSE_PREDIV_DIV1;


    RCC_OscInitStruct.HSIState          = RCC_HSI_OFF;


    RCC_OscInitStruct.PLL.PLLState      = RCC_PLL_ON;


    RCC_OscInitStruct.PLL.PLLSource     = RCC_PLLSOURCE_HSE;


    RCC_OscInitStruct.PLL.PLLMUL        = RCC_PLL_MUL9;


    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)


    {


        while(1);


    }




    /** Initializes the CPU, AHB and APB busses clocks


    */


    RCC_ClkInitStruct.ClockType         = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK


                                         | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;


    RCC_ClkInitStruct.SYSCLKSource      = RCC_SYSCLKSOURCE_PLLCLK;


    RCC_ClkInitStruct.AHBCLKDivider     = RCC_SYSCLK_DIV1;


    RCC_ClkInitStruct.APB1CLKDivider    = RCC_HCLK_DIV2;


    RCC_ClkInitStruct.APB2CLKDivider    = RCC_HCLK_DIV1;




    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)


    {


        while(1);


    }


}



  • 17行:定义RCC_OscInitTypeDef结构体变量,该结构体主要是选择时钟源、设置时钟开关状态、PLL倍频;

  • 20行:设置时钟来源为外部高速时钟HSE;

  • 21行:内部高速时钟HSE打开;

  • 22行:设置HSE预分频,设置为1分频;

  • 23行:不使用内部高速时钟,则HSI关闭;

  • 24行:锁相环PLL打开;

  • 25行:选择PLL时钟源,为HSE;

  • 26行:PLL的倍频为9倍频;

  • 27行:使用“HAL_RCC_ClockConfig()”函数设置RCC_OscInitStruct;

  • 18行:定义RCC_ClkInitTypeDef结构体变量,该结构体主要是配置系统时钟、AHB、APB1、APB2的分频;

  • 34-35行:设置哪些时钟将被设置;

  • 36行:设置系统时钟SYSCLK的来源为PLLCLK;

  • 37行:设置HCLK时钟(AHB Clock)为1分频(不能超过最大72MHz);

  • 38行:设置PCLK1时钟(APB1 Clock)为2分频(不能超过最大36MHz);

  • 39行:设置PCLK2时钟(APB2 Clock)为1分频(不能超过最大72MHz);

  • 41行:用“HAL_RCC_ClockConfig()”函数设置RCC_ClkInitStruct;

将代码和时钟树进行对照,如图 9.3.2 所示,红色数字为对应代码行号,蓝色数字为时钟频率,红色线段为时钟走向。外部高速时钟HSE不分频,通过选择器PLLXTPRE和选择器PLLRC,再PLL 9倍频为72MHz,作为系统时钟SYSCLK,再1分频给AHB,AHB再2分频给APB1,1分频给APB2。当前状态,为MCU全速工作状态。

图 9.3.2 设置HSE 和时钟树对照示意图


4) 获取系统时钟的函数

与前面类似,主函数里调用HAL库提供的“HAL_RCC_GetSysClockFreq()”函数获取系统时钟验证。

代码段 9.3.4 获取系统时钟(main.c)

[1] [2]
关键字:STM32  单片机  时钟系统 引用地址:【STM32单片机学习】第9章 基础重点—时钟系统

上一篇:什么是stm32单片机
下一篇:STM32驱动WS2812B

推荐阅读最新更新时间:2026-03-23 14:09

基于STM32单片机建立系统时钟的设计方案
这里必须阐明系统时钟的简历对于系统运行的重要性。系统所有的运行都是建立在时钟的正常运行上的,没有稳健的系统时钟,就不可能有稳定的系统。 在系统中,复位后首要的任务是建立系统时钟,以下是建立系统时钟的基本步骤: 1. 将所有的RCC外设寄存器重设为默认值; 2.启用外部高速晶振; 3.等待,知道外部高速晶振稳定; 4.设置欲取指缓存使能和代码延时值; 5.设置AHB(HCLK)等于系统时钟; 6.设置高速APB2(PCLK2)为系统时钟; 7.设置低速APB1(PCLK1)为系统时钟的1/2,APB2最高是38MHz; 8.设置PLL时钟源及倍频系数,使能PLL,经过PLL被频后最高时钟只能72MHz; 9.等待PLL初始化;
[单片机]
基于<font color='red'>STM32</font><font color='red'>单片机</font>建立<font color='red'>系统</font><font color='red'>时钟</font>的设计方案
STM32时钟系统的基础知识
01 时钟系统 1.1 时钟系统的作用 Stm32芯片中有大量的电路模块,时钟系统提供一个频率信号为电路模块提供统一的节拍,使电路模块能有序工作,最终达到控制电路的目的。 图1.1 晶振频率图 1.2 时钟周期的关系 时钟:为Stm32提供统一的节拍,形象的称时钟是单片机的心脏。 时钟周期:又名振荡周期,一个高低电平(0或1)所需要的时间。 指令周期:CPU从存储器中取出并执行一条指令所需的全部时间(取指、译码与执行三部分时间)。 机器周期:执行一个动作的时间周期,如取指令、存储器读、存储器写等,这每一项工作称为一个基本操作。完成一个基本操作所需要的时间称为机器周期。 图1.2 指令周期图 02 Stm32的时钟源 2.1
[单片机]
<font color='red'>STM32</font><font color='red'>时钟</font><font color='red'>系统</font>的基础知识
一文详解STM32时钟系统
STM32的时钟树 时钟信号推动单片机内各个部分执行相应的指令,时钟就像人的心跳一样。 STM32本身十分复杂,外设非常多,任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,如果都用高速时钟势必造成浪费。同一个电路,时钟越快功耗越大、抗电磁干扰能力越弱。复杂的MCU采用多时钟源的方法来解决这些问题。如下图,是STM32的时钟系统框图。 如上图左边的部分,看到STM32有4个独立时钟源,HSI、HSE、LSI、LSE。 HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。 HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 LSI是低速内部时钟,RC
[单片机]
一文详解<font color='red'>STM32</font>的<font color='red'>时钟</font><font color='red'>系统</font>
STM32的各种时钟系统的应用解析
时钟系统是处理器的核心,所以在学习STM32所有外设之前,认真学习时钟系统是必要的,有助于深入理解STM32。 重要的时钟: PLLCLK,SYSCLK,HCKL,PCLK1,PCLK2 之间的关系要弄清楚; 1、HSI:高速内部时钟信号 STM32单片机内带的时钟 (8M频率) 精度较差 2、HSE:高速外部时钟信号 精度高 来源(1)HSE外部晶体/陶瓷谐振器(晶振) (2)HSE用户外部时钟 3、LSE:低速外部晶体 32.768kHz 主要提供一个精确的时钟源 一般作为RTC时钟使用 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②
[单片机]
详解STM32时钟系统
STM32的时钟树 时钟信号推动单片机内各个部分执行相应的指令,时钟就像人的心跳一样。 STM32本身十分复杂,外设非常多,任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,如果都用高速时钟势必造成浪费。同一个电路,时钟越快功耗越大、抗电磁干扰能力越弱。复杂的MCU采用多时钟源的方法来解决这些问题。如下图,是STM32的时钟系统框图。 如上图左边的部分,看到STM32有4个独立时钟源,HSI、HSE、LSI、LSE。 HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。 HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 LSI是低速内部时钟,RC
[单片机]
STM32入门系列-STM32时钟系统STM32时钟
时钟对于单片机来说是非常重要的,它为单片机工作提供一个稳定的机器周期从而使系统能够正常运行。时钟系统犹如人的心脏,一旦有问题整个系统就崩溃。我们知道STM32属于高级单片机,其内部有很多的外设,但不是所有外设都使用同一时钟频率工作,比如内部看门狗和RTC,它只需30KHz的时钟频率即可工作,所以内部时钟源就有多种选择。在前面章节的介绍中,我们知道STM32系统复位后首先进入SystemInit函数进行时钟的设置,将STM32F1系统时钟设置为72MHz,然后进入主函数。那么这个系统时钟大小如何得来,其他外设的时钟又如何划分,可以通过一张时钟树图找到答案,只要理解好时钟树,STM32一切时钟的来龙去脉就会非常清楚。下面就来了解下时钟
[单片机]
STM32 系统时钟和SysTick定时器
1.STM32的时钟系统 在STM32中,一共有5个时钟源,分别是HSI、HSE、LSI、LSE、PLL (1)HSI是高速内部时钟,RC振荡器,频率为8MHz; (2)HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围是4MHz – 16MHz; (3)LSI是低速内部时钟,RC振荡器,频率为40KHz; (4)LSE是低速外部时钟,接频率为32.768KHz的石英晶体; (5)PLL为锁相环倍频输出,严格的来说并不算一个独立的时钟源,PLL的输入可以接HSI/2、HSE或者HSE/2。倍频可选择为2 – 16倍,但是其输出频率最大不得超过72MHz。 其中,40kHz的LSI供独
[单片机]
STM32 时钟系统
简介:时钟系统是 CPU 的脉搏,就像人的心跳一样。所以时钟系统的重要性就不言而喻了。STM32 的时钟系统比较复杂,不像简单的 51 单片机一个系统时钟就可以解决一切。于是有人要问,采用一个系统时钟不是很简单吗?为什么 STM32 要有多个时钟源呢? 因为首先STM32 本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率,比如看门狗以及 RTC 只需要几十 k 的时钟即可。 同一个电路,时钟越快功耗越大,同时抗电磁干扰能力也会越弱,所以对于较为复杂的MCU一般都是采取多时钟源的方法来解决这些问题。首先让我们来看看STM32的时钟系统图吧: 在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE
[单片机]
<font color='red'>STM32</font> <font color='red'>时钟</font><font color='red'>系统</font>
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved