STM32筆記之 Systick(滴答定時器)

寫在前面: 本文章旨在總結備份、方便以後查詢,由於是個人總結,如有不對,歡迎指正;另外,內容大部分來自網絡、書籍、和各類手冊,如若侵權請告知,馬上刪帖致歉。

 

目錄

一、Systick介紹

二、Systick時鐘分析

三、Systick時鐘節拍代碼實現


 

一、Systick介紹

在 ARM Cortex-M3內核中有一個 Systick定時器,它是一個 24bit的定時器,可用於系統中的時鐘節拍,因此係統滴答定時器能用於 Cortex‐M3處理器芯片的快速移植(ps:正是因爲這一特點,大部分在運行 RTOS都基於 Systick來用作時鐘節拍,以便移植)

 

附上兩張 Cortex-M3簡視圖,同時再附上兩個關於 Cortex-M3核心瞭解的鏈接:

《STM32F10xxx Cortex-M3編程手冊》

《Cortex™-M3技術參考手冊》

 

二、Systick時鐘分析

根據時鐘樹,我們可以看見在 SYSCLK出來後,可能會認爲滴答定時器是系統時鐘的 1/8,其實不是,滴答定時器的時鐘既可以是 HCLK/8,也可以是 HCLK,這個是通過 CTRL寄存器進行設定的(可以通過查看《STM32F10xxx Cortex-M3編程手冊》找到)如下圖所示:

Systick 相關寄存器介紹:

實現思路:利用 systick定時器爲遞減計數器,設定初值並使能它後,它會每過一個系統時鐘週期計數器進行減,直到計數到 0時,SysTick計數器會自動重裝初值並繼續計數,同時觸發中斷。

初值計數:根據上一篇配置的時鐘使用 72MHz作爲系統時鐘,那麼計數器每次減一所用的時間是 1/72MHz,假設我們的計數器初值是72000,那麼每次計數器減到 0,時間經過(1/72M) * 72000 = 0.001,即1ms。(可以理解爲:72MHz的時鐘頻率,那他表示 1s計數72000000次(週期數),那 1ms就計數72000次,所以計數值爲72000) 

 

三、Systick時鐘節拍代碼實現

bsp.c 源文件

#include "bsp.h"


static __IO u32 TimingDelay = 0;

/* Setup SysTick Timer for 1 msec interrupts.
 ------------------------------------------
1. The SysTick_Config() function is a CMSIS function which configure:
   - The SysTick Reload register with value passed as function parameter.
   - Configure the SysTick IRQ priority to the lowest value (0x0F).
   - Reset the SysTick Counter register.
   - Configure the SysTick Counter clock source to be Core Clock Source (HCLK).
   - Enable the SysTick Interrupt.
   - Start the SysTick Counter.

2. You can change the SysTick Clock source to be HCLK_Div8 by calling the
   SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8) just after the
   SysTick_Config() function call. The SysTick_CLKSourceConfig() is defined
   inside the misc.c file.

3. You can change the SysTick IRQ priority by calling the
   NVIC_SetPriority(SysTick_IRQn,...) just after the SysTick_Config() function 
   call. The NVIC_SetPriority() is defined inside the core_cm3.h file.

4. To adjust the SysTick time base, use the following formula:
						
	 Reload Value = SysTick Counter Clock (Hz) x  Desired Time base (s)

   - Reload Value is the parameter to be passed for SysTick_Config() function
   - Reload Value should not exceed 0xFFFFFF
*/

/************************************************
函數名稱 : SysTick_Init
功    能 : 啓動系統滴答定時器 SysTick
參    數 : 無
返 回 值 : 無
*************************************************/
void SysTick_Init(void)
{
	/* SystemCoreClock / 1000    1ms中斷一次
	 * SystemCoreClock / 100000  10us中斷一次
	 * SystemCoreClock / 1000000 1us中斷一次
	 */

	/* 嘀嗒定時器每計數一次爲 1/72M,此處計數 72個數,即1uS中斷一次 */
	if(SysTick_Config(SystemCoreClock / 1000000))	// ST V3.5.0庫版本
	{ 
		/* Capture error */ 
		while(1);
	}
	
	// 關閉滴答定時器  
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	
}

/************************************************
函數名稱 : Delay_us
功    能 : us延時程序,1us爲一個單位
參    數 : nTime ---- 時間次數
返 回 值 : 無
*************************************************/
void Delay_us( __IO u32 nTime )
{ 
	TimingDelay = nTime;	

	// 使能滴答定時器  
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

	while( TimingDelay != 0 );
	
	// 關閉滴答定時器  
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	
}

/************************************************
函數名稱 : TimingDelay_Decrement
功    能 : 獲取節拍程序
參    數 : 無
返 回 值 : 無
注    意 : 在 SysTick 中斷函數 SysTick_Handler()調用
*************************************************/
void TimingDelay_Decrement(void)
{
	if(TimingDelay != 0x00)
	{ 
		TimingDelay--;
	}
	
}


/*---------------------------- END OF FILE ----------------------------*/


根據上面的註釋,選擇對應參數傳參進行 SysTick_Config() 配置,本篇是製作以微秒爲單位的延時定時器,所以傳入的參數爲 SystemCoreClock / 1000000次,SystemCoreClock的數值,在上一篇 STM32筆記之系統時鐘上有講到

 

bsp.h 頭文件

#ifndef __BSP_H
#define __BSP_H


#include "stm32f10x.h"

void SysTick_Init(void);
void Delay_us( __IO u32 nTime );
void TimingDelay_Decrement(void);
void SystemSoftReset(void);


#endif	/* __BSP_H */


/*---------------------------- END OF FILE ----------------------------*/

 

接着我們再在 stm32f10x_it.c 文件中的 SysTick_Handler()函數裏調用 TimingDelay_Decrement()函數進行計數遞減

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
	TimingDelay_Decrement();
}

最後,我們在主函數中調用函數 SysTick_Init() 完成初始化,就可以使用利用 Systick獲取節拍的時鐘延時 Delay_us()函數了

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