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