stm32------系统时钟配置

Posted xugdawn666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32------系统时钟配置相关的知识,希望对你有一定的参考价值。

一、概述

  系统时钟,是整个芯片的心脏,如果没有了它,就等于人没有了心跳;
  在实际工程应用中,每当使用一个外设时,首先需要做的就是打开该外设对应的时钟;这样的好处就是,如果不使用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗,达到节能,实现低功耗的效果(低功耗); 
  寄存器是由D触发器组成的,只有送来了时钟,触发器才能被改写值。任何MCU的任何外设都需要有时钟,8051也是如此;STM32为了让用户更好地掌握功耗,对每个外设的时钟都设置了开关,让用户可以精确地控制,
  关闭不需要的设备,达到节省供电的目的。51单片机不用配置IO时钟,只是因为默认使用同一个时钟,这样是方便,但是这样的话功耗就降低不了。51中某个功能不需要,
  但是它还是一直运行。stm32中当你想关闭某个IO的时候,关闭它相对应的时钟使能就是了;ARM的芯片都是这样,外设通常都是给了时钟后,才能设置它的寄存器(即才能使用这个外设),
  这么做的目的是为了省电,使用了所谓时钟门控的技术。

 

二、关于时钟

  1.时钟分类(stm32所有型号的时钟分为4类)

  ①、HSI 是高速内部时钟(High Speed Internal Clock Signal)
  ②、HSE是高速外部时钟(High Speed External Clock Signal)
  ③、LSI 是低速内部时钟(Low  Speed Internal Clock Signal)
  ④、LSE是低速外部时钟(Low  Speed External Clock Signal)

 

  2.时钟源(stm32) 

  ①、HSI内部高速时钟,RC振荡器,频率为8MHz,当HSE故障时,系统时钟会自动切换到HSI,直到HSE启动成功,相对HSE精度小,受温度影响较大,会有温漂。
  ②、HSE外部高速时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz,多使用8MHz/12MHz。
  ③、PLL锁相环倍频时钟,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。

  STM32具有以下两个次级时钟源:

  ①、LSI内部低速时钟,RC振荡器,频率为30~60kHz不等,一般取40kHz,该 RC 用于驱动独立看门狗,也可选择提供给 RTC 用于停机/待机模式下的自动唤醒。
  ②、LSE外部低速时钟,接频率为32.768kHz的石英晶体,主要做RTC时钟源;
  (使用32.768kHz是因为2的15次方为32768,32.768kHz的晶振产生的时钟信号经过15次分频后,便会产生频率为1Hz的信号,即为秒脉冲信号

  

  3.时钟树(stm32)

  

  注:
  1)对于不同系列的芯片,时钟树之间会存在或大或小的差异,具体需要查看手册中RCC的章节;
  2)MCO接口的两个作用:其一,可以观察波形是否正常;其二,可以作为其他部件的时钟;

 

三、实验分析

  keil软件版本:V5.35.00
  st官网:STM32 固件 - 意法半导体STMicroelectronics
  单片机型号:STM32F103VET6
  1、标准库中配置系统时钟分析
  1)系统时钟配置的相关代码在这里哦

  

  

  

  2)配置详情及描述(stm32)  

  
 /**
   * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2 
   *         and PCLK1 prescalers. 
   * @note   This function should be used only after reset.
   * @param  None
   * @retval None
   */
 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);                            //使能HSE,等待HSE稳定
  
   /* Wait till HSE is ready and if Time out is reached exit */
   do                                                            //等待HSE启动稳定,并做超时处理
   
     HSEStatus = RCC->CR & RCC_CR_HSERDY;
     StartUpCounter++;  
    while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
 
   if ((RCC->CR & RCC_CR_HSERDY) != RESET)                        //判断HSE启动是否成功,置位标志位
   
     HSEStatus = (uint32_t)0x01;
   
   else
   
     HSEStatus = (uint32_t)0x00;
     
 
   if (HSEStatus == (uint32_t)0x01)                                //如果HSE启动成功
   
     /* Enable Prefetch Buffer */
     FLASH->ACR |= FLASH_ACR_PRFTBE;                                //使能FLASH预存取缓冲区
 
     /* Flash 2 wait state */                                    //SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2
     FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);        //设置成 2 的时候, SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
     FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;                //如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
                                                                 //0: 0 < SYSCLK <= 24M
                                                                 //1: 24< SYSCLK <= 48M
                                                                 //2: 48< SYSCLK <= 72M
  
                                                                 //设置AHB、APB2、APB1预分频因子
     /* HCLK = SYSCLK */
     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
       
     /* PCLK2 = HCLK */
     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
     
     /* PCLK1 = HCLK/2 */
     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         //设置PLL时钟来源,设置PLL倍频因子,PLLCLK = HSE * 9 = 72MHz
     
                                         | 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;                                    //使能PLL
 
     /* Wait till PLL is ready */
     while((RCC->CR & RCC_CR_PLLRDY) == 0)                        //等待PLL稳定
     
     
     
     /* Select PLL as system clock source */
     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));            //选择PLL作为系统时钟来源
     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    
 
     /* Wait till PLL is used as system clock source */            //读取时钟切换状态位,确保PLLCLK被选为系统时钟
     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
     
     
   
   else                                                            //如果HSE启动失败,可以在这里添加错误代码
    /* If HSE fails to start-up, the application will have wrong clock 
          configuration. User can add here some code to deal with this error */
   
 
