1. 程式人生 > >5.STM32F407ZG時鐘系統及定時器SYSTICK的使用

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(); 
}