STM32-内部时钟
- LSI:40kHz低速内部RC振荡器,驱动独立看门狗,或用程序选择驱动RTC
- HSI:8MHz高速内部RC振荡器,可用于系统时钟;系统启动时默认使用该时钟为系统时钟,频率就是8MHz。
另外,经过测试,得出几个结论点:
1.如果调用了库的时钟初始化函数,初始化HSE外部高速时钟为PLL;当外部高速时钟有异常时,会导致PLL启动失败,会一直卡在某一个地方。
2.当在运行过程中HSE出现异常(如用手触摸一个引脚),则会自动切换到HSI内部时钟;如果短路则不会切换,有看门狗会触发看门狗。
3.如果可以开启时钟监视器,当HSE出现异常(任何异常)后产生一个CSSI中断,映射到NMI中断里;(NMI中断的处理可查阅文档后面,NMI中断处理函数@NMI_Handler)
示例代码
#include "system_clock.h"
#include "stm32f10x.h"
#define SYS_DEFAULT_COUNT_FREQ 285522
#define VECT_TAB_OFFSET 0x0
void set_sysclock_to_HSI(uint32_t pll_mul)
{
RCC_DeInit();
RCC_HSICmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
RCC_PLLConfig(RCC_PLLSource_HSI_Div2,pll_mul);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08);
}
void config_rcc_interrupt(void)
{
#ifdef STM32F10X_CL
RCC_ITConfig(RCC_IT_LSIRDY, ENABLE);
RCC_ITConfig(RCC_IT_LSERDY, ENABLE);
RCC_ITConfig(RCC_IT_HSIRDY, ENABLE);
RCC_ITConfig(RCC_IT_HSERDY, ENABLE);
RCC_ITConfig(RCC_IT_PLLRDY, ENABLE);
RCC_ITConfig(RCC_IT_PLL2RDY, ENABLE);
RCC_ITConfig(RCC_IT_PLL3RDY, ENABLE);
#else
RCC_ITConfig(RCC_IT_LSIRDY, ENABLE);
RCC_ITConfig(RCC_IT_LSERDY, ENABLE);
RCC_ITConfig(RCC_IT_HSIRDY, ENABLE);
RCC_ITConfig(RCC_IT_HSERDY, ENABLE);
RCC_ITConfig(RCC_IT_PLLRDY, ENABLE);
#endif
}
static int set_sys_clock_to_72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
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)
{
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
RCC->CR |= RCC_CR_PLL2ON;
StartUpCounter = 0;
do{
StartUpCounter++;
}while(((RCC->CR & RCC_CR_PLL2RDY) == 0) && (SYS_DEFAULT_COUNT_FREQ*5 != StartUpCounter))
if((RCC->CR & RCC_CR_PLL2RDY) == 0){
return -2;
}
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif
RCC->CR |= RCC_CR_PLLON;
StartUpCounter = 0;
do{
StartUpCounter++;
}while(((RCC->CR & RCC_CR_PLLRDY) == 0) && (SYS_DEFAULT_COUNT_FREQ*5 != StartUpCounter));
if((RCC->CR & RCC_CR_PLLRDY) == 0){
return -3;
}
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
uint32_t pll_sta = 0;
StartUpCounter = 0;
do{
pll_sta = (RCC->CFGR & (uint32_t)RCC_CFGR_SWS);
StartUpCounter++;
}while((pll_sta != (uint32_t)0x8) && (SYS_DEFAULT_COUNT_FREQ*5 != StartUpCounter));
if(pll_sta != (uint32_t)0x8){
return -4;
}
}
else
{
return -1;
}
return 0;
}
void system_clock_init (void)
{
RCC->CR |= (uint32_t)0x00000001;
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif
RCC->CR &= (uint32_t)0xFEF6FFFF;
RCC->CR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifdef STM32F10X_CL
RCC->CR &= (uint32_t)0xEBFFFFFF;
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
RCC->CFGR2 = 0x00000000;
#else
#endif
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif
#endif
int err = 0;
err = set_sys_clock_to_72();
if(err < 0)
{
set_sysclock_to_HSI(RCC_PLLMul_9);
}
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
#endif
}
void NMI_Handler(void)
{
if((RCC_GetITStatus(RCC_IT_CSS) != RESET)
&& (RCC->CR | ((uint32_t)RCC_CR_HSEON)))
{
RCC_ClearITPendingBit(RCC_IT_CSS);
RCC_ClockSecuritySystemCmd(ENABLE);
set_sysclock_to_HSI(RCC_PLLMul_9);
}
}