5.STM32F407ZG時鐘系統及定時器SYSTICK的使用
1.系統時鐘樹:
LSI:低速內部時鐘(RC震盪器),32kHz,提供低功耗時鐘,用於看門狗和自動喚醒單元。
LSE:低速外部時鐘,外接32.768kHz的石英晶體。
HSI:高速內部時鐘16MHz,RC振盪器,精度不高,可用作系統時鐘或PLL輸入。
HSE:高速外部時鐘4~26MHz,外接石英/陶瓷諧振器或外部時鐘源。
PLL:鎖相環倍頻輸出,包括主PLL(生成高速系統時鐘168MHz和生成USB等的時鐘48MHz)和專用PLLI2S(生成精確時鐘,在I2S介面實現高品質音訊效能)。
總結:STM32有5個時鐘來源,HSI,HSE,LSI,LSE,PLL。 系統時鐘SYSCLK有3個時鐘來源,HSI,HSE和PLL。
STM32時鐘訊號輸出MCO1(PA8)和MCO2(PA9),最大輸出不超過100MHz。任何一個外設在使用前必須使能相應的時鐘。
2.相關庫函式
a.時鐘使能函式:RCC_HSICmd,RCC_LSICmd,RCC_PLLCmd等等;
b.時鐘源和相關配置函式:RCC_HSEConfig,RCC_LSEConfig,RCC_PLLConfig,RCC_SYSCLKConfig等等;
c.外設復位函式:RCC_AHB1PeriphResetCmd,RCC_APB2PeriphResetCmd等等;
d.狀態引數獲取函式:RCC_GetSYSCLKSource,RCC_GetClocksFreq,RCC_GetFlagStatus等等;
e.RCC中斷相關函式:RCC_ITConfig,RCC_GetITStatus等等。
啟動檔案中執行main()之前,會先執行SystemInit()進行系統時鐘的初始化配置,使能HSE(在stm32f4.h中定義了外部晶振頻率為HSE_VALUE ((uint32_t)8000000)),然後進行分頻係數的配置(M=8,N=336,P=2,Q=7),最終選擇PLL作為系統時鐘源。
初始化後: SYSCLK(系統時鐘):168MHz AHB:168MHz APB1: 42MHz APB2: 84MHz PLL: 168MHz
3.SysTick時鐘
SysTick屬於ARM Cortex-M3核心的一個“內設”,是一個擁有24位資料寬度的倒計數定時器,通常用來做延時或實時系統的心跳時鐘,節省資源。從時鐘源介面獲取時鐘驅動,在時鐘驅動下進行減一計數,減到0時觸發SysTick中斷。
相關函式: SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) 選擇Systick時鐘源
SysTick_Config(uint32_t ticks) 初始化Systick並開啟中斷, ticks為每隔多少個週期響應一次中斷。
思路:利用systick定時器為遞減計數器,設定初值並使能它後,它會每個1系統時鐘週期計數器減,計數到 0時,SysTick計數器自動重灌初值並繼續計數,同時觸發中斷。那麼每次計數器減到0,時間經過了:系統時鐘週期 *計數器初值。
採用SysTick_CLKSource_HCLK_Div8作為SysTick的時鐘源,頻率為21MHz,即每個週期用時1/21M。設定計數器初值為21,則每隔1/21M*21=1us就產生一次中斷。
3.程式碼實現
delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include <stm32f4xx.h>
void Delay_Init(void);
void Delay_ms(u32 nms);
void Delay_us(u32 nus);
extern void SysTick_Count(void);
#endif
delay.c
#include <delay.h>
static u32 delaytime=0;
void Delay_Init(void){
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
SysTick_Config(21);//every 1us create an interrupt
}
void Delay_ms(u32 nms){
delaytime=nms*1000;
while(!delaytime);
}
void Delay_us(u32 nus){
delaytime=nus;
while(!delaytime);
}
extern void SysTick_Count(void){
while(!delaytime){
delaytime--;
}
}
每1us產生中斷,呼叫SysTick_Handler()函式,對延時引數nus或nms進行處理。
注意在SysTick_Handler()的修改。
void SysTick_Handler(void)
{
SysTick_Count();
}