STM32学习笔记-系统时钟初始化函数详解
STM32学习笔记-系统时钟初始化函数详解
1. STM32F10xx时钟系统框图及说明
1. STM32有5个时钟源:HSI、HSE、LSI、LSE、PLL。
- HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高
- HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz
- LSI是低速内部时钟,RC振荡器,频率为40kHz,提供低功耗时钟,WDG
- LSE是低速外部时钟,接频率为32.768kHz的石英晶体,RTC
- PLL为锁相环倍频输出,其时钟输入源可以选为HSI/2,HSE或HSE/2。倍频可选择2~16倍,但是其输出频率最大不能超过72MHz
2. 系统时钟SYSCLK可源于三个时钟源
- HSI振荡器时钟
- HSE振荡器时钟
- PLL时钟
2. 系统初始化函数
//系统时钟初始化函数
//pll:选择的倍频数,从2开始,最大值为16
void Stm32_Clock_Init(u8 PLL)
{
unsigned char temp=0;
MYRCC_DeInit(); //复位并配置向量表
RCC->CR|=0x00010000; //外部高速时钟使能HSEON
while(!(RCC->CR>>17));//等待外部时钟就绪
RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL-=2; //抵消2个单位(因为是从2开始的,设置0就是2)
RCC->CFGR|=PLL<<18; //设置PLL值 2~16
//PLLSRC:PLL输入时钟源
RCC->CFGR|=1<<16; //PLLSRC ON
FLASH->ACR|=0x32; //FLASH 2个延时周期
RCC->CR|=0x01000000; //PLLON
while(!(RCC->CR>>25));//等待PLL锁定
RCC->CFGR|=0x00000002;//PLL作为系统时钟
while(temp!=0x02) //等待PLL作为系统时钟设置成功
{
temp=RCC->CFGR>>2;
temp&=0x03;
}
}
//不能在这里执行所有外设复位!否则至少引起串口不工作.
//把所有时钟寄存器复位
void MYRCC_DeInit(void)
{
//APB1RSTR和APB2RSTR是APB1和APB2外设复位寄存器,对应挂在两条总线上的各种外设,全部置为无作用
RCC->APB1RSTR = 0x00000000;//复位结束
RCC->APB2RSTR = 0x00000000;
//AHBENR、AHB2ENR、AHB1ENR是外设时钟使能寄存器,使能哪个外设需要将对应的位进行操作
//睡眠模式闪存和SRAM不使能就不能使用flash和SRAM
RCC->AHBENR = 0x00000014; //睡眠模式闪存和SRAM时钟使能.其他关闭.
RCC->APB2ENR = 0x00000000; //外设时钟关闭.
RCC->APB1ENR = 0x00000000;
//CR为时钟控制寄存器
//将HSI使能作为系统时钟
RCC->CR |= 0x00000001; //使能内部高速时钟HSI ON //CFGR为时钟控制寄存器
//SW:系统时钟切换 此处设为00: HSI作为系统时钟;
//HPRE:AHB预分频 此处设为0000:表示不分频
//PPRE1:低速APB预分频(APB1) 此处设为000表示HCLK不分频
//PPRE2:高速APB预分频(APB2) 此处设为000表示HCLK不分频
//ADCPRE:ADC预分频 此处设为00: PCLK2 2分频后作为ADC时钟
//MCO:微控制器时钟输出 此处设为000表示没有时钟输出
RCC->CFGR &= 0xF8FF0000; //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0] //HSEON:外部高速时钟使能 HSE振荡器关闭
//CSSON:时钟安全系统使能 时钟监测器关闭;
//PLLON:PLL使能 PLL关闭
RCC->CR &= 0xFEF6FFFF; //复位HSEON,CSSON,PLLON
//HSEBYP:外部高速时钟旁路 外部4-16MHz振荡器没有旁路
RCC->CR &= 0xFFFBFFFF; //复位HSEBYP
//PLLSRC:PLL输入时钟源 0: HSI振荡器时钟经2分频后作为PLL输入时钟
//PLLXTPRE:HSE分频器作为PLL输入 0: HSE不分频
//PLLMUL:PLL倍频系数 0000: PLL 2倍频输出
//USBPRE:USB预分频 0: PLL时钟1.5倍分频作为USB时钟
RCC->CFGR &= 0xFF80FFFF; //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
RCC->CIR = 0x00000000; //关闭所有中断
//配置向量表
#ifdef VECT_TAB_RAM
MY_NVIC_SetVectorTable(0x20000000, 0x0);
#else
MY_NVIC_SetVectorTable(0x08000000,0x0);
#endif
}
3. SysTick 定时器与延时函数
1. SysTick定时器
4个寄存器控制SysTick定时器:
2. 延时函数
void delay_init()
{
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
u32 reload;
#endif
//系统时钟为72M,1/8为9M,既每秒钟震动9000000次,1s=1000ms=1000000us =》 1us震动9次
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为M
reload*=1000000/delay_ostickspersec; //根据delay_ostickspersec设定溢出时间
//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
fac_ms=1000/delay_ostickspersec; //代表OS可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断
SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
#else
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
#endif
}
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
#endif