system_stm32f10x.c

  3)另外补充一个例子(gd32)

  
 /*!
     \\brief      configure the system clock to 72M by PLL which selects HXTAL as its clock source
     \\param[in]  none
     \\param[out] none
     \\retval     none
 */
 static void system_clock_72m_hxtal(void)
 
     uint32_t timeout = 0U;
     uint32_t stab_flag = 0U;
 
     /* enable HXTAL */
     /*开启外部高速时钟*/
     RCU_CTL0 |= RCU_CTL0_HXTALEN;
 
     /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
     /*等待外部高速时钟稳定,(当外部晶振稳定后,芯片将自动设置相关标志位,软件只需要不断读取这个标志位就可以知道时钟是否稳定)*/
     do 
         timeout++;
         stab_flag = (RCU_CTL0 & RCU_CTL0_HXTALSTB);
      while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
     /* if fail 若外部高速时钟异常,上面等待超时,进入这里*/
     if(0U == (RCU_CTL0 & RCU_CTL0_HXTALSTB)) 
         return;
     
     
     
     /*运行到这里,说明外部高速时钟正常启动,下面按照时钟树,来配置系统和各个模块的时钟*/
     /* HXTAL is stable */
     /* AHB = SYSCLK */
     RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;        //系统时钟到AHB总线时钟不进行分频
     /* APB2 = AHB/2 */
     RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;    //APB2是AHB的2分频
     /* APB1 = AHB/2 */
     RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;    //APB1是AHB的2分频
     
 
     /* PLL = HXTAL * 6 = 72 MHz */
     /*现在外部晶振是12M,通过PLL倍频为72M*/
     RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF | RCU_CFG0_PLLMF4 | RCU_CFG0_PLLPREDV);
     RCU_CFG1 &= ~(RCU_CFG1_PLLPRESEL | RCU_CFG1_PLLMF5 | RCU_CFG1_PREDV);
     
     RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | (RCU_PLL_MUL6 & (~RCU_CFG1_PLLMF5)));        //PLLSEL设置为1,PLL设置为6
 //    RCU_CFG0 |= (RCU_CFG0_PLLPREDV);                        //HXTAL或CK_IRC48M时钟二分频    (CFG0第17位,与CFG1中的PREDV[0]位是一样的)
     RCU_CFG1 |= (RCU_PLLPRESEL_HXTAL);                        //HXTAL选为PLL时钟源         PREDV 选择1分频
     RCU_CFG1 |= (RCU_PLL_MUL6 & RCU_CFG1_PLLMF5);            //PLLMF的第五位设置为0
     
     
     /* enable PLL */
     /*上面的配置完成,使能PLL*/
     RCU_CTL0 |= RCU_CTL0_PLLEN;
 
     /* wait until PLL is stable */
     while(0U == (RCU_CTL0 & RCU_CTL0_PLLSTB)) 
     
 
     /* select PLL as system clock */
     /*设置SCS[1:0],将时钟切换到刚配置好的PLL这条系统时钟线路*/
     RCU_CFG0 &= ~RCU_CFG0_SCS;
     RCU_CFG0 |= RCU_CKSYSSRC_PLL;
 
     /* wait until PLL is selected as system clock */
     /*等待PLL这条系统时钟配置能稳定给系统提供时钟*/
     while(0U == (RCU_CFG0 & RCU_SCSS_PLL)) 
     
     
     /*到此处,系统完成了从8M到200M的切换*/
 
