Appearance
时钟
来源HSE(High Speed External Clock signal)外部高速时钟,
通过OSC_OUT和OSC_IN两个引脚
还有一个内部的HSI, 精度比较小, 受温度影响, 被RCC_CR寄存器控制
故障的时候自动使用HSI, 直到HSE启动成功
也是由寄存器控制
寄存器
RCC_CR: HSE, HSI, PLL的使能, HSI的频率安全时钟使能
RCC_CFGR:时钟的选择以及分频
RCC_CLR: 时钟中断
RCC_APB2RSTR: APB2复位寄存器
RCC_APB1RSTR: APB1复位寄存器
RCC_AHBENR:AHB时钟使能
RCC_APB2ENR:APB2时钟使能
RCC_APB1ENR:APB1时钟使能
RCC_BDCR: 备份域控制寄存器,设置LSE使能, RTC的时钟源选择
的LSEON、LSEBYP、RTCSEL和RTCEN位处于备份域。因 此,这些位在复位后处于写保护状态,只有在电源控制寄存器(PWR_CR)中的DBP位置’1’后才 能对这些位进行改动。
RCC_CSR:状态寄存器
配置
PLL: 锁相环时钟, 是一种用于生成稳定时钟信号的时钟, 可以通过比较输入信号和输出信号的相位差来调整输出信号的频率和相位,从而使输出信号与输入信号同步。
使用外部时钟, PLLXTPRE不分频, PLLSRC选择, 之后的PLLMUL九倍频, 锁相环时钟PLLCLK为72MHz
如果使用内部时钟会进行一次分频, 最高频率为64MHz
SYSCLK: 系统时钟, 有三种来源, 一般设置为锁相环时钟, 由RCC_CFGR前两位控制第三位检测是否切换完成
之后有AHB分频器, 再通过APB1, APB2预分频器再次分频, PCLK1为APB1最高36MHz, 之后可以倍频为定时器配置时钟, PCLK2为APB2可以为72MHz
AHB还为内核等提供时钟
RTC试试时钟, HSE分频, LSE(外部32.768k), 或LSI(40K受温度影响)提供, 看门狗由LSI提供
还可以从MCO输出
CSS: 时钟安全系统, 外部的HSE故障的时候会发生时钟安全中断(CSSI后连接到不可屏蔽中断), 还会被发送到TIM1和TIM8的刹车输入端
HSE有毛病之后系统时钟自动切换为HSI为8MHz
c
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 定义 ---------------------------*/
/* 使能 HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* 等待 HSE is ready and if 超时 is reached exit */
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 2 wait state 设置等待时间在闪存编程手册中有描述配置系统时钟周期和闪存访问周期之间的关系 */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK 设置为72M*/
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK 一分频72M*/
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK 二分频36MHz*/
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);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
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 */
}
}
c
void HSE_SetSysClk(uint32_t RCC_PLLMul_x)
{
//复位
RCC_DeInit();
ErrorStatus HSEStatus;
//使能HSE
RCC_HSEConfig(RCC_HSE_ON);
HSEStatus = RCC_WaitForHSEStartUp();
if(HSEStatus==SUCCESS)
{
//启动成功
//根据库文件使能预取址, 设置为两个等待
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
//设置分频
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);
//设置系统时钟为PLL
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08);
}else
{
//启动失败
}
}