(1)STM32固件库默认8MHz时钟修改为16MHz的操作

    最近在跟着ZF学习无人机,到了软件编程部分,首先是产生PWM的代码,芯片使用的是STM32F373CCT6,Keil创建Project就不说了,关于固件库的移植做了一个图表便于记录。

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第1张图片 图1

 固件库默认的时钟是8MHz,实际使用的16MHz,需要修改固件库。

问题1:到哪里找这个8MHz呢?猜测在和时钟相关的.h文件种。

在stm32f37x.h文件中有宏定义:

/**
 * @brief In the following line adjust the value of External High Speed oscillator (HSE) used in your application 
  */           
#if !defined  (HSE_VALUE) 
 #define HSE_VALUE       ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

    右键索引到了文件system_stm32f37x.h中的SystemCoreClockUpdate()中,可以看出HSE_VALUE的值由RCC的CFGR 寄存器的SWS决定。

/* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & RCC_CFGR_SWS;
    switch (tmp)
  {
    case 0x04:  /* HSE used as system clock */
      SystemCoreClock = HSE_VALUE;
      break;
}

     到《STM32F373XXX_Reference_Manual》中找下RCC_CFGR_SWS,当值SWS[1:0]为01时,即0x04,系统时钟选用HSE,吻合。

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第2张图片 图2

问题2:SystemCoreClockUpdate()这个函数什么时候被调用?被谁调用?

    首先函数自身有解释,Each time the core clock (HCLK) changes, this function must be called to update SystemCoreClock variable value. Otherwise, any configuration based on this variable will be incorrect. 就是说只有HCLK被改变时,该函数才会执行。“默认不用调用这个函数,因为SystemCoreClock默认被设置为设定的频率了(72MHz)”。感觉不对。

    回到Reference_Manual中找下HSE的介绍,有这一句话:The HSE crystal can be switched on and off using the HSEON bit in the Clock control register (RCC_CR)P103.找到RCC_CR,Bit16决定HSE的ON/OFF。

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第3张图片 图3

 

问题3:在哪里设置RCC_CR呢?

    在出现RCC_CFGR_SWS的stm32f37x.h中搜一下RCC_CR,找到RCC_CR_HSEON=0x00010000=‭0001,0000,0000,0000,0000‬,即Bit16=1。

/******************************************************************************/
/*                         Reset and Clock Control                            */
/******************************************************************************/
/********************  Bit definition for RCC_CR register  ********************/
#define  RCC_CR_HSION                        ((uint32_t)0x00000001)
……
#define  RCC_CR_HSEON                        ((uint32_t)0x00010000)
……
#define  RCC_CR_PLLON                        ((uint32_t)0x01000000)
#define  RCC_CR_PLLRDY                       ((uint32_t)0x02000000)

    右键索引下谁在调用RCC_CR_HSEON, 跳到了SetSysClock()函数中,看解释是用来配置系统时钟频率,到此HSE使能。

/**
  * @brief  Configures the System clock frequency, AHB/APBx prescalers and Flash 
  *         settings.
  * @note   This function should be called only once the RCC clock configuration  
  *         is reset to the default reset state (done in SystemInit() function).             
  * @param  None
  * @retval None
  */
static void SetSysClock(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/

  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------*/
  /* Enable HSE */
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
……
}

问题4:谁调用了SetSysClock()呢?google一下……

    注意看下static void SetSysClock(void),它是一个静态函数,只在system_stm32f37x.c中被调用,一搜是函数SystemInit()调用的,用来配置系统时钟。

/**
  * @brief  Setup the microcontrollers system.
  *         Initialize the Embedded Flash Interface, the PLL and update the 
  *         SystemCoreClock variable.
  */
void SystemInit (void)
{ 
……
/* Set HSION bit */
 RCC->CR |= (uint32_t)0x00000001;
  
/* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
  SetSysClock();
……
}

问题5:谁调用了SystemInit()呢?google一下……

    “STM32系统复位后首先进入SystemInit函数进行时钟的设置,然后进入主函数main()”,第一步操作,找到源头了。到此修改HSE_Value就分析完了。

    打算结束了,突然感觉HSE_VALUE好像并没有写到函数中啊,只是宏定义了而已。

*********************************************************************************************************************************************************    

    从初始函数SystemInit()来逐渐分析下函数执行的顺序,在SystemInit()中先启动HSI,再复位几个寄存器,最后调用SystemInit()来配置the System clock frequency, AHB/APBx prescalers and Flash settings,可以借助STM32CubeMX看下时钟树:HSI RC->HSI->SYSCLK->AHB Prescaler->HCLK

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第4张图片 图4

    再到 SetSysClock()函数,已知该函数是用来配置系统时钟的,看下是如何配置时钟的:

/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/

  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------*/
  /* Enable HSE */
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

到此相当于打开了图4中PLL Soure Mux的HSE开关,即如图5所示,HSE作为时钟输入。等待HSERDY……

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第5张图片 图5 HSEON

    HSERDY之后,继续配置,效果如图6所示,继续……

     /* HCLK = SYSCLK / 1 */
     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;       /*!< SYSCLK not divided */
     /* PCLK2 = HCLK / 1 */
     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;     /*!< HCLK not divided */
     /* PCLK1 = HCLK / 2 */
     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;    /*!< HCLK divided by 2 */

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第6张图片 图6

    配置RCC_CFGR的PLLSRC、PLLXTPRE和PLLMULL位,选择HSE作为PLL输入时钟,并且不分频,但PLLMULL9倍频。效果如图7所示。

    /* PLL configuration */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL9);

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第7张图片 图7

后面代码使能PLL,选择PLL作为系统时钟。由默认的外部时钟8MHz,PLL倍频,得到系统72MHz时钟的流程,如图8。

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第8张图片 图8

     到此清楚了,如果修改默认的8MHz外部时钟为16MHz,那么得到需要的72MHz的SYSCLK,需要将PLLMULL9/2,不是整除,可以先将16MHz/2得到8MHz,再给PLL。只需要在程序中将RCC_CFGR_PLLXTPRE_PREDIV1修改为RCC_CFGR_PLLXTPRE_PREDIV1_Div2即可。如果将默认的8MHz外部时钟修改为16MHz,只需要2部就可以:

1、修改#define HSE_VALUE      ((uint32_t)16000000);

2、修改RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL9)。

(1)STM32固件库默认8MHz时钟修改为16MHz的操作_第9张图片

 

你可能感兴趣的:(STM32)