system_gd32f3x0.c

 

  2、重新定义并初始化函数

  由上文代码可知,程序运行起来会首先执行启动文件,调用systeminit()函数,最终初始化系统时钟;
  如需改变时钟配置,可以在系统时钟配置文件中修改;但是为了不破坏库函数的完整性,可重新定义并调用初始化函数;
  一般情况下,使用HSE经分频倍频后来配置系统时钟;
  1)以HSE配置系统时钟为例,按照时钟树流程来完成函数: 
   
 /**
   * @brief  HSE_SetSysClk program.
   * @param  RCC_PLLMul_x: specifies the PLL multiplication factor[2~16]
   * @retval None
   */
 void HSE_SetSysClk(uint32_t RCC_PLLMul_x)
 
     ErrorStatus HSEStatus;
     
     
     RCC_DeInit();                                //把RCC寄存器复位
     
     RCC_HSEConfig(RCC_HSE_ON);                    //使能HSE
     
     HSEStatus = RCC_WaitForHSEStartUp();        //等待HSE稳定,返回HSE状态
     
     if(HSEStatus == SUCCESS)
     
         /*预取缓冲器包含两个数据块,每个数据块有8个字节; 预取指令(数据)块直接映像到闪存中,
           因为数据块的大小与闪存的宽度相同, 所以读取预取指令块可以在一个读周期完成;
           设置预取缓冲器可以使CPU更快地执行, CPU读取一个字的同时下一个字已经在预取缓冲器中等候,
           即当代码跳转的边界为8字节的倍数时, 闪存的加速比例为2;
           flash等待周期数要系统时钟频率对应, 《stm32f10xxx闪存编程手册》中可以进行了解 */
         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);    //使能预取指
         FLASH_SetLatency(FLASH_Latency_2);                        //2个等待周期
         
         RCC_HCLKConfig(RCC_SYSCLK_Div1);                        //配置AHB总线时钟HCLK
         RCC_PCLK1Config(RCC_HCLK_Div2);                            //配置APB1总线时钟PCLK1,PCLK1 = HCLK/2
         RCC_PCLK2Config(RCC_HCLK_Div1);                            //配置APB2总线时钟PCLK2,PCLK2 = HCLK
         
         RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_x);        //配置锁相环时钟(PLLCLK = HSE * RCC_PLLMul_x = 72MHz),RCC_PLLMul_x为倍频因子,PLL需要先配置再使能
         RCC_PLLCmd(ENABLE);                                        //使能PLL
         while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLLRDY));        //等待PLL稳定
         
         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                //选择PLLCLK为系统时钟    
         while(0x08 != RCC_GetSYSCLKSource());                    //等待PLLCLK置位系统时钟完成
     
     else
     
         /*如果HSE启动失败,可以在这里添加处理错误的代码*/
     
 
 
 /*在main中调用即可*/
 /**
   * @brief  Main program.
   * @param  None
   * @retval None
   */
 int main(void)
 
     LED_GPIO_Config();
     HSE_SetSysClk(RCC_PLLMul_9);
 //    HSI_SetSysClk(RCC_PLLMul_16);
     MCO_GPIO_Config();
     RCC_MCOConfig(RCC_MCO_SYSCLK);
     
     for(;;)
     
         LED1_TOGGLE;
         Delay(0xFFFFF);
         LED1_TOGGLE;
             Delay(0xFFFFF);
     
 
rcc_clk_config_operation.c
  使能MCO,使用示波器抓取波形
    
 /**
   * @brief  MCO_GPIO_Config program.
   * @param  void
   * @retval enable mco for see clock
   */
 void MCO_GPIO_Config()
 
     GPIO_InitTypeDef  GPIO_InitStructure;
 
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
     
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     
     GPIO_Init(GPIOA,&GPIO_InitStructure);
 
 
 
 
     RCC_MCOConfig(RCC_MCO_SYSCLK);
