STM32F10x时钟系统

请参考芯片的参考手册

简介

时钟是由电路产生的具有周期性的脉冲信号

  1. 在STM32中存在五个时钟源,分别是HSI(高速内部时钟),HSE(高速外部时钟),LSI(低速内部时钟),LSE(低速外部时钟),PLL(锁相环倍频)。分类如下所示:
    1. 根据时钟频率可以分为高速(High Speed)时钟源和低速时钟源。
      1. 高速时钟源:HSI,HSE,PLL
      2. 低速时钟源:LSI,LSE
    2. 根据来源可以划分为外部时钟源和内部时钟源
      1. 外部时钟源:LSE,HSE
      2. 内部时钟源:PLL,LSI,HSI
    3. 如下图所示:几个重要的时钟是SYSCLM(系统时钟),AHB总线时钟,APB1总线时钟(低速,速度最高36MHz),APB2总线时钟(高速,速度最高72MHz),PLL时钟
  2. HSI:由内置的RC振荡器产生,频率近似为8MHz,可直接作为系统时钟或在2分频后作为PLL输入
  3. HSE:可接晶体/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz
  4. LSI:由内置的RC振荡器产生,频率近似为40kHz。其可以在停机或者待机模式下保持运行
  5. LSE:接频率为32.768kHz的外部晶体或者陶瓷谐振器
  6. PLL:用来倍频HSI RC的输出时钟或HSE晶体输出时钟。
时钟配置相关的寄存器
  1. 时钟配置相关的寄存器如下所示:
    1. RCC_CR:时钟控制寄存器,HSI,HSE,CSS(时钟监视系统),PLL等的使能和就绪标志位
    2. RCC_CFGR:时钟配置寄存器,PLL等的时钟源选择,分频系数设定,微控制器时钟输出设定等
    3. RCC_CIR:时钟中断寄存器,清除/使能时钟就绪中断
    4. RCC_APB2RSTR:APB2外设复位寄存器,APB2线上外设复位寄存器
    5. RCC_APB1RSTR:APB1外设复位寄存器,APB1线上外设复位寄存器
    6. RCC_AHBENR:AHB时钟使能寄存器
    7. RCC_APB2ENR:APB2外设时钟使能寄存器
    8. RCC_APB1ENR:APB1外设时钟使能寄存器
    9. RCC_BDCR:备份域控制寄存器
    10. RCC_CSR:控制/状态寄存器
  2. 在MDK中定义如下:
typedef struct
{
  __IO uint32_t CR;
  __IO uint32_t CFGR;
  __IO uint32_t CIR;
  __IO uint32_t APB2RSTR;
  __IO uint32_t APB1RSTR;
  __IO uint32_t AHBENR;
  __IO uint32_t APB2ENR;
  __IO uint32_t APB1ENR;
  __IO uint32_t BDCR;
  __IO uint32_t CSR;
} RCC_TypeDef;
时钟配置相关的函数
  1. 时钟使能配置
  2. 时钟源相关配置
  3. 分频系数选择配置
  4. 外设时钟使能
  5. 其他外设时钟使能
  6. 状态参数获取
  7. RCC中断相关函数
SystemInit函数
  1. 这个函数很重要,在上一节中也讲到了在复位中断处理程序中会调用。 这个函数主要初始化了系统时钟的频率,HCLK时钟,PCLK2时钟,PCLK1时钟的预分频系数。核心代码如下所示:
#define SYSCLK_FREQ_72MHz  72000000
void SystemInit (void)
{
#ifdef SYSCLK_FREQ_72MHz
    __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    RCC->CR |= ((uint32_t)RCC_CR_HSEON);      // HSE振荡器(外部高速时钟)开启
    // 等待外部高速时钟就绪
    do
    {
        HSEStatus = RCC->CR & RCC_CR_HSERDY;    
        StartUpCounter++;  
    } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
    // 外部高速时钟已就绪
    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;  // 计算HCLK(高速AHB的时钟)时,系统时钟不分频
          
        /* PCLK2 = HCLK */
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1; // 计算PCLK2(高速APB的时钟)时,系统时钟不分频
        
        /* PCLK1 = HCLK / 2 */
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; // 计算PCLK1(低速APB的时钟)时,系统时钟二分频
        
        /*  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);
        
        /* Enable PLL */
        RCC->CR |= RCC_CR_PLLON;        // PLL时钟使能
    
        /* 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;     // 将PLL输出作为系统时钟  
    
        /* Wait till PLL is used as system clock source */
        while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
        {
        }
    }
#endif
}
  1. 经过这个函数初始化后,SYSCLK时钟为72MHz,AHB时钟为72MHz,APB1时钟为36MHz,APB2时钟为72MHz。