STM32系统滴答定时器(systick)应用
一:系統(tǒng)滴答定時器(systick)
1.systick介紹
???? Systick就是一個定時器而已,只是它放在了NVIC中,主要的目的是為了給操作系統(tǒng)提供一個硬件上的中斷(號稱滴答中斷)。滴答中斷?這里來簡單地解釋一下。操作系統(tǒng)進行運轉(zhuǎn)的時候,也會有“心跳”。它會根據(jù)“心跳”的節(jié)拍來工作,把整個時間段分成很多小小的時間片,每個任務(wù)每次只能運行一個“時間片”的時間長度就得退出給別的任務(wù)運行,這樣可以確保任何一個任務(wù)都不會霸占整個系統(tǒng)不放。或者把每個定時器周期的某個時間范圍賜予特定的任務(wù)等,還有操作系統(tǒng)提供的各種定時功能,都與這個滴答定時器有關(guān)。因此,需要一個定時器來產(chǎn)生周期性的中斷,而且最好還讓用戶程序不能隨意訪問它的寄存器,以維持操作系統(tǒng)“心跳”的節(jié)律。?只要不把它在SysTick控制及狀態(tài)寄存器中的使能位清除,就永不停息。
?????知道systick在系統(tǒng)中的地位后,我們來了解systick的實現(xiàn)。這里只是舉例說明systick的使用。它有四個寄存器,筆者把它列出來:
??? SysTick->CTRL,??????? --控制和狀態(tài)寄存器
??? SysTick->LOAD,? ??????--重裝載寄存器
?? ?SysTick->VAL,?????? ???--當(dāng)前值寄存器
?? SysTick->CALIB,???? ???--校準值寄存器????
下圖有他們的分別描述:?????下圖引用地址:http://blog.csdn.net/marike1314/article/details/5673684
2.systick編程
????現(xiàn)在我們想通過Systick定時器做一個精確的延遲函數(shù),比如讓LED精確延遲1秒鐘閃亮一次。
????思路:利用systick定時器為遞減計數(shù)器,設(shè)定初值并使能它后,它會每個1系統(tǒng)時鐘周期計數(shù)器減,計數(shù)到?0時,SysTick計數(shù)器自動重裝初值并繼續(xù)計數(shù),同時觸發(fā)中斷。
那么每次計數(shù)器減到0,時間經(jīng)過了:系統(tǒng)時鐘周期?*計數(shù)器初值。我們使用72M作為系統(tǒng)時鐘,那么每次計數(shù)器減1所用的時間是1/72M,計數(shù)器的初值如果是72000,那么每次計數(shù)器減到0,時間經(jīng)過(1/72M)*72000= 0.001,即1ms。(簡單理解:用72M的時鐘頻率,即1s計數(shù)72M=72000000次,那1ms計數(shù)72000次,所以計數(shù)值為72000)?
?
首先,我們需要有一個72M的systick系統(tǒng)時鐘,那么,使用下面這個時鐘OK就?!
??? SystemInit();
????這個函數(shù)可以讓主頻運行到72M。可以把它作為systick的時鐘源。
????接著開始配置systick,實際上配置systick的嚴格過程如下:
??? 1、調(diào)用SysTick_CounterCmd()????? ?--失能SysTick計數(shù)器
??? 2、調(diào)用SysTick_ITConfig()????????? --失能SysTick中斷
??? 3、調(diào)用SysTick_CLKSourceConfig()? --設(shè)置SysTick時鐘源。
??? 4、調(diào)用SysTick_SetReload()???????? --設(shè)置SysTick重裝載值。
??? 5、調(diào)用SysTick_ITConfig()?????? ???--使能SysTick中斷
??? 6、調(diào)用SysTick_CounterCmd()?????? --開啟SysTick計數(shù)器??????????????????????????????????????????????????????
????這里大家一定要注意,必須使得當(dāng)前寄存器的值VAL等于0!
??? SysTick->VAL? = (0x00);只有當(dāng)VAL值為0時,計數(shù)器自動重載RELOAD。
接下來就可以直接調(diào)用Delay();函數(shù)進行延遲了。延遲函數(shù)的實現(xiàn)中,要注意的是,全局變量TimingDelay必須使用volatile,否則可能會被編譯器優(yōu)化。
下面我們來做一下程序分析:
(1)系統(tǒng)時鐘進配置
首先我們對系統(tǒng)時鐘進行了配置并且SetSysClock(void)函數(shù)使用72M作為系統(tǒng)時鐘;
為了方面看清代碼我選擇截圖:
(2)先來看看主函數(shù)
[plain]?view plaincopy(3)系統(tǒng)滴答定時器的配置--主角登場:
主函數(shù)中:?SysTick_Config(72000) ;滴答定時器的參數(shù)是72000即計數(shù)72000
(因為我們使用72M的時鐘頻率,即1s計數(shù)72M=72000000次,那1ms計數(shù)72000次,所以計數(shù)值為72000)?
在文件Core_cm3.h中
SysTick_Config函數(shù)的具體實現(xiàn)如下:
[html]?view plaincopy我們來看一下這句代碼:SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<<SYSTICK_ENABLE) | (1<<SYSTICK_TICKINT);?這是使能IRQ(普通中斷)和系統(tǒng)定時器,為什么要使能中斷和系統(tǒng)定時器呢?
下面我們來看一下stm32f10x_it.h文件中:
找到滴答定時器中斷函數(shù):SysTickHandler()
void SysTickHandler(void)
{
??? TimingDelay_Decrement();
}
從上文我們通過裝載的計數(shù)值72000知道每1ms發(fā)生一次中斷,在中斷函數(shù)中調(diào)用一個函數(shù)TimingDelay_Decrement();-----即每1ms發(fā)生中斷時就調(diào)用到此函數(shù);
下面我們來看看TimingDelay_Decrement();在干些什么?
[html]?view plaincopy通過上面幾個函數(shù)我們知道了,在調(diào)用Delay(500)即nTime=500;在后在Delay()函數(shù)中TimingDelay?=nTime;(即TimingDelay=500是它的初始值),再TimingDelay_Decrement(void)函數(shù)的作用就是把TimingDelay- -;每毫秒進行遞減直到減到0為止;這樣就起到一個延時的作用;
現(xiàn)在我們做出來的Delay(1),就是1毫秒延遲。Delay(1000)就是1秒。
? 我們來畫個圖,方便這幾個函數(shù)間關(guān)系的理解:
我們在返回到主函數(shù)main()中看這幾條語句:紅色標注de
[html]?view plaincopy經(jīng)過上面系統(tǒng)定時器的分析我們知道Delay(500);是延時500ms ;那么LED就是每隔500ms閃爍一次;
上面有關(guān)系統(tǒng)滴答定時器的應(yīng)用講解基本完畢!
?有關(guān)SysTick編譯后的源代碼包,(其實客官細心的話一經(jīng)發(fā)現(xiàn)上面代碼含有485通訊代碼,
只不過被暫時屏蔽掉了,下一節(jié)將講到)我放在我的資源里:http://download.csdn.net/detail/yx_l128125/4511622
?
下面我們來看看一下參考資料的問題,一邊對上面我寫的博客有更深入的理解:
《Cortex-M3權(quán)威指南》
《Cortex-M3 Technical Reference Manual》
Q:什么是SYSTick定時器?
SysTick?是一個24位的倒計數(shù)定時器,當(dāng)計到0時,將從RELOAD寄存器中自動重裝載定時初值。只要不把它在SysTick控制及狀態(tài)寄存器中的使能位清除,就永不停息。
Q:為什么要設(shè)置SysTick定時器?
(1)產(chǎn)生操作系統(tǒng)的時鐘節(jié)拍
SysTick定時器被捆綁在NVIC中,用于產(chǎn)生SYSTICK異常(異常號:15)。在以前,大多操作系統(tǒng)需要一個硬件定時器來產(chǎn)生操作系統(tǒng)需要的滴答中斷,作為整個系統(tǒng)的時基。因此,需要一個定時器來產(chǎn)生周期性的中斷,而且最好還讓用戶程序不能隨意訪問它的寄存器,以維持操作系統(tǒng)“心跳”的節(jié)律。
(2)便于不同處理器之間程序移植。
Cortex‐M3處理器內(nèi)部包含了一個簡單的定時器。因為所有的CM3芯片都帶有這個定時器,軟件在不同?CM3器件間的移植工作得以化簡。該定時器的時鐘源可以是內(nèi)部時鐘(FCLK,CM3上的自由運行時鐘),或者是外部時鐘(?CM3處理器上的STCLK信號)。
不過,STCLK的具體來源則由芯片設(shè)計者決定,因此不同產(chǎn)品之間的時鐘頻率可能會大不相同,你需要檢視芯片的器件手冊來決定選擇什么作為時鐘源。SysTick定時器能產(chǎn)生中斷,CM3為它專門開出一個異常類型,并且在向量表中有它的一席之地。它使操作系統(tǒng)和其它系統(tǒng)軟件在CM3器件間的移植變得簡單多了,因為在所有CM3產(chǎn)品間對其處理都是相同的。
(3)作為一個鬧鈴測量時間。
SysTick定時器除了能服務(wù)于操作系統(tǒng)之外,還能用于其它目的:如作為一個鬧鈴,用于測量時間等。要注意的是,當(dāng)處理器在調(diào)試期間被喊停(halt)時,則SysTick定時器亦將暫停運作。
Q:Systick如何運行?
首先設(shè)置計數(shù)器時鐘源,CTRL->CLKSOURCE(控制寄存器)。設(shè)置重載值(RELOAD寄存器),清空計數(shù)寄存器VAL(就是下圖的CURRENT)。置CTRL->ENABLE位開始計時。
如果是中斷則允許Systick中斷,在中斷例程中處理。如采用查詢模式則不斷讀取控制寄存器的COUNTFLAG標志位,判斷是否計時至零。或者采取下列一種方法
當(dāng)SysTick定時器從1計到0時,它將把COUNTFLAG位置位;而下述方法可以清零之:
1.?讀取SysTick控制及狀態(tài)寄存器(STCSR)
2.?往SysTick當(dāng)前值寄存器(STCVR)中寫任何數(shù)據(jù)
只有當(dāng)VAL值為0時,計數(shù)器自動重載RELOAD。
Q:如何使用SysTicks作為系統(tǒng)時鐘?
SysTick?的最大使命,就是定期地產(chǎn)生異常請求,作為系統(tǒng)的時基。OS都需要這種“滴答”來推動任務(wù)和時間的管理。如欲使能SysTick異常,則把STCSR.TICKINT置位。另外,如果向量表被重定位到SRAM中,還需要為SysTick異常建立向量,提供其服務(wù)例程的入口地址。
二:就在前一段時間,有人突然問我SysTick_Handler(void)這個定時器中斷處理函數(shù)是怎么定義的?根據(jù)以往的經(jīng)驗,我感覺在底層應(yīng)該會有一個類似于函數(shù)聲明的東西的存在,但是往下跟程序的話,一直都沒有找到相應(yīng)的定義或者聲明,那么究竟SysTick_Handler這個函數(shù)怎么來的呢?是不是可以人為的做修改呢?給我的第一感覺是,肯定是可以做修改的,畢竟只是一個 函數(shù) 的名字而已,于是就翻看LPC1114的數(shù)據(jù)手冊,結(jié)合網(wǎng)上的一些參考文件,去理清楚到底是怎么回事。
那么還是非常容易找到SysTick_Handler()這個函數(shù)的位置的,如下圖所示:
? ? ??說到了定時器中斷處理函數(shù),那么定時器Systick是怎樣來進行設(shè)置的呢?
? ? 在系統(tǒng)定時器的四個寄存器中,SYST_CALIB為校準寄存器,這個是在出廠之前就已經(jīng)配置好了的,我們不必考慮這個寄存器。那么我們一共需要配置3個寄存器就可以完成我們工作的模塊。
? ? CSR寄存器用到的位有4個,bit0用于是否開啟定時器,置1的話就是允許,bit1用于控制是否產(chǎn)生中斷,該位置為1為允許產(chǎn)生中斷,bit2用于設(shè)置定時器的時鐘源,設(shè)為1,定時器的時鐘源為主時鐘,反之設(shè)為0的話定時器的時鐘源為主時鐘的一半。
(2)SYST_RVR?? 寄存器? ?
? ? RVR寄存器用到0~23位,這個值是定時器倒計時的初始值,打開定時器以后,就會從這里設(shè)置的值倒計時到0,倒計時到0以后,又會從此值開始倒計時。
(3)SYST_CVR? 寄存器???
系統(tǒng)定時器函數(shù)——SysTick_Config()函數(shù)
總結(jié)
以上是生活随笔為你收集整理的STM32系统滴答定时器(systick)应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: STM32之DMA
- 下一篇: STM32F030控制蜂鸣器定时响和控制