STM32_时钟树

文章目录

  • 一、RCC时钟
    • [   主要作用:](#   主要作用:)
    • [   时钟框图:](#   时钟框图:)
  • 二、时钟源
    • [   1、HSE高速外部时钟](#   1、HSE高速外部时钟)
    • [   2、HSI高速内部时钟](#   2、HSI高速内部时钟)
    • [   3、LSI低速内部时钟](#   3、LSI低速内部时钟)
    • [   4、LSE低速外部时钟](#   4、LSE低速外部时钟)
  • 三、系统时钟
    • [   1、HSE时钟源](#   1、HSE时钟源)
    • [   2、PLL时钟源](#   2、PLL时钟源)
    • [   3、PLL时钟PLLCLK](#   3、PLL时钟PLLCLK)
    • [   4、系统时钟SYSCLK](#   4、系统时钟SYSCLK)
    • [   5、AHB总线时钟HCLK](#   5、AHB总线时钟HCLK)
    • [   6、APB2总线时钟PCLK2](#   6、APB2总线时钟PCLK2)
    • [   7、APB1总线时钟PCLK1](#   7、APB1总线时钟PCLK1)
    • [   8、设置系统时钟库函数代码分析](#   8、设置系统时钟库函数代码分析)
  • 四、其它时钟
    • [   1、USB时钟](#   1、USB时钟)
    • [   2、Cortex系统时钟](#   2、Cortex系统时钟)
    • [   3、ADC时钟](#   3、ADC时钟)
    • [   4、RTC时钟](#   4、RTC时钟)
    • [   5、独立看门狗时钟](#   5、独立看门狗时钟)
    • [   6、MCO时钟输出](#   6、MCO时钟输出)
  • 五、配置系统时钟(编程)
    • [   0、编程要点:](#   0、编程要点:)
    • [   1、使用HSE](#   1、使用HSE)
    • [   2、使用HIS](#   2、使用HIS)
  • 六、使用MCO输出(编程)
    • [   1、MCO GPIO初始化](#   1、MCO GPIO初始化)
    • [   2、输出时钟选择](#   2、输出时钟选择)
  • 七、主函数参考(编程)

一、RCC时钟

RCC :reset clock control 复位和时钟控制器。

主要作用:

设置系统时钟 SYSCLK、设置 AHB 分频因子(决定 HCLK 等于多少)、设置 APB2 分频因子(决 定 PCLK2 等于多少)、设置 APB1 分频因子(决定 PCLK1 等于多少)、设置各个外设的分频因子;

控制 AHB、APB2 和 APB1 这三条总线时钟的开启、控制每个外设的时钟的开启。

对于 SYSCLK、 HCLK、PCLK2、PCLK1 这四个时钟的配置一般是:

PCLK2 = HCLK = SYSCLK=PLLCLK = 72M, PCLK1=HCLK/2 = 36M。

时钟框图:

二、时钟源

1、HSE高速外部时钟

HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。

使用HSE时钟:

使用HSE,然后HSE经过PLL倍频之后作为系统时钟。

通常的配置是:HSE=8M,PLL的倍频因子为:9, 系统时钟就设置成:SYSCLK = 8M * 9 = 72M。

2、HSI高速内部时钟

HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。

HSE故障时,系统会自动切换HSI作为系统时钟。SYSCLK=HSI=8M

3、LSI低速内部时钟

LSI是低速内部时钟,RC振荡器,频率为40kHz,提供低功耗时钟。

对低功耗要求较高,用于供给独立看门狗和自动唤醒单元使用。

4、LSE低速外部时钟

LSE是低速外部时钟,接频率为32.768kHz的石英晶体。

为RTC(实时时钟)来提供准确的时钟信号。

三、系统时钟

1、HSE时钟源

外接晶振:

晶振可使用4-16MHZ频率。

使用无源晶振:

时钟从OSC_IN和OSC_OUT进入,并且要配谐振电容。

使用有源晶振:

时钟从OSC_IN引脚进入,OSC_OUT引脚悬空。

HSE最常使用的就是8M的无源晶振。.

当确定PLL时钟来源的时候,HSE可以不分频或者2分频, 这个由时钟配置寄存器CFGR的位17:PLLXTPRE设置,我们设置为HSE不分频。

2、PLL时钟源

PLL时钟来源可以有两个,一个来自HSE,另外一个是HSI/2,具体用哪个由时钟配置寄存器CFGR的位16:PLLSRC设置。

HSI是内部高速的时钟信号,频率为8M,根据温度和环境的情况频率会有漂移,一般不作为PLL的时钟来源。

我们选HSE作为PLL的时钟来源。

3、PLL时钟PLLCLK

通过设置PLL的倍频因子,可以对PLL的时钟来源进行倍频,倍频因子可以是:

[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]。

具体设置成多少,由时钟配置寄存器CFGR的位21-18:PLLMUL[3:0]设置。

我们设置为9倍频,即时钟源为HSE=8M,PLLCLK = 8*9=72M。

4、系统时钟SYSCLK

系统时钟来源可以是:HSI、PLLCLK、HSE,具体的时钟配置寄存器CFGR的位1-0:SW[1:0]设置。

我们这里设置系统时钟:SYSCLK = PLLCLK = 72M。

5、AHB总线时钟HCLK

系统时钟SYSCLK经过AHB预分频器分频之后得到时钟叫APB总线时钟,即HCLK,分频因子可以是:

[1,2,4,8,16,64,128,256,512],

具体的由时钟配置寄存器CFGR的位7-4 :HPRE[3:0]设置。

我们设置为1分频,即HCLK=SYSCLK=72M。

6、APB2总线时钟PCLK2

APB2总线时钟PCLK2由HCLK经过高速APB2预分频器得到,分频因子可以是:

[1,2,4,8,16],

具体由时钟配置寄存器CFGR的位13-11:PPRE2[2:0]决定。

我们设置为1分频,即PCLK2 = HCLK = 72M。

7、APB1总线时钟PCLK1

APB1总线时钟PCLK1由HCLK经过低速APB预分频器得到,分频因子可以是:

[1,2,4,8,16],

具体的由时钟配置寄存器CFGR的位10-8:PRRE1[2:0]决定。

我们设置为2分频,即PCLK1 = HCLK/2 = 36M。

8、设置系统时钟库函数代码分析

c 复制代码
		static void SetSysClockTo72(void)
		{
		    __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
		
		    // ① 使能HSE,并等待HSE稳定
		    RCC->CR |= ((uint32_t)RCC_CR_HSEON);
		
		    // 等待HSE启动稳定,并做超时处理
		    do {
		        HSEStatus = RCC->CR & RCC_CR_HSERDY;
		        StartUpCounter++;
		    } while ((HSEStatus == 0)&&(StartUpCounter !=HSE_STARTUP_TIMEOUT));
		
		    if ((RCC->CR & RCC_CR_HSERDY) != RESET) {
		        HSEStatus = (uint32_t)0x01;
		    } else {
		        HSEStatus = (uint32_t)0x00;
		    }
		    // HSE启动成功,则继续往下处理
		    if (HSEStatus == (uint32_t)0x01) {
		
		        //-----------------------------------------------------------
		        // 使能FLASH 预存取缓冲区 */
		        FLASH->ACR |= FLASH_ACR_PRFTBE;
		
		        // SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
		        // 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
		        // 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
		        // 0:0 < SYSCLK <= 24M
		        // 1:24< SYSCLK <= 48M
		        // 2:48< SYSCLK <= 72M */
		        FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
		        FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
		        //------------------------------------------------------------
		
		        // ② 设置AHB、APB2、APB1预分频因子
		        // HCLK = SYSCLK
		        RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
		        //PCLK2 = HCLK
		        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
		        //PCLK1 = HCLK/2
		        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
		
		        // ③ 设置PLL时钟来源,设置PLL倍频因子,PLLCLK = HSE * 9 = 72 MHz
		        RCC->CFGR &= (uint32_t)((uint32_t)
		                                ~(RCC_CFGR_PLLSRC
		                                | RCC_CFGR_PLLXTPRE
		                                | RCC_CFGR_PLLMULL));
		        RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE
		                                | RCC_CFGR_PLLMULL9);
		
		        // ④ 使能 PLL
		        RCC->CR |= RCC_CR_PLLON;
		
		        // ⑤ 等待PLL稳定
		        while ((RCC->CR & RCC_CR_PLLRDY) == 0) {
		        }
		
		        // ⑥ 选择PLL作为系统时钟来源
		        RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
		        RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
		
		        // ⑦ 读取时钟切换状态位,确保PLLCLK被选为系统时钟
		        while ((RCC->CFGR&(uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){
		        }
		    } else {// 如果HSE启动失败,用户可以在这里添加错误代码出来
		    }
		}

四、其它时钟

1、USB时钟

USB时钟是由PLLCLK经过USB预分频器得到,分频因子可以是:

[1,1.5],

具体的由时钟配置寄存器CFGR的位22:USBPRE配置。

USB的时钟最高是48M。

2、Cortex系统时钟

Cortex系统时钟由HCLK 8分频得到,等于9M, Cortex系统时钟用来驱动内核的系统定时器SysTick,SysTick一般用于操作系统的时钟节拍,也可以用做普通的定时。

3、ADC时钟

ADC时钟由PCLK2经过ADC预分频器得到,分频因子可以是:

[2,4,6,8],

具体的由时钟配置寄存器CFGR的位15-14:ADCPRE[1:0]决定。

ADC时钟最高只能是14M。

4、RTC时钟

RTC时钟可由HSE/128分频得到,也可由低速外部时钟信号LSE提供,频率为32.768KHZ,也可由低速内部时钟信号LSI提供,

具体选用哪个时钟由备份域控制寄存器BDCR的位9-8:RTCSEL[1:0]配置。

5、独立看门狗时钟

独立看门狗的时钟由LSI提供, 且只能是由LSI提供,LSI是低速的内部时钟信号,频率为30~60KHZ直接不等,一般取40KHZ。

6、MCO时钟输出

MCO是microcontroller clock output的缩写,是微控制器时钟输出引脚。

在STM32 F1系列中 由 PA8复用所得, 主要作用是可以对外提供时钟,相当于一个有源晶振。

MCO的时钟来源可以是:PLLCLK/2、HSI、HSE、SYSCLK,

具体选哪个由时钟配置寄存器CFGR的位26-24:MCO[2:0]决定。

五、配置系统时钟(编程)

0、编程要点:

1、开启HSE/HSI ,并等待 HSE/HSI 稳定。

2、设置 AHB、APB2、APB1的预分频因子。

3、设置PLL的时钟来源,和PLL的倍频因子,设置各种频率主要就是在这里设置。

4、开启PLL,并等待PLL稳定。

5、把PLLCK切换为系统时钟SYSCLK。

6、读取时钟切换状态位,确保PLLCLK被选为系统时钟。

1、使用HSE

HSE作为系统时钟来源

c 复制代码
		void HSE_SetSysClock(uint32_t pllmul)
		{
		    __IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;
		
		    // 把RCC外设初始化成复位状态,这句是必须的
		    RCC_DeInit();
		
		    //使能HSE,开启外部晶振,野火STM32F103系列开发板用的是8M
		    RCC_HSEConfig(RCC_HSE_ON);
		
		    // 等待 HSE 启动稳定
		    HSEStartUpStatus = RCC_WaitForHSEStartUp();
		
		    // 只有 HSE 稳定之后则继续往下执行
		    if (HSEStartUpStatus == SUCCESS) {
		//-----------------------------------------------------------------//
		
		        // 使能FLASH 预存取缓冲区
		        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		
		        // SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
		        // 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
		        // 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
		        // 0:0 < SYSCLK <= 24M
		        // 1:24< SYSCLK <= 48M
		        // 2:48< SYSCLK <= 72M
		        FLASH_SetLatency(FLASH_Latency_2);
		//-----------------------------------------------------------------//
		
		        // AHB预分频因子设置为1分频,HCLK = SYSCLK
		        RCC_HCLKConfig(RCC_SYSCLK_Div1);
		
		        // APB2预分频因子设置为1分频,PCLK2 = HCLK
		        RCC_PCLK2Config(RCC_HCLK_Div1);
		
		        // APB1预分频因子设置为1分频,PCLK1 = HCLK/2
		        RCC_PCLK1Config(RCC_HCLK_Div2);
		
		//-----------------设置各种频率主要就是在这里设置-------------------//
		        // 设置PLL时钟来源为HSE,设置PLL倍频因子
		        // PLLCLK = 8MHz * pllmul
		        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);
		//-------------------------------------------------------------//
		
		        // 开启PLL
		        RCC_PLLCmd(ENABLE);
		
		        // 等待 PLL稳定
		        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
		        }
		
		        // 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
		        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		
		        // 读取时钟切换状态位,确保PLLCLK被选为系统时钟
		        while (RCC_GetSYSCLKSource() != 0x08) {
		        }
		    } else {
		        // 如果HSE开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
		        // 当HSE开启失败或者故障的时候,单片机会自动把HSI设置为系统时钟,
		        // HSI是内部的高速时钟,8MHZ
		        while (1) {
		        }
		    }
		}

2、使用HIS

使用HSI配置系统时钟

c 复制代码
		void HSI_SetSysClock(uint32_t pllmul)
		{
		    __IO uint32_t HSIStartUpStatus = 0;
		
		    // 把RCC外设初始化成复位状态,这句是必须的
		    RCC_DeInit();
		
		    //使能HSI
		    RCC_HSICmd(ENABLE);
		
		    // 等待 HSI 就绪
		    HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;
		
		    // 只有 HSI就绪之后则继续往下执行
		    if (HSIStartUpStatus == RCC_CR_HSIRDY) {
		    //-------------------------------------------------------------//
		
		        // 使能FLASH 预存取缓冲区
		        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		
		        // SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
		        // 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
		        // 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
		        // 0:0 < SYSCLK <= 24M
		        // 1:24< SYSCLK <= 48M
		        // 2:48< SYSCLK <= 72M
		        FLASH_SetLatency(FLASH_Latency_2);
		    //------------------------------------------------------------//
		
		        // AHB预分频因子设置为1分频,HCLK = SYSCLK
		        RCC_HCLKConfig(RCC_SYSCLK_Div1);
		
		        // APB2预分频因子设置为1分频,PCLK2 = HCLK
		        RCC_PCLK2Config(RCC_HCLK_Div1);
		
		        // APB1预分频因子设置为1分频,PCLK1 = HCLK/2
		        RCC_PCLK1Config(RCC_HCLK_Div2);
		
		        //-----------设置各种频率主要就是在这里设置-------------------//
		        // 设置PLL时钟来源为HSI,设置PLL倍频因子
		        // PLLCLK = 4MHz * pllmul
		        RCC_PLLConfig(RCC_PLLSource_HSI_Div2, pllmul);
		    //-- -----------------------------------------------------//
		
		        // 开启PLL
		        RCC_PLLCmd(ENABLE);
		
		        // 等待 PLL稳定
		        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
		        }
		
		        // 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
		        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		
		        // 读取时钟切换状态位,确保PLLCLK被选为系统时钟
		        while (RCC_GetSYSCLKSource() != 0x08) {
		        }
		    } else {
		        // 如果HSI开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
		        // 当HSE开启失败或者故障的时候,单片机会自动把HSI设置为系统时钟,
		        // HSI是内部的高速时钟,8MHZ
		        while (1) {
		        }
		    }
		}

六、使用MCO输出(编程)

MCO 引脚的时钟输出来验证我们的系统时钟配置是否正确。

1、MCO GPIO初始化

MCO GPIO初始化

c 复制代码
		/*
		* 初始化MCO引脚PA8
		* 在F103系列中MCO引脚只有一个,即PA8,在F4系列中,MCO引脚有两个
		*/
		void MCO_GPIO_Config(void)
		{
		    GPIO_InitTypeDef GPIO_InitStructure;
		    // 开启GPIOA的时钟
		    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
		
		    // 选择GPIO8引脚
		    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
		
		    //设置为复用功能推挽输出
		    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
		
		    //设置IO的翻转速率为50M
		    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		
		    // 初始化GPIOA8
		    GPIO_Init(GPIOA, &GPIO_InitStructure);
		}

2、输出时钟选择

c 复制代码
		// 设置MCO引脚输出时钟,用示波器即可在PA8测量到输出的时钟信号,
		// 我们可以把PLLCLK/2作为MCO引脚的时钟来检测系统时钟是否配置准确
		// MCO引脚输出可以是HSE,HSI,PLLCLK/2,SYSCLK
		//RCC_MCOConfig(RCC_MCO_HSE);
		//RCC_MCOConfig(RCC_MCO_HSI);
		//RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
		RCC_MCOConfig(RCC_MCO_SYSCLK);

七、主函数参考(编程)

主函数调用

c 复制代码
		int main(void)
		{
		    // 程序来到main函数之前,启动文件:statup_stm32f10x_hd.s已经调用
		    // SystemInit()函数把系统时钟初始化成72MHZ
		    // SystemInit()在system_stm32f10x.c中定义
		    // 如果用户想修改系统时钟,可自行编写程序修改
		
		    // 重新设置系统时钟,这时候可以选择使用HSE还是HSI
		
		    // 使用HSE时,SYSCLK = 8M * RCC_PLLMul_x, x:[2,3,...16],最高是128M
		    HSE_SetSysClock(RCC_PLLMul_9);
		
		    // 使用HSI时,SYSCLK = 4M * RCC_PLLMul_x, x:[2,3,...16],最高是64MH
		    //HSI_SetSysClock(RCC_PLLMul_16);
		
		    // MCO 引脚初始化
		    MCO_GPIO_Config();
		
		    // 设置MCO引脚输出时钟,用示波器即可在PA8测量到输出的时钟信号,
		    // 我们可以把PLLCLK/2作为MCO引脚的时钟来检测系统时钟是否配置准确
		    // MCO引脚输出可以是HSE,HSI,PLLCLK/2,SYSCLK
		    //RCC_MCOConfig(RCC_MCO_HSE);
		    //RCC_MCOConfig(RCC_MCO_HSI);
		    //RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
		    RCC_MCOConfig(RCC_MCO_SYSCLK);
		
		    // LED 端口初始化
		    LED_GPIO_Config();
		    while (1) {
		        LED1( ON );       // 亮
		        Delay(0x0FFFFF);
		        LED1( OFF );      // 灭
		        Delay(0x0FFFFF);
		    }
		}
相关推荐
lljss20202 小时前
ADC通道切换在GD32和PY32(STM32)区别
stm32·单片机·嵌入式硬件
森利威尔电子-2 小时前
5V到100V+通吃!森利威尔SL4008B升压芯片,电源设计的“万能钥匙”
嵌入式硬件·集成电路·芯片·电源芯片
SCBAiotAigc2 小时前
2026.3.7:具身智能之51单片机<二>:ISP烧录过程
c++·人工智能·单片机·嵌入式硬件·51单片机·c
一只黑鸟3 小时前
基于STM32的罐装水泥成分实时检测系统设计与实现(含有matlab仿真)
stm32·嵌入式硬件·算法·matlab·毕设
Saniffer_SH3 小时前
【高清视频】SerialTek PCIe 5.0/6.0 协议分析仪API自动化编程演示
网络·人工智能·驱动开发·嵌入式硬件·测试工具·自动化·压力测试
国科安芯3 小时前
抗辐照MCU在高空长航时无人机热管理系统中的可靠性研究
单片机·嵌入式硬件·架构·无人机·cocos2d·risc-v
从零点3 小时前
从 STM32 到 RK3588 再到电脑的深度对比
stm32·嵌入式硬件·电脑
炸膛坦客4 小时前
单片机/C语言八股:(八)指针函数 和 函数指针
c语言·单片机
CHANG_THE_WORLD4 小时前
glog3 捕获Windows异常崩溃信号
windows·stm32·单片机