Section 7_SysTick系統定時器

Try-027發表於2020-10-07

1.SysTick定時器介紹

SysTick定時器也叫SysTick滴答定時器,它是Cortex-M4核心的一個外設,被嵌入在 NVIC 中。它是一個24 位向下遞減的定時器,每計數一次所需時間為1/SYSTICK,SYSTICK是系統定時器時鐘,它可以直接取自系統時鐘,還可以通過系統時鐘8分頻後獲取。當定時器計數到0時,將從LOAD 暫存器中自動重灌定時器初值,重新向下遞減計數,如此迴圈往復。如果開啟SysTick中斷的話,當定時器計數到0,將產生一箇中斷訊號。因此只要知道計數的次數就可以準確得到它的延時時間。

2.SysTick定時器暫存器

(1)CTRL暫存器

CTRL是SysTick定時器的控制及狀態暫存器。其相應位功能如下:
在這裡插入圖片描述

(2)LOAD暫存器

LOAD是SysTick定時器的重灌載數值暫存器。其相應位功能如下:在這裡插入圖片描述

(3)VAL暫存器

VAL是SysTick定時器的當前數值暫存器。其相應位功能如下:在這裡插入圖片描述

(4)CALIB暫存器

CALIB是SysTick定時器的校準數值暫存器。其相應位功能如下:在這裡插入圖片描述

3.SysTick定時器配置步驟

SysTick定時器的操作可以分為 4 步:
(1)設定SysTick定時器的時鐘源。
(2)設定SysTick定時器的重灌初始值(如果要使用中斷的話,就將中斷使能開啟)。
(3)清零SysTick定時器當前計數器的值。
(4)開啟SysTick定時器。

4.函式

SysTick_Init()函式:

void SysTick_Init(u8 SYSCLK)
{
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //函式在misc.c
	fac_us=SYSCLK/8;						//SYSCLK的8分頻 儲存1us所需的計數次數
	fac_ms=(u16)fac_us*1000;				//每個ms需要的systick時鐘數   
}

delay_us()函式:

void delay_us(u32 nus)                      //不能大於2的24次方/21  798000
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 				//時間載入	  		 
	SysTick->VAL=0x00;        				//清空計數器  
	SysTick->CTRL|=0x01 ;                   //開始倒數                     
	do
	{
		temp=SysTick->CTRL;                              
	}while((temp&0x01)&&!(temp&(1<<16)));	//等待時間到達   
	SysTick->CTRL&=~0x01; //關閉計數器                     
	SysTick->VAL =0X00;       				//清空計數器    
}

delay_nms()函式:

void delay_nms(u16 nms)                     //798
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;			//時間載入(SysTick->LOAD為24bit)
	SysTick->VAL =0x00;           			//清空計數器
	SysTick->CTRL|=0x01 ; //開始倒數 
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));	//等待時間到達   
	SysTick->CTRL&=~0x01; //關閉計數器
	SysTick->VAL =0X00;     		  		//清空計數器	  	    
} 

delay_ms()函式:

void delay_ms(u16 nms)
{	 	 
	u8 repeat=nms/540;		//這裡用540,是考慮到某些客戶可能超頻使用,                                           
						    //比如超頻到248M的時候,delay_nms最大隻能延時541ms左右了
	u16 remain=nms%540;                      
	while(repeat)                            
	{
		delay_nms(540);                      
		repeat--;
	}
	if(remain)delay_nms(remain);            
} 

在這裡插入圖片描述

5.程式設計

1.在Public建立兩個檔案

SysTick.h

#ifndef _SysTick_H
#define _SysTick_H

#include "system.h"

void SysTick_Init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);



#endif

SysTick.c

#include "SysTick.h"

static u8  fac_us=0;							//us延時倍乘數			   
static u16 fac_ms=0;							//ms延時倍乘數

/*******************************************************************************
* 函 數 名         : SysTick_Init
* 函式功能		   : SysTick初始化,SYSTICK的時鐘固定為AHB時鐘的1/8
* 輸    入         : SYSCLK:系統時脈頻率
* 輸    出         : 無
*******************************************************************************/
void SysTick_Init(u8 SYSCLK)
{
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
	fac_us=SYSCLK/8;						//SYSCLK的8分頻 儲存1us所需的計數次數
	fac_ms=(u16)fac_us*1000;				//每個ms需要的systick時鐘數   
}								    

/*******************************************************************************
* 函 數 名         : delay_us
* 函式功能		   : us延時,
* 輸    入         : nus:要延時的us數
					注意:nus的值,不要大於798915us(最大值即2^24/fac_us@fac_us=21)
* 輸    出         : 無
*******************************************************************************/
void delay_us(u32 nus)
{		
	u32 temp;	    	 
	SysTick->LOAD=nus*fac_us; 				//時間載入	  		 
	SysTick->VAL=0x00;        				//清空計數器
	SysTick->CTRL|=0x01 ; //開始倒數 	 
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));	//等待時間到達   
	SysTick->CTRL&=~0x01; //關閉計數器
	SysTick->VAL =0X00;       				//清空計數器 
}

/*******************************************************************************
* 函 數 名         : delay_nms
* 函式功能		   : ms延時,
* 輸    入         : nms:要延時的ms數
					注意:nms的值,SysTick->LOAD為24位暫存器,
					不要大於0xffffff*8*1000/SYSCLK
					對168M條件下,nms<=798ms 
* 輸    出         : 無
*******************************************************************************/
void delay_nms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;			//時間載入(SysTick->LOAD為24bit)
	SysTick->VAL =0x00;           			//清空計數器
	SysTick->CTRL|=0x01 ; //開始倒數 
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));	//等待時間到達   
	SysTick->CTRL&=~0x01; //關閉計數器
	SysTick->VAL =0X00;     		  		//清空計數器	  	    
}

/*******************************************************************************
* 函 數 名         : delay_ms
* 函式功能		   : ms延時,
* 輸    入         : nms:要延時的ms數 0~65535
* 輸    出         : 無
*******************************************************************************/
void delay_ms(u16 nms)
{	 	 
	u8 repeat=nms/540;		//這裡用540,是考慮到某些客戶可能超頻使用,
							//比如超頻到248M的時候,delay_nms最大隻能延時541ms左右了
	u16 remain=nms%540;
	while(repeat)
	{
		delay_nms(540);
		repeat--;
	}
	if(remain)delay_nms(remain);
} 

2.編寫main.c

main.c

/*******************************************************************************
* 實 驗 名		 : SysTick系統定時器
* 實驗說明       : 
* 連線方式       : 
* 注    意		 : SysTick驅動程式在SysTick.c內
*******************************************************************************/

#include "system.h"
#include "SysTick.h"
#include "led.h"

/*******************************************************************************
* 函 數 名         : main
* 函式功能		   : 主函式
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
int main()
{
	SysTick_Init(168);
	LED_Init();
	while(1)
	{
		led1=0;
		led2=1;
		delay_ms(500);  //精確延時500ms
		led1=1;
		led2=0;
		delay_ms(500);  //精確延時500ms
	}

3.新增misc.c防止報錯

在這裡插入圖片描述

在這裡插入圖片描述

相關文章