STM32时钟树详解

RCC——复位时钟控制

时钟就相当于外设的心脏,如果没有时钟,外设就不能工作。

时钟源:HSI、HSE、PLL、LSE、LSI

HSI(High Speed Internal)

约等于8MHz,内置RC振荡器,可以作为系统时钟的选择。

请添加图片描述

由上图可以看出,HSI可以作为系统时钟的一个选择。

HSE(High Speed External)

请添加图片描述

高速外部时钟,由外部晶振产生,也可以作为系统时钟的时钟源,还可以作为PLL的输入

PLL

请添加图片描述

锁相环,是用来倍频的,可以将频率放大倍数 。
经过PLL产生了一个PLLCLK,这个时钟也可以作为系统时钟的时钟源。

以上就是系统时钟的全部来源。

请添加图片描述

在HSE旁边还有一个CSS——时钟监视系统,由于外部晶振存在不稳定性,一旦HSE失效,则自动切换至系统时钟为HSI

LSE(Low Speed External)

低速外部时钟,一般用来给RTC——实时时钟提供时钟信号

LSI(Low Speed internal)

低速内部时钟,主要用来给独立看门狗提供时钟信号

讲解系统时钟配置函数SetSysClockTo72()

请添加图片描述

请添加图片描述

请添加图片描述

请添加图片描述

在开发板系统初始化函数SystemInit()中,会对系统 时钟进行初始化,会调用SetSysClock()这个函数,而在SetSysClock()这个函数中,会将系统时钟设置为72M

static void SetSysClockTo72(void)//
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* 使能 HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 //由于HSE是无源晶振,这个晶振需要一段时间,我们通过RCC_CR寄存器中的HSERDY这个位是否置1来判断,HSE是否起振成功。
  /* 等待HSE就绪并做超时处理 */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
//如果HSE启动成功,程序继续执行
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    //使能预取指
    FLASH->ACR |= FLASH_ACR_PRFTBE;
	//配置两个等待状态,在闪存编程手册中,对这两个配置由详细的讲解。
    //不同的时钟周期所需配置的等待状态是不同的。
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    
      
	//下面配置AHB、APB1、APB2总线的时钟分频因子,具体理解过程请参考图7
    //三个时钟分频因子的配置位置请参考图8
      
    /* HCLK = SYSCLK = 72M */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK = 72M */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK = 36M */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

	//锁相环配置
    /*  PLL configuration: 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)
    {
    }
    
    /* 选择PLLCLK作为系统时钟 */
    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启动失败,用户可以在这里添加处理错误代码
  { 
         
  }
}

使用HSE配置系统时钟并使用MCO输出监控系统时钟

void HSE_SetSysClk(){
    ErrorStatus HSEStatus;
    
    //把RCC寄存器复位到复位值
    RCC_DeInit();
   
    //使能HSE
    RCC_HSEConfig(RCC_HSE_ON);
    //获取HSE启动成功状态位
    HSEStatus = RCC_WaitForHSEStartUp();
    if(HSEStatus == SUCCESS){
        //HSE启动成功
        //使能预取指
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        //设置FLASH等待周期
        FLASH_SetLatency(FLASH_Latency_2);
        //系统时钟一分频
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        RCC_PCLK1Config(RCC_HCLK_Div2);
        RCC_PCLK2Config(RCC_HCLK_Div1);
        //配置PLLCLK=HSE*x
        RCC_PLLConfig(RCC_PLLSource_HSE_Div, RCC_PLLMul_x);
        //使能PLL
        RCC_PLLCmd(ENABLE);
        
        //等待PLL稳定
        while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
        //选择系统时钟
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        while(RCC_GetSYSCLKSouce()!=0x08);
        
    }else{
        
    }
}

欢迎关注微信公众号:计算机达人

请添加图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamerForLife

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值