Fork me on GitHub

STM32学习笔记-系统时钟初始化函数详解

STM32学习笔记-系统时钟初始化函数详解

1. STM32F10xx时钟系统框图及说明

image

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 


posted @ 2021-06-22 22:32  一地鸡毛-  阅读(2431)  评论(0编辑  收藏  举报