專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> STM32 >> 瀏覽文章

第三講 STM32 SysTick---系統(tǒng)滴答定時(shí)器

作者:鵬心飛漾   來源:轉(zhuǎn)自鵬心飛漾   點(diǎn)擊數(shù):  更新時(shí)間:2014年07月28日   【字體:

一、Systick簡介

    Systick也叫系統(tǒng)滴答定時(shí)器,滴答定時(shí)器就是一個(gè)非常基本的倒計(jì)時(shí)定時(shí)器。它存在的意義是為系統(tǒng)提供一個(gè)時(shí)基,能夠給操作系統(tǒng)提供一個(gè)硬件上的中斷。使用Systick能夠精準(zhǔn)延時(shí),對(duì)于時(shí)間要求嚴(yán)格的場所,意義十分重大,我將寫一個(gè)流水燈改進(jìn)版----精確延時(shí)(可調(diào)控)的流水燈。
二、Systick timer
    Systick是一個(gè)24位的定時(shí)器,一次最多可以計(jì)數(shù)2^24個(gè)時(shí)鐘脈沖,這個(gè)脈沖計(jì)數(shù)值保存在當(dāng)前計(jì)數(shù)值寄存器STK_VAL(Systick current value register)中,只能向下計(jì)數(shù),每接收到一個(gè)時(shí)鐘脈沖,STK_VAL的值就會(huì)向下減1,當(dāng)減到0時(shí),硬件會(huì)自動(dòng)把重裝載寄存器STK_LOAD(Systick reload value register)中保存的數(shù)據(jù)加載到STK_VAL,重新開始向下計(jì)數(shù)。如果STK_VAL的值被減至0時(shí),會(huì)觸發(fā)異常產(chǎn)生中斷。
三、相關(guān)寄存器介紹
除了上面說的STK_VAL,下面帶大家了解相關(guān)的寄存器和寄存器位。
1.  SysTick_CSR       控制狀態(tài)寄存器
 


Bit0: ENABLE
          SysTick timer的使能位,1使能Systick timer,0關(guān)閉Systick timer
Bit1: TICKINT
          異常觸發(fā)使能位,TICKINT=1,STK_VAL計(jì)數(shù)到0觸發(fā)異常;TICKINT=0,不觸發(fā)異常
Bit2: CLKSOURCE
          Systick時(shí)鐘選擇位,SysTick = 1,時(shí)鐘為AHB時(shí)鐘;0時(shí)鐘位AHB/8
Bit16:COUNTFLAG
          計(jì)數(shù)為0標(biāo)志位, 當(dāng)STK_VAL計(jì)數(shù)到0,此標(biāo)志位會(huì)被置1       
 

2. SysTick_LOAD      重裝載寄存器
 
0-23 24位的重裝值,這也是為什么只能計(jì)數(shù)到2^24
3.  SysTick_VAL    當(dāng)前值寄存器


 
 
4.  SysTick_CALRB    校準(zhǔn)寄存器

 
由于我們要寫精確延時(shí)的LED流水燈,所以我們需要使用Systick進(jìn)行精確延時(shí),理論上它的最小計(jì)時(shí)單位為AHB的時(shí)鐘周期,1/72000000秒,72分之一微秒。
 
我們?cè)谧蛱炝魉疅舻幕A(chǔ)上,新建兩個(gè)文件,SysTick.c和SysTick.h
具體代碼如下
SysTick.h
#ifndef __SYSTICK_H__
#define __SYSTICK_H__
#include "stm32f10x.h"
void SysTick_Init(void);
void Delay_us(__IO u32 nTime);
#endif
 
SysTick.c
#include "SysTick.h"
#include "stm32f10x.h"
static __IO u32 TimingDelay;
void SysTick_Init(void)
{
 if(SysTick_Config(SystemCoreClock/100000))
 {
  while(1);
 }
 //關(guān)閉滴答定時(shí)器
 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
void TimingDelay_Decrement(void)
{
 if(TimingDelay != 0x00)
 {
  TimingDelay--;
 }
}
void Delay_us(__IO u32 nTime)
{
 TimingDelay = nTime;
 
 //使能滴答定時(shí)器
 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
 
 while(TimingDelay != 0);
}
 
中斷函數(shù),在stm32f10xit.c
void SysTick_Handler(void)
{
 TimingDelay_Decrement();
}
 
修改main.c如下
#include "stm32f10x.h"
#include "led.h"
#include "SysTick.h"


int main(void)
{
 //LED端初始化
 LED_GPIO_Config();
 
 //配置SysTick為10us中斷一次
 SysTick_Init();
 
 while(1)
 {
  LED1(0);
  Delay_us(50000);
  LED1(1);
  
  LED2(0);
  Delay_us(50000);
  LED2(1);
  
  LED3(0);
  Delay_us(50000);
  LED3(1);
  
  LED4(0);
  Delay_us(50000);
  LED4(1);
 }
}
這里面只有兩個(gè)函數(shù),SysTick_Init()和Delay_us(),一個(gè)是配置SysTick定時(shí)器,一個(gè)是進(jìn)行精確延時(shí)
中斷函數(shù)也只是運(yùn)行了一個(gè)自定義函數(shù),看看不難理解
SysTick_Config(SystemCoreClock/100000);
SystemCoreClock是系統(tǒng)時(shí)鐘的宏,SystemCoreClock = 72000000
我們的計(jì)時(shí)總時(shí)間 T = tick * (1/f),tick為SysTick_Config()的輸入?yún)?shù)
 
1/f為SysTick timer使用的時(shí)鐘源的時(shí)鐘周期,f為該時(shí)鐘源的時(shí)鐘頻率。
上面的語句中:tick = SystemCoreClock/100000=720,表示720個(gè)時(shí)鐘周期中斷一次,1/f是時(shí)鐘周期的時(shí)間,1/f = 1/72us,所以T = 720*(1/72) = 10us
SysTick_CTRL_ENABLE_Msk,這是一個(gè)宏,用來指示寄存器的特定位置或進(jìn)行位屏蔽用的,那么他是如何定義的呢?


其中的寄存器位指示宏:SysTick_xxx_Pos, 宏展開后為xxx在相應(yīng)寄存器中的位置,如控制SysTick時(shí)鐘源的SysTick_CTRL_CLKSOURCE_Pos,宏展開后為2,正好是SysTick_CSR中的Bit2
寄存器的位屏蔽宏:SysTick_xxx_Msk,宏展開是xxx的位全部置1后,左移SysTick_xxx_Pos位,1ul使之無符號(hào)長整型,上圖中SysTick_CTRL_CLKSOURCE_Msk,宏展開為1ul<<SysTick_CTRL_CLKSOURCE_Pos,即1左移2位,得到的只有Bit2:CLKSOURCE位被置1,而其它位為0,這樣搭配& | 能夠很方便的修改寄存器的某些位,這樣就程序就不難理解了.就說這么多吧,已經(jīng)講得很多了,不懂得自己想想,琢磨一下就通了。

 

關(guān)閉窗口

相關(guān)文章