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