systick定時器的配置與應用解析

Systick定時器簡介

  • Systick定時器,是一個簡單的定時器,對於CM3,CM4內核芯片,都有Systick定時器。
  • Systick定時器常用來做延時,或者實時系統的心跳時鐘。這樣可以節省MCU資源,不用浪費一個定時器。比如UCOS中,分時複用,需要一個最小的時間戳,一般在STM32+UCOS系統中,都採用Systick做UCOS心跳時鐘。
  • Systick定時器就是系統滴答定時器,一個24 位的倒計數定時器,計到0 時,將從RELOAD
    寄存器中自動重裝載定時初值。只要不把它在SysTick 控制及狀態寄存器中的使能位清除,就永不停息。
  • SysTick定時器被捆綁在NVIC中,用於產生SYSTICK異常(異常號:15)。
  • Systick中斷的優先級也可以設置。

Systick定時器的4個Systick寄存器

  1. CTRL SysTick 控制和狀態寄存器
  2. LOAD SysTick 自動重裝載除值寄存器
  3. VAL SysTick 當前值寄存器
  4. CALIB SysTick 校準值寄存器摘自Cortex-M3權威指南(中文)

systick定時器時鐘源配置函數

#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)    //1111 1111 1111 1111 1111 1111 1111 1011
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)   //0000 0000 0000 0000 0000 0000 0000 0100
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || 
                                        ((SOURCE) == SysTick_CLKSource_HCLK_Div8))

void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
      /* Check the parameters(選擇參數) */ 
      //注:assert_param函數目的是判斷用戶輸入的參數是否在預設的範圍中,
      assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
      /*判斷用戶輸入的參數*/
      /*設置systick定時器的時鐘源爲內核時鐘(FCLK)HCLK,具體參數在前置的宏定義中*/
      if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
      { 
          SysTick->CTRL |= SysTick_CLKSource_HCLK;
      }
      /*設置systick定時器的時鐘源爲外部時鐘源(STCLK),HCLK的8分頻,具體參數在前置的宏定義中*/
      Else
      {
          SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; 
      }
}

用查詢寄存器的位值的方式實現延時
函數的前置定義

static u8   fac_us=0;     //定義了兩個靜態變量用來存儲systick定時器單位時間計數次數,詳見下文
static u16  fac_ms=0;
#define   SYSCLK_FREQ_72MHz  72000000
uint32_t  SystemCoreClock  =  SYSCLK_FREQ_72MHz;
#define SysTick_CTRL_ENABLE_Pos             0  
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos)                                         

Delay延時初始化函數

void delay_init()
{
    /*配置systick定時器的時鐘源爲外部時鐘HCLK的8分頻(9MHz)*/
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	
	fac_us=SystemCoreClock/8000000;   //設置參數
	fac_ms=(u16)fac_us*1000;          //設置參數
}	

毫秒延時函數

void delay_ms(u16 nms)
{ 
	u32 temp;  
	/*配置LOAD寄存器中存儲的倒計數次數的值,即nms毫秒要計數的次數*/
	SysTick->LOAD=(u32)nms*fac_ms;
	/*配置VAL寄存器當前值爲0,即清空倒數計數器*/
	SysTick->VAL =0x00; 
	/*配置CTRL寄存器的使能位爲1,即開始計數*/
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; 
	/*獲取CTRL寄存器的當前值存儲在上述變量中*/
	/*(temp&0x01)即獲取CTRL寄存器的使能位,定時器打開則此位爲1*/
	/*(temp&(1<<16))即獲取CTRL寄存器的位16,計數完成後此位爲1,通過!運算得到0*/
	/*通過&&運算上述值得到結束循環的條件爲:定時器關閉或者計數完成*/
	do{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));	
    /*配置CTRL寄存器的使能位爲0,即結束計數*/
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
	/*配置VAL寄存器當前值爲0,即清空倒數計數器*/    	
	SysTick->VAL =0X00;
}

微秒延時函數

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

通過delay_init的設置,SysTick定時器的時鐘源爲外部時鐘的8分頻(9MHz),即1秒鐘計數9000000次,每次計數的時間爲1/9000000秒,通過上述計算可以得出此配置下systick定時器的每毫秒計數爲9000次,每微秒計數次數爲9次。
而SystemCoreClock通過前置的宏定義可以知道等於72000000,由此可以得出fac_us = 9 ;fac_ms=9000。用戶調用delay_ms()函數時輸入的是毫秒數,該函數爲LOAD寄存器賦的值爲毫秒數X9000得到用戶輸入的毫秒數內計數systick定時器的計數次數,綜上fac_us和fac_ms對應着systick定時器單位時間計數次數。

文中函數和部分內容摘自正點原子stm32資料與官方庫函數

自學新手,個人總結,如有出入,請多指教!

發佈了13 篇原創文章 · 獲贊 2 · 訪問量 2025
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章