- void NMI_Handler(void)
- {
- if(RCC_GetITStatus(RCC_IT_CSS)!= RESET)
- {
- HSI_SetSysClock(); //外部晶振故障时启用内部晶振
- RCC_ClearITPendingBit(RCC_IT_CSS); //清除时钟安全系统中断的挂起位
- }
- }
- / *
- *使用HSI时,设置系统时钟的步骤
- * 1,开启HSI,并等待HSI稳定
- * 2,设置AHB,APB2,APB1的预分频因子
- * 3,设置PLL的时钟来源
- *设置VCO输入时钟分频因子m
- *设置VCO输出时钟倍频因子
- *设置SYSCLK时钟分频因子p
- *设置OTG FS,SDIO,RNG时钟分频因子q
- * 4,开启PLL,并等待PLL稳定
- * 5,把PLLCK切换为系统时钟SYSCLK
- * 6,读取时钟切换状态位,确保PLLCLK被选为系统时钟
- * /
- void HSI_SetSysClock(void)
- {
- __IO uint32_t HSIStartUpStatus = 0;
- RCC_DeInit(); //复位RCC寄存器
- RCC_HSEConfig(RCC_HSE_OFF); //关闭外部晶振(HSE)
- RCC_HSICmd(ENABLE); //使能HSI,HSI = 16M
- while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET); //等待使能HSI成功
- //调压器电压输出级别配置为1,以便在器件为最大频率
- //工作时使性能和功耗实现平衡
- RCC-> APB1ENR | = RCC_APB1ENR_PWREN;
- PWR-> CR | = PWR_CR_VOS;
- RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置ABH时钟HCLK =系统时钟HCLK = SYSCLK
- RCC_PCLK2Config(RCC_HCLK_Div2); //设置高速APB时钟PCLK2 =系统时钟2分频PCLK2 = SYSCLK / 2
- RCC_PCLK1Config(RCC_HCLK_Div4); //设置低速APB时钟PCLK1 =系统时钟4分频PCLK = SYSCLK / 4
- //默认VCO输入频率=外部晶振频率/外部晶振频率= 1Mhz,所以PLLM =频率,注意的是2 <= PLLM <= 63
- //默认VCO输出频率= VCO输入频率* PLLN,并且192 <= PLLN <= 432,默认设置PLLN = 336,正好使VCO输出频率两分频后为168Mhz
- //默认PLL输出时钟频率= VCO输出频率/ PLLP,并且PLLP = 2,4,6,8默认设置为2,使得PLL输出频率为168Mhz
- //默认USB OTG FS时钟频率= VCO输出频率/ PLLQ,并且2 <= PLLQ <= 15默认设置为7,使得输出频率为48Mhz
- RCC_PLLConfig(RCC_PLLSource_HSI,16,336,2,7);
- RCC_PLLCmd(ENABLE);
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET); //等待PLL稳定
- / *配置Flash预取,指令缓存,数据缓存和等待状态* /
- FLASH-> ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
- while(RCC_GetSYSCLKSource()!= 0x08); //读取时钟切换状态位,确保PLLCLK被选为系统时钟
- }
- / *
- *使用HSE时,设置系统时钟的步骤
- * 1,开启HSE,并等待HSE稳定
- * 2,设置AHB,APB2,APB1的预分频因子
- * 3,设置PLL的时钟来源
- *设置VCO输入时钟分频因子m
- *设置VCO输出时钟倍频因子
- *设置PLLCLK时钟分频因子p
- *设置OTG FS,SDIO,RNG时钟分频因子q
- * 4,开启PLL,并等待PLL稳定
- * 5,把PLLCK切换为系统时钟SYSCLK
- * 6,读取时钟切换状态位,确保PLLCLK被选为系统时钟
- * /
- void HSE_SetSysClock(uint32_t frequency)
- {
- __IO uint32_t HSEStartUpStatus = 0;
- RCC_DeInit(); //复位RCC寄存器
- RCC_HSEConfig(RCC_HSE_ON); //设置外部晶振HSE
- HSEStartUpStatus = RCC_WaitForHSEStartUp(); //等待HSE起振
- if(HSEStartUpStatus == SUCCESS)
- {
- RCC_ClockSecuritySystemCmd(ENABLE); //启动时钟安全系统CSS
- //调压器电压输出级别配置为1,以便在器件为最大频率
- //工作时使性能和功耗实现平衡
- RCC-> APB1ENR | = RCC_APB1ENR_PWREN;
- PWR-> CR | = PWR_CR_VOS;
- RCC_HCLKConfig(RCC_SYSCLK_Div1); //设置ABH时钟HCLK =系统时钟HCLK = SYSCLK
- RCC_PCLK2Config(RCC_HCLK_Div2); //设置高速APB时钟PCLK2 =系统时钟2分频PCLK2 = SYSCLK / 2
- RCC_PCLK1Config(RCC_HCLK_Div4); //设置低速APB时钟PCLK1 =系统时钟4分频PCLK = SYSCLK / 4
- //默认VCO输入频率=外部晶振频率/外部晶振频率= 1Mhz,所以PLLM =频率,注意的是2 <= PLLM <= 63
- //默认VCO输出频率= VCO输入频率* PLLN,并且192 <= PLLN <= 432,默认设置PLLN = 336,正好使VCO输出频率两分频后为168Mhz
- //默认PLL输出时钟频率= VCO输出频率/ PLLP,并且PLLP = 2,4,6,8默认设置为2,使得PLL输出频率为168Mhz
- //默认USB OTG FS时钟频率= VCO输出频率/ PLLQ,并且2 <= PLLQ <= 15默认设置为7,使得输出频率为48Mhz
- RCC_PLLConfig(RCC_PLLSource_HSE,频率,336,2,7);
- RCC_PLLCmd(ENABLE); //使能PLL
- while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET); //等待PLL稳定
- / *配置Flash预取,指令缓存,数据缓存和等待状态* /
- FLASH-> ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
- RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
- while(RCC_GetSYSCLKSource()!= 0x08); //读取时钟切换状态位,确保PLLCLK被选为系统时钟
- }
- else
- {// HSE启动出错使用系统内部HSI时钟
- HSI_SetSysClock();
- }
- }
|