mco_gpio_config.c
  波形如下:(使用HSE 8*9 = 72MHz; 使用HSE(超频) 8*16 = 128MHz)

    

  2)以HSI作为系统时钟

   
 /**
   * @brief  HSI_SetSysClk program.
   * @param  RCC_PLLMul_x: specifies the PLL multiplication factor[2~16]
   * @retval None
   */
 void HSI_SetSysClk(uint32_t RCC_PLLMul_x)
 
     __IO uint32_t HSIStatus = 0;                //加 __IO 防止编译器优化
     
 
     RCC_DeInit();                                //把RCC寄存器复位
 
 //    RCC_HSICmd(ENABLE);                            //使能HSI,复位时候已经使能了HSI,这里可以不再使能
     
     HSIStatus = RCC->CR & RCC_CR_HSIRDY;        //等待HSI稳定,读取hsirdy寄存器
     
     if(HSIStatus == RCC_CR_HSIRDY)
     
         /*预取缓冲器包含两个数据块,每个数据块有8个字节; 预取指令(数据)块直接映像到闪存中,
           因为数据块的大小与闪存的宽度相同, 所以读取预取指令块可以在一个读周期完成;
           设置预取缓冲器可以使CPU更快地执行, CPU读取一个字的同时下一个字已经在预取缓冲器中等候,
           即当代码跳转的边界为8字节的倍数时, 闪存的加速比例为2;
           flash等待周期数要系统时钟频率对应, 《stm32f10xxx闪存编程手册》中可以进行了解 */
         FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);    //使能预取指
         FLASH_SetLatency(FLASH_Latency_2);                        //2个等待周期
         
         RCC_HCLKConfig(RCC_SYSCLK_Div1);                        //配置AHB总线时钟HCLK
         RCC_PCLK1Config(RCC_HCLK_Div2);                            //配置APB1总线时钟PCLK1,PCLK1 = HCLK/2
         RCC_PCLK2Config(RCC_HCLK_Div1);                            //配置APB2总线时钟PCLK2,PCLK2 = HCLK
         
         RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x);    //配置锁相环时钟(PLLCLK = HSI * RCC_PLLMul_x = 64MHz),RCC_PLLMul_x为倍频因子,PLL需要先配置再使能
         RCC_PLLCmd(ENABLE);                                        //使能PLL
         while(RESET == RCC_GetFlagStatus(RCC_FLAG_PLLRDY));        //等待PLL稳定
         
         RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);                //选择PLLCLK为系统时钟    
         while(0x08 != RCC_GetSYSCLKSource());                    //等待PLLCLK置位系统时钟完成
     
     else
     
         /*如果HSI启动失败,可以在这里添加处理错误的代码*/
     
 
rcc_clk_config_operation_hsi.c
  波形如下:(使用HSI 8/2 * 16 = 64MHz; 使用HSI  8/2*8 = 32MHz)

    

 

四、总结

  系统时钟配置需要根据具体的时钟框图,先设置好时钟源,AHB、APB1、APB2的分频系数;再设置好PLL倍频和分频;最后使用SW切换选择系统时钟来源即可。

 

参考:

           1、《STM32F10X-中文参考手册》
           2、[野火EmbedFire]《STM32库开发实战指南——基于野火指南者开发板》;
   3、野火F103-指南者bilibili教程视频【150集-野火F103霸道/指南者视频教程】-中级篇_哔哩哔哩_bilibili
   4、32系统时钟配置 - Darren_pty - 博客园 (cnblogs.com)
   5、STM32F4_RCC系统时钟配置及描述 - strongerHuang - 博客园 (cnblogs.com)
           6、STM32F2系列系统时钟默认配置 - MyBooks - 博客园 (cnblogs.com)
           7、STM32入门系列-STM32时钟系统,时钟使能配置函数 - STM32嵌入式开发 - 博客园 (cnblogs.com)

 

小弟才疏学浅,如有错误或不足之处,还请大佬批评指正,深表感谢!

STM32F4_RCC系统时钟配置及描述

、概述

对于系统时钟应该都知道它的作用,就是驱动整个芯片工作的心脏,如果没有了它,就等于人没有了心跳。

对于使用开发板学习的朋友来说,RCC系统时钟这一块知识估计没怎么去配置过,原因在于开发板提供的晶振基本上都是官方标准的时钟频率,使用官方的标准库,这样系统时钟就是默认的配置,也就是默认的频率。但对于自己设计开发板,或者想要改变系统时钟频率(如:降低功耗就需要降频)的朋友来说,配置系统时钟就有必要了。

关于时钟这一块对定时器(TIM、RTC、WDG等)相关的外设也比较重要,因为要求精准,就需要时钟频率精准。

该文将描述关于系统时钟配置及注意的相关事项,更多详情内容,请往下看。

 

本着免费分享的原则,方便大家手机学习知识,定期在微信平台分享技术知识。如果你觉得分享的内容对你有用,又想了解更多相关的文章,请用微信搜索“EmbeddDeveloper” 或者扫描下面二维码、关注,将有更多精彩内容等着你。

 

 

Ⅱ、关于时钟

1.时钟分类

STM32芯片(所有型号)的时钟包含4类:

HSE(High Speed External)高速外部时钟

HSI(High Speed Internal)高速内部时钟

LSE(Low  Speed External)低速外部时钟

LSI(Low  Speed Internal)低速内部时钟

 

2.时钟源

STM32芯片(所有型号)驱动系统时钟的时钟源:

HSI 内部高速时钟

HSE 外部高速时钟

PLLCLK倍频时钟

 

STM32具有以下两个次级时钟源:

