STM32F4时钟初始化配置(01)
  /**********************************************************/
  STM32F4 时钟系统初始化是在system_stm32f4xx.c中的 SystemInit()函数中完成的。对于系统时钟关键寄存器设置主要是在 SystemInit 函数中调用 SetSysClock()函数来设置的。我们可以先看看 SystemInit ()函数体:
  void SystemInit(void)
  {
  /*FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
  SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
  #endif
  /* Reset the RCC clock configuration to thedefault reset state ------------*/
  /*Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;
  /*Reset CFGR register */
  RCC->CFGR = 0x00000000;
  /*Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF;
  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x24003010;
  /*Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;
  /*Disable all interrupts */
  RCC->CIR = 0x00000000;
  #if defined (DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
  SystemInit_ExtMemCtl();
  #endif /* DATA_IN_ExtSRAM ||DATA_IN_ExtSDRAM */

  /*Configure the System clock source, PLL Multiplier and Divider factors,
  AHB/APBx prescalers and Flash settings----------------------------------*/
  SetSysClock();
  /*Configure the Vector Table location add offset address ------------------*/
  #ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocationin Internal
  SRAM */
  #else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocationin
  Internal FLASH */
  #endif
  }
  SystemInit函数开始先进行浮点运算单元设置,然后是复位PLLCFGR,CFGR寄存器,同时通过设置 CR寄存器的 HSI 时钟使能位来打开 HSI 时钟。默认情况下如果 CFGR 寄存器复位,那么是选择HSI作为系统时钟,这点大家可以查看RCC->CFGR 寄存器的位描述最低2位可以得知,当低两位配置为 00的时候(复位之后),会选择 HSI振荡器为系统时钟。也就是说,调用 SystemInit 函数之后,首先是选择 HSI 作为系统时钟。
  在设置完相关寄存器后,接下来SystemInit函数内部会调用 SetSysClock函数。这个函数比较长,我们就把函数一些关键代码行截取出来给大家讲解一下。这里我们省略一些宏定义标识符值的判断而直接把针对STM32F407 比较重要的内容贴出来:
  static void SetSysClock(void)
  {
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  /*使能 HSE*/
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  /* 等待HSE 稳定*/
  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)
  {
  /* Select regulator voltage output Scale 1 mode */
  RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  PWR->CR |= PWR_CR_VOS;
  /* HCLK = SYSCLK / 1*/
  RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

  /* PCLK2 = HCLK / 2*/
  RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;

  /* PCLK1 = HCLK / 4*/
  RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
  /* PCLK2 = HCLK / 2*/
  RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;

  /* PCLK1 = HCLK / 4*/
  RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;
  /* Configure the main PLL */
  RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1)<< 16) |
  (RCC_PLLCFGR_PLLSRC_HSE) |(PLL_Q << 24);
  /* 使能主PLL*/
  RCC->CR |= RCC_CR_PLLON;
  /* 等待主PLL就绪 */
  while((RCC->CR & RCC_CR_PLLRDY) == 0)
  {
  }

  /* Configure Flash prefetch, Instruction cache, Data cache and waitstate */
  FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN
  |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

  /* 设置主PLL时钟为系统时钟源 */
  RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  RCC->CFGR |= RCC_CFGR_SW_PLL;
  /* 等待设置稳定(主PLL作为系统时钟源)*/
  while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) !=RCC_CFGR_SWS_PLL);
  {
  }
  }
  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 */
  }
  }
  这段代码的大致流程是这样的:先使能外部时钟 HSE,等待 HSE 稳定之后,配置AHB,APB1,APB2 时钟相关的分频因子,也就是相关外设的时钟。等待这些都配置完成之后,打开主PLL时钟,然后设置主PLL作为系统时钟 SYSCLK时钟源。如果HSE 不能达到就绪状态(比如外部晶振不能稳定或者没有外部晶振),那么依然会是HSI作为系统时钟。
  /**********************************************************/