1.内部RC震荡器与外部晶振的选择
STM32可以选择内部时钟(内部RC振荡器),也可以选择外部时钟(外部晶振)。
HSE时钟
HSE(High speed external clock signal),即高速外部时钟
来源:外部8M的无源晶振
HSI时钟
HSI(Low speed internal clock signal),高速的内部时钟
在芯片内部,大小为8M,当HSE故障时,系统时钟会自动切换到HSI,直到HSE启动成功。
2.系统时钟的来源
系统时钟源的切换
3.时钟配置-
4.AHB系统总线
1.APB1是低速总线
2.APB2是高速总线
APB2 Precaler 配置为 0xx
4.RTC时钟
RTC时钟:为芯片内部的RTC外设提供时钟。
来源: HSE
时钟树小结
1.通常我们用HSE(8M)配置为系统时钟,不分频(PLLXTPRE设为0),再到HSE时钟作为PLL输入时钟(PLLSRC设置为1),再(PLLMUL:PLL倍频系数设置为9)0111:PLL 9倍频输出,
这样STM32的系统时钟(SYSCLK)就为72M。
#include "rccclkconfig.h"
void HSE_SetSysClk( uint32_t RCC_PLLMul_x )
{
ErrorStatus HSEStatus;
//把RCC寄存器复位成复位值
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON); //打开外部高速时钟,使能HSE
//等待HSE就绪并做出
HSEStatus=RCC_WaitForHSEStartUp();
if( HSEStatus==SUCCESS )
{
//使能预取指
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2); //72M,主频设置为2个等待
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1最大为36M
RCC_PCLK2Config(RCC_HCLK_Div1);
//配置锁相环:PLLCLK = HSE * RCC_PLLMul_x = 72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x);
//使能PLL
RCC_PLLCmd(ENABLE);
//等待PLL稳定
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );
//选择系统时钟(SYSCLK)
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while( RCC_GetSYSCLKSource() !=0x08 ); //如果不成功就一直等待,0x08: PLL used as system clock
}
else
{
//如果HSE启动失败,用户可以在这里添加处理错误的代码
}
}
以下是时钟设置的基本流程:
默认使用HSE
1.将RCC寄存器重新设置为默认值,即调用函数RCC_DeInit;
2.打开外部高速时钟晶振HSE,调用函数RCC_HSEConfig(RCC_HSE_ON);
3.等待外部高速时钟晶振工作,调用HSEStartUpStatus=RCC_WaitForHSEStartUp();
4.设置AHB时钟,即调用函数RCC_HCLKConfig;
5.设置高速AHB时钟,即调用函数RCC_PCLK2Config;
6.设置低速 AHB时钟,即调用函数RCC_PCLK1Config;
7.设置PLL,即调用函数RCC_PLLConfig;
8.打开PLL,即调用函数RCC_PLLCmd(ENABLE);
9.等待PLL工作,while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)== RESET);
10.设置系统时钟,即调用函数RCC_SYSCLKConfig;
11.判断PLL是否是系统时钟,while(RCC_GetSYSCLKSource()!=0x08);
库文件参考启动文件
改变系统时钟(SYSCLK)的时钟频率,当时钟频率越大,灯闪烁得越快。
#include "stm32f10x.h"
#include "dsp_led.h"
#include "rccclkconfig.h"
#define GPIOB_ODR_Addr (GPIOB_BASE+0X0C)
#define GPIOE_IDR_Addr (GPIOE_BASE+0X08)
#define PBout(n) *(unsigned int*)((GPIOB_ODR_Addr & 0xF0000000)+0x02000000+((GPIOB_ODR_Addr &0x00FFFFFF)<<5)+(n<<2))
#define PEin(n) *(unsigned int*)((GPIOE_ODR_Addr & 0xF0000000)+0x02000000+((GPIOE_ODR_Addr &0x00FFFFFF)<<5)+(n<<2))
void Delay(uint32_t count)
{
for(;count!=0;count--);
}
int main(void)
{
//来到这里的时候,系统的时钟已经被配置成72M.
HSE_SetSysClk( RCC_PLLMul_9 );
LED_GPIO_Config();
while(1)
{
PBout(5)=1;
Delay(0XFFFFF);
PBout(5)=0;
Delay(0XFFFFF);
}
}
寄存器版本
#include "stm32f10x.h"
#include "dsp_led.h"
#include "rccclkconfig.h"
#define GPIOB_ODR_Addr (GPIOB_BASE+0X0C)
#define GPIOE_IDR_Addr (GPIOE_BASE+0X08)
#define PBout(n) *(unsigned int*)((GPIOB_ODR_Addr & 0xF0000000)+0x02000000+((GPIOB_ODR_Addr &0x00FFFFFF)<<5)+(n<<2))
#define PEin(n) *(unsigned int*)((GPIOE_ODR_Addr & 0xF0000000)+0x02000000+((GPIOE_ODR_Addr &0x00FFFFFF)<<5)+(n<<2))
void Delay(uint32_t count)
{
for(;count!=0;count--);
}
//系统时钟初始化函数
//采用寄存器方式编程 时钟配置寄存器(RCC_CFGR)
//pll: 选择的倍频数,从2开始,最大值为16
void Rcc_Init(u8 PLL)
{
u8 temp=0;
RCC_DeInit();
RCC->CR|=0X00010000; //使能外部高速时钟使能HSEON
while(!(RCC->CR>>17)); // HSERDY:外部高速时钟就绪标志 由硬件置’1’来指示外部4-16MHz振荡器已经稳定
RCC->CFGR|=0X00000400; // APB1软件必须保证APB1时钟频率不超过36MHz。
PLL-=2; //等待2个周期
RCC->CFGR|=PLL<<18; //PLLMUL[3:0],设置由软件设置来确定PLL倍频系数。
RCC->CFGR|=1<<16; //由软件置’1’或清’0’来选择PLL输入时钟源 PLLSRC:1:HSE时钟作为PLL输入时钟。
FLASH->ACR|=0X32; //FLASH 2个延时周期
RCC->CR|=0X01000000; //位24(PLLON)置1,当PLL时钟被用作或被选择将要作为系统时钟
while(!(RCC->CR>>25)); //PLLRDY:PLL时钟就绪标志 位25 PLL锁定后由硬件置’1’
RCC->CFGR|=0X00000002; //SW[1:0]:系统时钟切换 10:PLL输出作为系统时钟;
while(temp!=0x02) //等待PLL作为系统时钟设置成功
{
temp=RCC->CFGR>>2;
temp&=0x03;
}
}
int main(void)
{
//来到这里的时候,系统的时钟已经被配置成72M.
Rcc_Init(16);
LED_GPIO_Config();
while(1)
{
// LED_G(OFF);
PBout(5)=1;
Delay(0XFFFFF);
PBout(5)=0;
Delay(0XFFFFF);
}
}
配置HSI时钟为系统时钟
#include "rccclkconfig.h"
void HSI_SetSysClk( uint32_t RCC_PLLMul_x )
{
__IO uint32_t HSIStatus=0;
//把RCC寄存器复位成复位值
RCC_DeInit();
RCC_HSICmd(ENABLE); //使能HSI
//等待HSE就绪并做出
HSIStatus=RCC->CR & RCC_CR_HSIRDY;
if( HSIStatus==SUCCESS )
{
//使能预取指
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2); //72M,主频设置为2个等待
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2); //PCLK1最大为36M
RCC_PCLK2Config(RCC_HCLK_Div1);
//配置锁相环:PLLCLK = HSI/2 * RCC_PLLMul_x = 72MHz
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_x);
//使能PLL
RCC_PLLCmd(ENABLE);
//等待PLL稳定
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET );
//选择系统时钟(SYSCLK)
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while( RCC_GetSYSCLKSource() !=0x08 ); //如果不成功就一直等待,0x08: PLL used as system clock
}
else
{
//如果HSI启动失败,用户可以在这里添加处理错误的代码
}
}