32 kHz 低速内部 RC (LSI RC),该 RC 用于驱动独立看门狗,也可选择提供给 RTC 用于停机/待机模式下的自动唤醒。

32.768 kHz 低速外部晶振( LSE 晶振),用于驱动 RTC 时钟 (RTCCLK)。对于每个时钟源来说,在未使用时都可单独打开或者关闭,以降低功耗。

 

3.时钟树(框图)

关于STM32的时钟树针对不同系列芯片可能存在差异。F0、F1和F3系列芯片(主流芯片,频率相对较低)有很多相似的地方,F2和F4(高性能芯片)系列芯片有很多相似的地方。但是,F3芯片和F4芯片的时钟树之间却存在很大差异,具体请看参考手册RCC相关章节。

STM32时钟控制器为应用带来了高度的灵活性,用户在运行内核和外设时可选择使用外部晶振或者使用振荡器,既可采用最高的频率,也可为以太网、 USB OTG FS 以及 HS、 I2S 和 SDIO等需要特定时钟的外设保证合适的频率。

以F417芯片为例:可通过多个预分频器配置 AHB 频率、高速 APB (APB2) 和低速 APB (APB1)。 AHB 域的最大频率为 168 MHz。高速 APB2 域的最大允许频率为 84 MHz。低速 APB1 域的最大允许频率为 42 MHz。实际上输出的最大时钟可以适当提高一点,但为了保证在多种环境下,最好还是不要超过标准的最大值。

 

STM32F4xx 器件具有两个 PLL

PLL (PLL) HSE HSI 振荡器提供时钟信号,并具有两个不同的输出时钟:

第一个输出用于生成高速系统时钟(最高达 168 MHz

第二个输出用于生成 USB OTG FS 的时钟 (48 MHz)、随机数发生器的时钟

 

专用 PLL (PLLI2S) 用于生成精确时钟,从而在 I2S 接口实现高品质音频性能。

由于在 PLL 使能后主 PLL 配置参数便不可更改,所以建议先对 PLL 进行配置,然后再使能(选择 HSI HSE 振荡器作为 PLL 时钟源,并配置分频系数 MNP Q)。

PLLI2S 使用与 PLL 相同的输入时钟( PLLM[5:0] PLLSRC 位为两个 PLL 所共用)。但是, PLLI2S 具有专门的使能/禁止和分频系数( N R)配置位。在 PLLI2S 使能后,配置参数便不能更改。

 

Ⅲ、代码分析

以STM32F4x5、x7系列芯片为例来分析一下系统时钟的配置。

参考软件工程:

https://yunpan.cn/cRepWDShSK4yc  访问密码 65b1

 

1.倍频参数

结合上面时钟树和源代码可以看得出来,系统时钟PLLCLK的计算主要是配置PLL_MPLL_NPLL_P这三个参数,最后168M是通过分频、倍频得出来的。

 

2.验证时钟频率

对于STM32芯片来说,验证系统时钟最终运行多大的速度,最准确的验证方法的用示波器测试它的系统时钟。

这里描述一下怎样用示波器来测试系统时钟。其实很简单,就是在软件代码里面配置时钟输出(这里可以输出多种类型的时钟HSE、HSI、PLLCLK等),根据代码配置不同,相应输出的时钟就不同。请看源代码:

我提供的代码里面就有这一选项,将定义配置为1,就打开了这个功能。时钟输出的参数有两个,时钟源,分频值。注意:这里的最大输出时钟是100M,所以PLLCLK时钟分频之后才能输出,不然你用示波器检测不到波形(我测试过了)。

最后输出的波形如图:

 

、说明

关于STM32的开发,软件兼容性是很好的,不要觉得你的芯片和我总结的实例有差异就不看了,其实是错误的认识,特别是同一个系列的芯片基本上程序都兼容,也就是可以互相使用。

以上总结仅供参考,若有不对之处,敬请谅解。

 

Ⅴ、最后

关注微信,回复“更多内容”,将获得更多内容(如:UCOS实例等,不断更新中......)。

如果你喜欢我分享的内容,你又想了解更多相关内容,请关注文章开头的微信公众号,新内容持续更新中,后期将会有更多精彩内容出现。

 

以上是关于stm32------系统时钟配置的主要内容,如果未能解决你的问题,请参考以下文章

STM32--RCC时钟配置寄存器

stm32------系统时钟配置

STM32F103想用内部时钟HSI做为系统时钟,怎么配置成36M

STM32F4_RCC系统时钟配置及描述

STM32学习笔记 一基于STM32F103C8T6最小系统板和STM32CubeMX实现LED灯循环闪烁

STM32系统时钟配置,滴答定时器配置相关