一、概述
本文主要介绍使用HSE高速外部时钟通过PLL倍频输出72MHZ的时钟作为系统时钟。下图为时钟树。
使用正点原子的开发板调试OSC_IN、OSC_OUT接的是8MHZ的晶振即为HSE时钟。
二、配置流程
1)复位RCC相关的所有寄存器
复位内容是参考正点原子例程,按照博主理解只要将HSE对应会影响到的RCC寄存器复位即可。本博客重点主要在时钟配置原理,此步骤可以不用特别关注。
RCC->APB1RSTR = 0x00000000;//
RCC->APB2RSTR = 0x00000000;
RCC->AHBENR = 0x00000014; //睡眠模式闪存和SRAM时钟使能,其他关闭
RCC->APB2ENR = 0x00000000; //外设时钟关闭
RCC->APB1ENR = 0x00000000;
RCC->CR |= 0x00000001; //使能内部高速时钟HSION
RCC->CFGR &= 0xF8FF0000; //复位SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0], MCO[2:0]
RCC->CR &= 0xFEF6FFFF; //复位HSEON, CSSON, PLLON
RCC->CR &= 0xFFFBFFFF; //复位HSEBYP
RCC->CFGR &= 0xFF80FFFF; //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
RCC->CIR = 0x00000000; //关闭所有中断
2)使能HSE时钟
使能HSE时钟等待就绪。
RCC->CR |= 1 << 16; // enable HSE clock
while (!(RCC->CR >> 17)); // wait HSE rdy
3)配置PLLXTPRE
配置为0,使得HSE作为PLL输出时不分频,上面复位操作已经配置为0这里就不重新配。
4)配置PLLMUL
RCC->CFGR |= PLL << 18; // set PLLMUL
5)配置PLL时钟源为HSE
RCC->CFGR |= 1 << 16; // PLLSRC HSE as PLL clock
6)配置FLASH等待周期
由于半导体制造工艺的限制,存放程序的FLASH存储器不可能达到这么高的工作频率,这样当CPU直接访问Flash存储器时必须插入等待周期以得到正确的结果。
在<<STM32F10xxx存编程手册>>有如下规定:
ACR寄存器内容:
7)使能PLL
使能PLL时钟,等待PLL时钟就绪。
RCC->CR |= 1 << 24; // PLLON PLL enable
while(!(RCC->CR >> 25)); // wait PLL rdy
8)PLL时钟作为系统时钟
配置PLL时钟作为系统时钟等待配置完成。
RCC->CFGR |= 0x00000002; // PLL as sysclk
do
{
temp = RCC->CFGR>>2;
temp &= 0x3;
} while (temp != 2); // temp = 2 indicator PLL as sysclk suc
三、源码
整个代码调用情况如下:
void Stm32_Clock_Init(u8 PLL)
{
unsigned char temp=0;
MYRCC_DeInit(); // reset and cfg vector tab
RCC->CR |= 1 << 16; // enable HSE clock
while (!(RCC->CR >> 17)); // wait HSE rdy
RCC->CFGR |= 0x00000400; // APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL -= 2; // 0 - PLL * 2 14/15 - PLL * 16
RCC->CFGR |= PLL << 18; // set PLLMUL
RCC->CFGR &= ~(1 << 17); // PLLXTPRE set 0 HSE PLL DIV1
RCC->CFGR |= 1 << 16; // PLLSRC HSE as PLL clock
FLASH->ACR |= 0x02; // LATENCY read Flash clock wait states
RCC->CR |= 1 << 24; // PLLON PLL enable
while(!(RCC->CR >> 25)); // wait PLL rdy
RCC->CFGR |= 0x00000002; // PLL as sysclk
do
{
temp = RCC->CFGR>>2;
temp &= 0x3;
} while (temp != 2); // temp = 2 indicator PLL as sysclk suc
}
在时钟配置完成后,通过能够成功点亮LED来验证配置成功。