STM32 时钟系统详解

1. 复位

STM32F10xxx支持三种复位模式,分别是:系统复位、上电复位、备份区域复位。

1.1 系统复位

请查阅参考手册

1.2 上电复位

请查阅参考手册

1.3 备份区域复位

请查阅参考手册

2. 时钟树

image-20220516222009325

2.1 HSE时钟

High Speed External Clock signal,高速的外部时钟,一般来自无源晶振(4-16MHz),通常使用8MHz,利用RCC_CR时钟控制寄存器的位16:HSEON控制。通过PLL倍频至72MHz使用。

image-20220516224106202

2.2 HSI时钟

Low Speed Internal Clock signal,高速的内部时钟,内部8MHz时钟,精度较小,受温度影响较大。当HSE故障时,系统时钟会自动切换到HSI,直到HSE启动成功,利用RCC_CR时钟控制寄存器的位0:HSION控制。

image-20220516224050714

2.3 锁相环时钟 PLLCLK

经过HSI/2、HSE倍频所得,利用CFGR寄存器的:PLLXTPRE、PLLMUL控制,

注意:PLL时钟源头使用HSI/2时,PLLMUL最大只能是16,这时PLLCLK最大只有64MHz,小于ST官方推荐的最大时钟72MHz。

image-20220516224020514

2.4 系统时钟 SYSCLK

锁相环时钟最高为72MHz,来源有HSI、HSE、PLLCLK,通过CFGR寄存器的SW为控制。注意:通常的配置是SYSCLK=PLLCLK=72MHz。

image-20220516224657159

2.5 AHB总线时钟 HCLK

Advanced High-performance Bus,来自系统时钟的分频,一般设置为HCLK=SYSCLK=72MHz。通过CFGR的HPRE控制。AHB高速总线时钟,速度最高为72MHz,为AHB总线外设提供时钟、为Cortex系统定时器提供时钟(SysTick)、为内核提供时钟(FCLK)。

image-20220516225236455

2.6 APB1总线时钟 PCLK1

APB1低速总线时钟,最高36MHz,为APB1总线的外设提供时钟,2倍频之后则为APB1总线的定时器2-7提供时钟,最大为72MHz。经过HCLK分频获得,一般配置为PCLK1=HCLK/2=36MHz,通过RCC_CFGR寄存器的PPRE1位控制。

image-20220516225637755

2.7 APB2总线时钟 PCLK2

APB2高速总线时钟,最高72MHz,为APB2总线的外设提供时钟,2倍频之后则为APB2总线的定时器1和8提供时钟,最大为72MHz。经过HCLK分频获得,一般配置为PCLK1=HCLK=72MHz,通过RCC_CFGR寄存器的PPRE2位控制。

image-20220516225925628

2.8 RTC时钟 (实时时钟)

为芯片内部的RTC外设提供时钟,一般来自HSE_RTC(HSE分频得到)、LSE(外部32.768KHz的晶体提供)、LSI(32KHz),通过RCC备份域控制寄存器RCC_BDCR的RTCSEL位控制。

独立看门狗时钟:IWDGCLK,由LSI提供

image-20220516230730615

2.9 MCO时钟输出

microcontroller clock output,微控制器时钟输出引脚,由GPIO_PA8复用所得。来自PLLCLK/2、HSE、HSI、SYSCLK,通过CFGR的MCO位控制。

image-20220516230835012

2.10 时钟安全系统 (CSS)

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

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

3. 时钟配置

参考手册image-20220516232638518

中相关寄存器进行时钟配置,

3.1 相关寄存器描述

时钟配置寄存器在STM32上的基地址为:0x40021000

3.1.1 时钟控制寄存器 (RCC_CR)

image-20220516234020481

image-20220516234042925

3.1.2 时钟配置寄存器(RCC_CFGR)

image-20220516234102145

image-20220516234255192

image-20220516234310668

image-20220516234339566

3.1.3 时钟中断寄存器(RCC_CIR)

image-20220516234355034

image-20220516234429258

image-20220516234451197

image-20220516234508566

3.1.4 APB2外设复位寄存器(RCC_APB2RSTR)

image-20220516235156384

image-20220516235136058

image-20220516235101722

3.1.5 APB1外设复位寄存器(RCC_APB1RSTR)

image-20220516235043732

image-20220516235027333

image-20220516235007314

3.1.6 AHB外设时钟使能寄存器(RCC_AHBENR)

image-20220516234948804

image-20220516234933082

3.1.7 APB2外设时钟使能寄存器(RCC_APB2ENR)

image-20220516234916010

image-20220516234858262

3.1.8 APB1外设时钟使能寄存器(RCC_APB1ENR)

image-20220516234738079

image-20220516234805996

image-20220516234835839

3.1.9 备份域控制寄存器 (RCC_BDCR)

image-20220516234651318

image-20220516234708579

3.1.10 控制/状态寄存器(RCC_CSR)

image-20220516234608143

image-20220516234628458

3.1.11 闪存访问控制寄存器 FLASH_ACR

image-20220516233834396

image-20220516233928682

3.2 配置例程代码

// 固件库时钟配置例程如下
static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  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)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 2 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

 
    /* 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;

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL9); 
#else    
    /*  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);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* Select PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  }
}

__IO 表示防止编译器优化,使每次读取都去寄存器去读取。

image-20220517224555085

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

XYJ_Tiger

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

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

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

打赏作者

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

抵扣说明:

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

余额充值