RCC——复位时钟控制
时钟就相当于外设的心脏,如果没有时钟,外设就不能工作。
时钟源:HSI、HSE、PLL、LSE、LSI
HSI(High Speed Internal)
约等于8MHz,内置RC振荡器,可以作为系统时钟的选择。
由上图可以看出,HSI可以作为系统时钟的一个选择。
HSE(High Speed External)
高速外部时钟,由外部晶振产生,也可以作为系统时钟的时钟源,还可以作为PLL的输入
PLL
锁相环,是用来倍频的,可以将频率放大倍数 。
经过PLL产生了一个PLLCLK,这个时钟也可以作为系统时钟的时钟源。
以上就是系统时钟的全部来源。
在HSE旁边还有一个CSS——时钟监视系统,由于外部晶振存在不稳定性,一旦HSE失效,则自动切换至系统时钟为HSI
LSE(Low Speed External)
低速外部时钟,一般用来给RTC——实时时钟提供时钟信号
LSI(Low Speed internal)
低速内部时钟,主要用来给独立看门狗提供时钟信号
讲解系统时钟配置函数SetSysClockTo72()
在开发板系统初始化函数SystemInit()中,会对系统 时钟进行初始化,会调用SetSysClock()这个函数,而在SetSysClock()这个函数中,会将系统时钟设置为72M
static void SetSysClockTo72(void)//
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* 使能 HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
//由于HSE是无源晶振,这个晶振需要一段时间,我们通过RCC_CR寄存器中的HSERDY这个位是否置1来判断,HSE是否起振成功。
/* 等待HSE就绪并做超时处理 */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
//如果HSE启动成功,程序继续执行
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;
//下面配置AHB、APB1、APB2总线的时钟分频因子,具体理解过程请参考图7
//三个时钟分频因子的配置位置请参考图8
/* HCLK = SYSCLK = 72M */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK = 72M */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK = 36M */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
//锁相环配置
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
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);
/* 使能 PLL */
RCC->CR |= RCC_CR_PLLON;
/* 等待PLL稳定 */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* 选择PLLCLK作为系统时钟 */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* 等待PLLCLK切换为系统时钟 */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else//HSE启动失败,用户可以在这里添加处理错误代码
{
}
}
使用HSE配置系统时钟并使用MCO输出监控系统时钟
void HSE_SetSysClk(){
ErrorStatus HSEStatus;
//把RCC寄存器复位到复位值
RCC_DeInit();
//使能HSE
RCC_HSEConfig(RCC_HSE_ON);
//获取HSE启动成功状态位
HSEStatus = RCC_WaitForHSEStartUp();
if(HSEStatus == SUCCESS){
//HSE启动成功
//使能预取指
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//设置FLASH等待周期
FLASH_SetLatency(FLASH_Latency_2);
//系统时钟一分频
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PCLK2Config(RCC_HCLK_Div1);
//配置PLLCLK=HSE*x
RCC_PLLConfig(RCC_PLLSource_HSE_Div, RCC_PLLMul_x);
//使能PLL
RCC_PLLCmd(ENABLE);
//等待PLL稳定
while( RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//选择系统时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSouce()!=0x08);
}else{
}
}