学习记录:STM32F103 时钟系统概述工作原理

 

目录

        前言

        一、看如下时钟树我们能发现STM32有5个时钟源

       二、 STM32F103 时钟系统配置


        前言

        想要运用好一款单片机必须要知道微控制器原理性的东西,这样在对它进行应用的时候,才能得心应手明白它如何进行的工作。项目出问题时,也能在底层找到问题的源头和解决方案。STM32的时钟系统比51单片机的时钟系统要复杂很多,毕竟51单片机只有一个时钟系统。

        从STM32参考手册上,我了解到STM32F103MCU有三种不同的时钟源可被用来驱动系统时钟(SYSCLK): HSI振荡器时钟 、HSE振荡器时钟 、PLL时钟。当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。

所以能够知道, STM32采取多种时钟源是为了减少时钟的功耗,在数字电子技术中:同一个电路,时钟越快它消耗的功率就越大,并且抗电磁场的干扰能力也就越弱,脉冲越不稳定。

        一、看如下时钟树我们能发现STM32有5个时钟源

(参考正点原子的开发指南)

ⅰ、HSI 是高速内部时钟,RC 振荡器(在Multisim专栏里,对文氏桥电路进行了仿真,想详细了解可以去看一看),频率为 8MHz。

ⅱ、HSE 是高速外部时钟,可接石英/陶瓷谐振器(在Multisim专栏里,对石英晶体电路进行了仿真,想详细了解可以去看一看),或者接外部时钟源,频率范围为4MHz~16MHz。

ⅲ、LSI 是低速内部时钟,RC 振荡器,频率为 40kHz。独立看门狗的时钟源只能是 LSI,同 时 LSI 还可以作为 RTC 的时钟源。

ⅳ、LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体。这个主要是 RTC 的时钟源。

ⅴ、PLL 为锁相环倍频输出,其时钟输入源可选择为 HSI/2、HSE 或者 HSE/2。倍频可选择为 2~16 倍,但是其输出频率最大不得超过 72MHz。

时钟树

 ①、MCO 是 STM32 的一个时钟输出 IO(PA8),它可以选择一个时钟信号输出,可以选择为 PLL 输出的 2 分频、HSI、HSE或者系统时钟。这个时钟可以用来给外部其他系统提供时钟源。

②、 这里是 RTC 时钟源,从图上可以看出,RTC 的时钟源可以选择 LSI,LSE,以及 HSE 的 128 分频。

③、从图中可以看出 USB 的时钟是来自 PLL 时钟源。STM32 中有一个全速功能 的 USB 模块,其串行接口引擎需要一个频率为 48MHz 的时钟源。该时钟源只能从 PLL 输出端获取,可以选择为 1.5 分频或者 1 分频,也就是,当需要使用 USB 模块时,PLL 必须使能,并且时钟频率配置为 48MHz 或 72MHz。

④、 STM32 的系统时钟 SYSCLK,它是供 STM32 中绝大部分部件工作的时钟源。系统时钟可选择为 PLL 输出、HSI 或者 HSE。系统时钟最大频率为 72MHz, 当然你也可以超频,不过一般情况为了系统稳定性是没有必要冒风险去超频的。

⑤、是指其他所有外设了。从时钟图上可以看出,其他所有外设的时钟最终来源都是 SYSCLK。SYSCLK 通过 AHB 分频器分频后送给各模块使用。这些模块包括:

1、AHB 总线、内核、内存和 DMA 使用的 HCLK 时钟。

2、通过 8 分频后送给 Cortex 的系统定时器时钟,也就是 systick 。

3、直接送给 Cortex 的空闲运行时钟 FCLK。

4、送给 APB1 分频器。APB1 分频器输出一路供 APB1外设使用(PCLK1,最大频率 36MHz),另一路送给定时器(Timer)2、3、4 倍频器使用。

5、送给 APB2分频器。APB2分频器分频输出一路供 APB2 外设使用(PCLK2:最大频率 72MHz),另一路给定时器(Timer)1倍频器使用。

APB1 上面连接的是低速外设,包括电源接口、 备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等,APB2 上面连接的是高速外设包 括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。

       二、 STM32F103 时钟系统配置

(都是根据STM32的寄存器进行编程的)

typedef struct /*寄存器*/

{

  __IO uint32_t CR;                //HSI,HSE,CSS,PLL等的使能和就绪标志位

  __IO uint32_t CFGR;           //PLL等的时钟源选择,分频系数设定

  __IO uint32_t CIR;               // 清除/使能 时钟就绪中断

  __IO uint32_t APB2RSTR;  //APB2线上外设复位寄存器

  __IO uint32_t APB1RSTR;   //APB1线上外设复位寄存器

  __IO uint32_t AHBENR;    //DMASDIO等时钟使能

  __IO uint32_t APB2ENR;   //APB2线上外设时钟使能

  __IO uint32_t APB1ENR;   //APB1线上外设时钟使能

  __IO uint32_t BDCR;        //备份域控制寄存器

  __IO uint32_t CSR;           //控制状态寄存器

} RCC_TypeDef;

1.SystemInit 初始化程序:

void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001; //打开 HSION 位


  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   
  
  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;// 复位 HSEON, CSSON 和 PLLON 位


  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF; // 复位 HSEBYP 位


  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR &= (uint32_t)0xFF80FFFF;//复位 CFGR 寄存器


#ifdef STM32F10X_CL
  /* Reset PLL2ON and PLL3ON bits */
  RCC->CR &= (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  /* Configure the Flash Latency cycles and enable prefetch buffer */
  SetSysClock();

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

SystemInit 主要做了如下三个方面工作: 1) 复位 RCC 时钟配置为默认复位值(默认开始了 HIS) 2) 外部存储器配置 3) 中断向量表地址配置。

2.SetSysClockTo72

将系统时钟频率设置为 72MHz 并配置 HCLK、PCLK2和 PCLK1 预分频器。

初始化之前首先通过宏定义定义系统时钟频率:#define SYSCLK_FREQ_72MHz  72000000

初始化之后的状态:

     SYSCLK         72MHz

     AHB                72MHz

     PCLK1           36MHz

     PCLK2           72MHz

     PLL                72MHz

初始化之后可以通过变量SystemCoreClock获取系统变量。如果SYSCLK=72MHz,那么变量SystemCoreClock=72000000。

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;//HCLK2分频

#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 */
  }
}

SetSysClockTo72 将系统时钟频率设置为 72MHz 并配置 HCLK、PCLK2和 PCLK1 预分频器。

主要通过查询STM32中文参考手册,找到相应的寄存器,明白各个代码的作用。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Bitter tea seeds

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

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

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

打赏作者

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

抵扣说明:

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

余额充值