dufaxing To be a better man

STM32系统时钟时钟

2017-10-19


在STM32中有5个时钟源:
①、HSI是高速内部时钟,RC震荡器,频率为 8MHz。
②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
③、LSI是低速内部时钟,RC振荡器,频率为40kHz。
④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HIS/2、HSE或HSE/2。倍频可选择为2~16倍,但其输出频率最大不得超过72MHz。
系统时钟SYSCLK,它是供STM32中绝大部分器件工作的时钟源,系统时钟可选择为PLL输出、HSI或者HSE。系统时钟的做大频率为72MHz,它通过AHB分频器分频后送给个模块使用,AHB分频器可选择1、2、4、8、16、32、64、128、256、512分频。AHB分频器输出的时钟送给5大模块使用:

  1. 送给AHB总线、内核、内存和DMA使用的HCLK时钟。
  2. 通过8分频后送给Cortex的系统定时器时钟。
  3. 直接送给Cortex的空闲运行时钟PCLK。
  4. 送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。
  5. 送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给定时器(Timer)1倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2、4、6、8分频。
    连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。 连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口、第二功能IO口。

HSI经PLL锁相环倍频后作为系统时钟

HSI:内部高速时钟,频率为HSI RC的2分频。
PLL:锁相环.通过PLL倍频后,送入系统时钟。
STM32F10X使用HSI作为时钟源,最大时钟频率为36MHz。

  • 时钟初始化
    VOID HwRcc_Init()
    {
      RCC_DeInit();
      /*开启内部时钟*/
      RCC_HSICmd(ENABLE);
      /*等待内部晶振起振*/
      while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
    
      RCC_HCLKConfig(RCC_SYSCLK_Div1);    //设置HCLK(AHB时钟)=SYSCLK
      RCC_PCLK1Config(RCC_HCLK_Div2);     //PCLK1(APB1) = HCLK
    
      RCC_PCLK2Config(RCC_HCLK_Div2);     //PCLK2(APB2) = HCLK
    
      /*配置HSI*/
      HwRcc_Hsi();
    
      //16mhz
      //FLASH_PrefetchBufferCmd(ENABLE);
      FLASH_SetLatency(FLASH_Latency_2);
    
      return;
    }
    
  • HSI时钟配置
    VOID HwRcc_Hsi()
    {
      g_stHwadpt.RccHse = FALSE;
    
      //设置系统时钟SYSCLK = PLL输出
      RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
    
      RCC_PLLCmd(DISABLE);
    
      //PLL设置SYSCLK/2 * 6 = 8*3= 24MHz
      //STM32F10X中PLL锁相环作为系统 最大时钟为 (SYSCLK/2 * 9 )= 36M
      RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_6);
    
      //设置系统时钟SYSCLK = PLL输出
      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
      //启动PLL
      RCC_PLLCmd(ENABLE);//如果PLL被用于系统时钟,不能被DISABLE
      //等待PLL稳定
      while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){;}
    
      //等待PLL成功用作于系统时钟的时钟源,并等待稳定
      // 0x00:HSI作为系统时钟
      // 0x04:HSE作为系统时钟
      // 0x08:PLL作为系统时钟
      while(RCC_GetSYSCLKSource() != 0x08);
    
      return;
    }
    

HSE经PLL锁相环倍频后作为系统时钟

  • 时钟初始化
    VOID HwRcc_Init()
    {
    RCC_DeInit();
    /*开始外部时钟*/
    RCC_HSEConfig(RCC_HSE_ON);
    /*等待外部晶振起振*/
    while(SUCCESS != RCC_WaitForHSEStartUp());
    
    RCC_HCLKConfig(RCC_SYSCLK_Div1);    //设置HCLK(AHB时钟)=SYSCLK
    RCC_PCLK1Config(RCC_HCLK_Div2);     //PCLK1(APB1) = HCLK
    
    RCC_PCLK2Config(RCC_HCLK_Div2);     //PCLK2(APB2) = HCLK
    /*配置外部时钟*/
    HwRcc_Hse();
    }
    
  • HSE时钟配置
    我在配置HSE时,想将系统时钟配置成STM32F10X允许的最大时钟72MHz时遇到个问题,RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_6);PLL最大为6倍频,也就是48MHz,超过6倍频时while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){;}不能正常工作。
    解决办法:
    查阅资料知:
    Bits 2:0 LATENCY: Latency
    These bits represent the ratio of the SYSCLK (System Clock) period to the Flash Access time.
    000 Zero wait state, if 0 < SYSCLK≤ 24 MHz
    001 One wait state, if 24 MHz < SYSCLK ≤ 48 MHz
    010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
    超过48MHz的SYSCLK,需要2个FLASH预取延时周期
    添加如下两行代码后,系统运行正常,且时钟频率为72MHz
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    FLASH_SetLatency(FLASH_Latency_2);/* Flash 2 wait state */
    
  • 配置代码
    VOID HwRcc_Hse()
    {
      g_stHwadpt.RccHse = TRUE;
    
      RCC_PLLCmd(DISABLE);
    
      //PLL设置SYSCLK/2 * 3 = 8*3= 24MHz
      RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9);
      //设置系统时钟SYSCLK = PLL输出
      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
      /*******************************************************************************************/
      //不加延时周期,FLASH的访问速度最高为50MHz左右.
      //These bits represent the ratio of the SYSCLK (System Clock) period to the Flash Access time.
      //000 Zero wait state, if 0 < SYSCLK≤ 24 MHz
      //001 One wait state, if 24 MHz < SYSCLK ≤ 48 MHz
      //010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
      /********************************************************************************************/
      FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
      FLASH_SetLatency(FLASH_Latency_2);/* Flash 2 wait state */
      //启动PLL
      RCC_PLLCmd(ENABLE);//如果PLL被用于系统时钟,不能被DISABLE
      //等待PLL稳定
      while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){;}
    
      //等待PLL成功用作于系统时钟的时钟源,并等待稳定
      // 0x00:HSI作为系统时钟
      // 0x04:HSE作为系统时钟
      // 0x08:PLL作为系统时钟
      while(RCC_GetSYSCLKSource() != 0x08);
    
      return;
    }
    

在配置外部晶振为系统时钟源时需要注意需要注意,若外部晶振为16MHz需要更改HSE_VALUE宏定义。

修改RCC配置代码如下:
将语句:RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //之前使用8MHz外部晶振,9倍频到72MHz:
修改为:RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9); //使用16MHz外部晶振之后,2分频再9倍频到72MHz:

(1).此文件中找到语句:#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */:
(2).将这条语句更改为:#define HSE_VALUE ((uint32_t)16000000) /*!< Value of the External oscillator in Hz */:


相关文档

STM32-通用定时器基本定时功能



Comments

Content