STM32-RCC时钟-时钟树介绍

本篇文章主要讲解STM32的时钟部分,解读时钟树。本片文章较长请耐心看完。那么你会了解对于STM32的一切时钟的来龙去脉。且本片文章大量的对照着STM32Fxx手册。请读者们提前下好手册的链接我放这了

STM32的手册STM32FXX手册  https://pan.baidu.com/s/1sk1_DSbL5ZV33I7zqzJEsg 
提取码:pyj1

目录

一、时钟树(系统时钟)

1、HSE(高速外部时钟信号)

 2、PLL时钟源

3、PLLCLK(锁相环时钟)

 4、SYSCLK(系统时钟)

 5、HCLK(AHB总线时钟)

6、HCLK1(APB1总线时钟)

7、HCLK2(APB2总线时钟)

二、时钟树(其他时钟)

1、USB时钟

 2、Cortex系统时钟

3、CSS(时钟安全系统)

 4、RTC时钟、独立看门狗时钟

 5、MCO时钟

6、ADC时钟


一、时钟树(系统时钟)

我们打开STM32的手册STM32FXX手册在手册56页找到我们的时钟树框图。

         时钟树中这么多东西我们该这么来看呢,这里我选取了一条主线,是固件库函数中的SetSysClockTo72 (),以这个函数的编写流程来展开,旁边的就在这条主线中分支介绍。既然是固件库函数可以看我前面的STM32固件库点亮LED这篇文章。我们在固件库中找到system_stm32f10x.这个文件在其中找到SetSysClockTo72这个函数。

 因为其中的注释是英文且其中配置时钟时也加入了别的类型时钟配置,我把它整理成我们需要的样子,和上面时钟树我画的流程图对应起来,代码如下

static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
      
  /*1.使能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;
  }  

  if (HSEStatus == (uint32_t)0x01)
  {
    /*使能Flash预存取缓冲区*/
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /*设置系统时钟周期与Flash访问的时间比例,统一设置成2*/
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

    /*2.设置AHB、APB1、APB2的预分频因子*/
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;  
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;


    /* 3.设置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);

    /* 4.使能PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* 5.等待PLL时钟被配置成功稳定运行 */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* 6.选择PLL作为系统时钟的来源 */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /*7.确定系统时钟来源已经被设置成PLLCLK*/
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /*如果HSE时钟启动失败,我们可以在这里添加错误代码*/
  }
}

1、HSE(高速外部时钟信号)

      HSE是高速外部时钟信号,由我们的外部时钟电路提供,可以是有源晶振或者是无源晶振提供,频率一般是8MHZ。使用无源晶振时钟从OSC_IN和OSC_OUT引脚进入,且必须搭配谐振电容来使用。我们可以操作RCC-CR寄存器的16(HSEON)位来使能HSE。因为晶振发生频率需要一定时间我们还得读取RCC-CR寄存器的17位(HSERDY)时钟是否已经准备就绪。

       既然有外部那么就有内部HSI(高速内部时钟信号)它提供的时钟信号是8MHZ且如果作为PLL时钟来源的话必定被2分频,我们可以操作RCC-CR寄存器的0位来使能HSI和读取RCC-CR寄存器的1位(HEIRDY)时钟是否以经准备就绪。HSE精度高我们一般使用它作为PLL的时钟来源。HSI的精度低且容易受到温度的影响一般只有HSE失效的时候我们才使用它。

       上面我们说了我们一般用HSE做为PLL时钟来源,这里这条时钟可以2分频或者不分频,由RCC-CFGR寄存器的17位 (PLLXTPRE)来设置。这里我们一般选择不分频。

 2、PLL时钟源

         这里可以返回到时钟树看到哪里了,建议对着时钟树看本片文章。上面说了PLL时钟的来HSE(高速外部时钟信号)或者HSI(高速内部时钟信号)具体用哪个我们可以操作RCC-CFGR寄存器16位(PLLSRC)。这里我在啰嗦一遍为什么选用HSE(高速外部时钟信号),因为HSI(高速内部时钟信号)根据温度和环境的情况频率会飘逸不稳定。

3、PLLCLK(锁相环时钟)

       这里可以设置PLL时钟的倍频因子,对PLL时钟来源进行倍频,可以是2~16倍,具体是多少可以通过RCC-CFGR寄存器21~18位(PLLMUL[3:0])来配置。ST公司官方推荐72MHZ,如果想超频的话自己也可以设置。

 4、SYSCLK(系统时钟)

       系统时钟的来源我们看时钟树就知道它的来源有三个可以是HSE、HSI、PLLCLK的其中一个具体是那个可以由RCC-CFGR寄存器的0~1(SW[1:0])来设置。

 5、HCLK(AHB总线时钟)

       SYSCLK(系统时钟)通过AHB预分频之后得到的时钟叫HCLK(AHB总线时钟),分频因子可以是1、2、4、8、16、128、256、512,具体由RCC-CFGR寄存器的4~7位(HPRE[3:0])来配置。片上外设的时钟都是经过HCLK分频得到的。

 HCLK(AHB总线时钟)出来时大部分片上外设的时钟来源SDIO、FSMC、DMA等外设。

