就是STM32的时钟时钟没有搞清楚,蹭着今天的东风,写一点东西理清思路。
STM32在默认情况下,使用的是内部的HSI做为时钟的。虽然使用库函数比较方便,但同时也隐藏了些东西。借助寄存器版的时钟配置函数也可以了解不少 。
情况1、
假设时钟源使用外部时钟源,则复位起始阶段是使用还是HSI作为系统时钟,有一个时钟切换的过程。
在时钟切换前, 系统主动开启HSI作为系统时钟,清零其他时钟使能,禁止RCC时钟中断后,再设置外部时钟。
在切换至外部时钟前所做的一些设置工作如下所示: 以F4为例
RCC->CR |= 0x00000001; //HISON置1, 开启HSI振荡器
RCC->CCFGR = 0x00000000; //配置寄存器清零,也就是使用HSI作为系统时钟源
RCC->CR &= 0xFEF6FFFF; // HSEON、CSSON、PLLON清零,
RCC->PLLCFGR = 0x24003010; //PLLCFGR恢复复位值
RCC->CR &= ~(1<<18); //HSEBYP清零,外部晶振不旁路
RCC->CIR = 0x00000000; //禁止RCC时钟中断
而时钟设置的步骤
1、开启HSE
2、等待HSE准备好
3、使能电源接口时钟------ 这是系统复位后,对后备寄存器和RTC访问的条件之1 即使能APB1的外设时钟使能寄存器的PWREN位置1 <其他条件是 BKPEN 备份接口时钟使能位置1 和 电源控制寄存器PWR_CR的DPB 位置1(disable protect b)>
则有这一步,才能进入待机模式
4、选择调压器输出电压级别, 用级别1模式 为备份域和待机电路以外的所有数字电路供电, 也确定了最大HCLK的频率
5、设置HCLK APB1 APB2预分频系数
6、关闭主PLL,设置倍频系数 和源
7、打开PLL
8、等待PLL时钟准备好
9、指令预取、cache使能 (CPU时钟频率变化前,通过软件序列来根据CPU频率调整访问Flash时所需的等待周期数---为了准确读取Flash数据)
10、选择主PLL作为系统时钟源
11、等待主PLL作为系统时钟成功
代码如下所示:
u16 retry = 0;
RCC->CR |= (0x01<<16); //*1
while((RCC->CR & (0x01<<17)==0x00)&&(retry<=0x1FFF)) retry++; //*2
if(retry>=0x1FFF) return 1; //失败
else{
RCC->APB1ENR |= (0x01<<28); //*3
PWR->CR |= (0x03<<14); //*4
RCC->CFGR |= (0<<4)| (5<<10) |(4<<13); //AHB 不分频 APB1 4分频 APB2 2分频 *5
//关闭主PLL,才能设置
RCC->CR &= ~(1<<24); //6*
//主PLL分频系数 pllq 主PLL和音频PLL的输入时钟源 HSE 主PLL 分频系数 VCO 主PLL倍频系数
RCC->PLLCFGR |=pllm | (plln<<6)|(((pllp>>1)-1)<<16) |(pllq<<24)|(1<<22);
RCC->CR |= (1<<24); //7*
while((RCC->CR)&(1<<25)==0); //8*
FLASH->ACR |= 1<<8; //使能指令预取 //9*
FLASH->ACR |= 1<<9; //使能指令缓存
FLASH->ACR |= 1<<10; //使能数据缓存
FLASH->ACR |=5<<0; //5个时钟等待 = CPU时钟总周期/Flash访问时间之比
RCC->CFGR &= ~(3<<0); //清零
RCC->CFGR |= 2<<0; // 10*
while(RCC->CFGR &(3<<2)!= (2<<2)); //11*
}
retrun 0;
/************************************************************************************************/
情况2、
使用HSI作为时钟源,以stm32l0为例,流程基本上和情况1的第二阶段的步骤3~11类似
/* (1) Enable power interface clock */
/* (2) Select voltage scale 1 (1.65V - 1.95V)
i.e. (01) for VOS bits in PWR_CR */
/* (3) Enable HSI divided by 4 in RCC-> CR */
/* (4) Wait for HSI ready flag and HSIDIV flag */
/* (5) Set PLL on HSI, multiply by 8 and divided by 2 */
/* (6) Enable the PLL in RCC_CR register */
/* (7) Wait for PLL ready flag */
/* (8) Select PLL as system clock */
/* (9) Wait for clock switched on PLL */