1.系統定時器介紹
總體概述
SysTick 定時器被捆綁在 NVIC 中,用于產生SysTick異常(異常號:15)。
SysTick 中斷對系統尤其重要,操作系統提供的各種定時功能都與這個滴答定時器有關。因此。需要一個定時器來產生周期性的中斷,而且最好讓用戶不能隨意訪問它的寄存器以維持系統“心跳”的節律。
SysTick 定時器能產生中斷,CM3 為它專門開出一個異常類型,并且在向量表中有它的一席之地。它使操作系統和其他系統軟件在 CM3 器件之間的移植變得簡單,因為在所有的 CM3 產品中,SysTick的處理方式都是相同的。SysTick定時器不僅能服務于操作系統,還能用于延時,鬧鐘以及測量時間。
原理分析
SysTick 是一個24位的寄存器,因此它一次最多可以計數2的24次方個時鐘脈沖。
用戶定義一個時鐘脈沖的值之后,這個值被送入計數寄存器中,每收到一個脈沖,這個值就減1,當這個值減小到0時就觸發異常。
2.程序代碼
程序目的:使用 SysTick 延時控制 LED 燈的閃爍。
<------------------------------------------------------------->
systick.h源代碼:
#ifndef __SYSTICK_H
#define __SYSTICK_H
#include "stm32f10x.h"
void SysTick_Init(void);
void Delay_ms( __IO u32 nTime );
#endif
systick.c源代碼:
/***************************************
程序的本意是想在初始化時關閉滴答定時器
在每次使用延時函數時再把它打開
這兩句代碼去掉,程序也可以正常運行
***************************************/
#include "stm32f10x.h"
#include "systick.h"
static __IO u32 TimingDelay;
void SysTick_Init(void)
{
/**********************************
StstemFrequency / 1000 1ms
StstemFrequency / 100000 10us
StstemFrequency / 1000000 1us
***********************************/
if( SysTick_Config( SystemCoreClock / 1000 ) ) //ST3.5.0 庫版本
{
/* Capture error */
while ( 1 );
}
/* 關閉滴答定時器 */
//SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_MSK;
}
void Delay_ms( __IO u32 nTime )
{
TimingDelay = nTime;
/* 使能滴答定時器 */
//SysTick->CTRL |= SysTick_CTRL_ENABLE_MSK;
while( TimingDelay != 0 );
}
void TimingDelay_Decrement(void)
{
if( TimingDelay != 0x00 )
{
TimingDelay --;
}
}
stm32f103x_it.c源代碼:
/******************************************************************
在stm32f103x_it.c文件中可以找到 SysTick_Handler 函數
這個函數是系統定義好的,在里面調用 TimingDelay_Decrement 函數即可
因為 TimingDelay_Decrement 函數是在別的地方定義的
所以要在 stm32f103x_it.c 中加上以下聲明:
extern void TimingDelay_Decrement(void);
******************************************************************/
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
主函數main.c源代碼:
#include "stm32f10x.h"
#include "led.h"
#include "systick.h"
int main(void)
{
LED_Init();
SysTick_Init();
LED2(ON);
while(1)
{
Delay_ms(200);
LED2_REV;
LED3_REV;
}
}
3.補充
在延時的函數中我們會發現 TimingDelay 這個變量,它的定義是這樣的:
static __IO u32 TimingDelay;
static:
static 修飾符好理解,它用來聲明靜態變量,相當于全局變量。
我們知道,C/C++的變量都有一個作用域。舉個例子,一個函數聲明的變量只存在于它的執行過程中,這時變量保存在棧里。一旦退出函數,變量也就死亡了。而用 static 修飾的變量是存儲在堆里的,知道整個程序結束它才會消失。
因此在我們進行延時的時候,需要讓延時剩下的脈沖數一直存在于程序中,這樣才能完成延時。
__IO:
__IO 本身是不存在于 C 語言中的,它是一個另一個修飾符的宏定義:
#define __IO volatile
如果一個值有可能會被意想不到的改變,那么它有必要被定義為 volatile。
這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。