6、HCLK1(APB1总线时钟)

HCLK1(APB1总线时钟)由HCLK经过低速APB1预分频得到,分频因子可以是1、2、4、8、16,具体是由RCC-CFGR寄存器8~10位(PPRE[2:0])决定。因为HCLK1属于低速的总线时钟,最高为36MHZ,片上低速的外设挂载在这条总线上如USART2/3/4/5、SPI2/3、I^{2}C1/2等。

7、HCLK2(APB2总线时钟)

 HCLK2(APB2总线时钟)由HCLK经过高速APB2预分频得到,分频因子可以是1、2、4、8、16,具体是由RCC-CFGR寄存器11~13位(PPRE2[2:0])决定。因为HCLK2属于高速的总线时钟,最高为72MHZ,片上高速的外设挂载在这条总线上如USART1、SPI1、GPIO等。

 介绍到这里整个系统时钟的介绍就完了,对照时钟树也差不多六七成,下面对其他时钟做个简单的介绍。

二、时钟树(其他时钟)

1、USB时钟

USB时钟是由PLLCLK(锁相环时钟)经过USB预分频器得到的,分频因子可以是1、1.5,具体可以由RCC-CFGR寄存器22位(USBPRE)配置。USB时钟对要求较高,所以PLLCLK(锁相环时钟)只能由HSE倍频得到,不能使用HSI倍频。

 2、Cortex系统时钟

Cortex系统时钟由HCLK8分频得到,Cortex系统时钟用来驱动内核的系统定时器SysTick。

3、CSS(时钟安全系统)

时钟安全系统可以通过软件被激活。一旦其被激活,时钟监测器将在HSE启动延迟后被 使能,并在HSE时钟关闭后关闭。 如果HSE时钟发生故障,HSE时钟被自动关闭,时钟失效事件将被送到高级定时器(TIM1和 TIM8)的刹车输入端,并产生时钟安全中断CSSI,允许软件完成营救操作(比如使用HSI)。此CSSI中断连接到 Cortex™-M3的NMI中断(不可屏蔽中断)。

注意: 一旦CSS被激活,并且HSE时钟出现故障,CSS中断就产生,并且NMI也自动产生。NMI将被不 断执行,直到CSS中断挂起位被清除。因此,在NMI的处理程序中必须通过设置时钟中断寄存器 (RCC_CIR)里的CSSC位来清除CSS中断。 如果HSE被直接或间接地作为系统时钟,(间接的意思是:它被作为PLL输入时钟,并且 PLL时钟被作为系统时钟),时钟故障将导致系统时钟自动切换到HSI振荡器,同时外部HSE时钟将被关闭。在时钟失效时,如果HSE时钟(被分频或未被分频)是用作系统时钟的PLL的输 入时钟,PLL也将被关闭。

 4、RTC时钟、独立看门狗时钟

RTC时钟可以由HSE/128分频或者由LSE(低速外部时钟信号)得到,HSI(高速内部时钟信号)也行,频率为32.768KHZ具体哪个时钟信号由RCC-BDCR寄存器的9~8位(RTCSEL[1:0])配置。独立看门狗时钟只能由LSI(低速内部时钟信号)提供,频率为30~60KHZ,一般取40KHZ。

 5、MCO时钟

MCO是Microcontroller Clock Output,是微控制器时钟输出引脚,主要作用是对外提供时钟,相当于一个有源晶振,时钟来源可以是PLLCLK/2(锁相环时钟)2分频、HSI(高速内部时钟信号)HSE(高速外部时钟信号)、SYSCLK(系统时钟),具体是哪个可以由RCC-CFGR寄存器26~24(MOC[2:0])来配置。除了对外部提供时钟信号外,我们还可以通过示波器监控MCO引脚的时钟输出来验证系统时钟配置是否正确。

6、ADC时钟

ADC时钟由PCLK2(APB2总线时钟)经过ADC预分频得到,分频因子可以是2、4、6、8,具体由RCC-CFGR寄存器的15~14位(ADCPRE[1:0])来配置。ADC时钟很奇怪最高14MHZ,我们逆推一下PCLK2的时钟只能是28MHZ、56MHZ、84MHZ、112MHZ。鉴于PCLK2时钟最高只有72MHZ,所以我们只能取28MHZ、56MHZ。

到这我们的时钟树已经全部介绍完毕,关注我后面我会更新STM32的所有特色外设

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>