stm32库函数void SystemInit (void)分析

来源:互联网 发布:淘宝剑三代练 编辑:程序博客网 时间:2024/05/24 07:05
void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */

  RCC->CR |= (uint32_t)0x00000001;

//配置时钟控制寄存器(RCC_CR),主要操作RCC_CR的位0 (HSION:内部高速时钟使能)当从待机和停止模式返回或用作系统时钟的外部3-25MHz振荡器发生故障时,该位由硬件置’1’来启动内部8MHz的RC振荡器。当内部8MHz振荡器被直接或间接地用作或被选择将要作为系统时钟时,该位不能被清零。可以看出系统启动后是首先依靠内部时钟源而工作的


  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL//STM32F10X_CL代表的是使用了 STM32互联系列微处理器也就是STM32F105和STM32F107系列处理器。
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   

 //初始化时钟配置寄存器(RCC_CFGR) 



其他的控制位大家可以参考STM32中文参考手册,这里不详细介绍。

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;


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

关闭CSSON HSEON PLLON PLL2ON


  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

  RCC->CFGR &= (uint32_t)0xFF80FFFF;


OSC_OUT和OSC_IN这两个引脚接外部晶振8MHz,8MHz的时钟遇到了第一个分频器PLLXTPRE(HSE divider for PLL entry),在这个分频器中,可以通过寄存器配置,选择它的输出。它的输出时钟可以是对输入时钟的二分频或不分频。本例子中,我们选择不分频,所以经过PLLXTPRE后,还是8MHz的时钟。开关PLLSRC(PLL entry clock source),我们可以选择其输出,输出为外部高速时钟(HSE)或是内部高速时钟(HSI)。接着锁相环PLL,具有倍频作用,在这里我们可以输入倍频因子PLLMUL,根据需求来设置,如果想超频可以在此处设置。经过倍频的时钟称为PLLCLK。倍频因子我们设定为9倍频,也就是说,经过倍频之后,我们的时钟从原来8MHz的 HSE变为72MHz的PLLCLK。紧接着又遇到了一个开关SW(SW:系统时钟切换00:HSI作为系统时钟; 01:HSE作为系统时钟; 10:PLL输出作为系统时钟; 11:不可用。),经过这个开关之后就是STM32的系统时钟(SYSCLK)了。通过这个开关,可以切换SYSCLK的时钟源,可以选择为HSI、PLLCLK、HSE。我们选择为PLLCLK时钟,所以SYSCLK就为72MHz了。PLLCLK在输入到SW前,还流向了USB预分频器,这个分频器输出为USB外设的时钟(USBCLK)。回到SYSCLK,SYSCLK经过AHB预分频器,分频后再输入到其它外设。如输出到称为HCLK、FCLK的时钟,还直接输出到SDIO外设的SDIOCLK时钟、存储器控制器FSMC的FSMCCLK时钟,和作为APB1、APB2的预分频器的输入端。GPIO外设是挂载在APB2总线上的, APB2的时钟是APB2预分频器的输出,而APB2预分频器的时钟来源是AHB预分频器。因此,把APB2预分频器设置为不分频,那么我们就可以得到GPIO外设的时钟也等于HCLK,为72MHz了。



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

时钟中断寄存器(RCC_CIR)禁止所有中断并且清除所有中断标志位,不同的芯片有不同的寄存器。

    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); //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();
//配置系统时钟频率。HCLK,PCLK2,PCLK1的分频值,分别代表AHB,APB2,和APB1。当然还干了其它的事情,配置FLASH延时周期和使能预取缓冲期

#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 

}

//设置中断向量表到SRAM和FLASH中的宏定义


此处分析不够深入,借鉴了很多东西如有冒犯请指出,我将立即删除。大家互相学习,希望各位高手多多指教!

原创粉丝点击