STM32 Systick 編程及應用
一、 systick介紹
Systick 就是一個(gè)定時(shí)器而已,只是它放在了NVIC 中,主要的目的是為了給操作系統提供一個(gè)硬件上的中斷(號稱(chēng)滴答中斷)。沒(méi)有學(xué)過(guò)操作系統的同學(xué), 可能會(huì )很郁悶,啥叫滴答中斷?這里來(lái)簡(jiǎn)單地解釋一下:操作系統進(jìn)行運轉的時(shí)候,也會(huì )有"心跳"。它會(huì )根據"心跳"的節拍來(lái)工作,把整個(gè)時(shí)間段分成很多小小的時(shí)間片,每個(gè)任務(wù)每次只能運行一個(gè)"時(shí)間片"的時(shí)間長(cháng)度就得退出給別的任務(wù)運行,這樣可以確保任何一個(gè)任務(wù)都不會(huì )霸占整個(gè)系統不放。這個(gè)心跳,可以通過(guò)定時(shí)器來(lái)周期性觸發(fā),而這個(gè)定時(shí)器就是systick。很明顯,這個(gè)"心跳" 是不允許任何人來(lái)隨意地訪(fǎng)問(wèn)和修改的。只要不把它在SysTick 控制及狀態(tài)寄存器中的使能位清除,就永不停息。
知道systick 在系統中的地位后,我們來(lái)了解systick 的實(shí)現。注意,本期教程并沒(méi)有講述systick 如何在操作系統中的運行,因為這對初學(xué)者來(lái)說(shuō)比較復雜。我們這里只是舉例說(shuō)明systick 的使用。它有四個(gè)寄存器,筆者把它列出來(lái):
STK_CSR, 0xE000E010 -- 控制寄存器
STK_LOAD, 0xE000E014 -- 重載寄存器
STK_VAL, 0xE000E018 -- 當前值寄存器
STK_CALRB, 0xE000E01C -- 校準值寄存器
以下部分參考互聯(lián)網(wǎng)的一篇文章,網(wǎng)址為:
http://home.eeworld.com.cn/my/space.php?uid=116357&do=blog&id=31714
感謝作者"416561760 的博客"提供如此詳細的寄存器說(shuō)明的文章。
1、STK_CSR控制寄存器:寄存器內有4 個(gè)位具有意義
第0 位:ENABLE,Systick 使能位(0:關(guān)閉Systick 功能;1:開(kāi)啟Systick功能)
第1 位:TICKINT,Systick 中斷使能位(0:關(guān)閉Systick 中斷;1:開(kāi)啟Systick 中斷)
第2 位:CLKSOURCE,Systick 時(shí)鐘源選擇(0:使用HCLK/8 作為Systick時(shí)鐘;1:使用HCLK 作為Systick 時(shí)鐘)
第3 位:COUNTFLAG,Systick 計數比較標志,如果在上次讀取本寄存器后,SysTick 已經(jīng)數到了0,則該位為1。如果讀取該位,該位將自動(dòng)清零。
2、STK_LOAD 重載寄存器
Systick 是一個(gè)遞減的定時(shí)器,當定時(shí)器遞減至0 時(shí),重載寄存器中的值就 會(huì )被重裝載,繼續開(kāi)始遞減。STK_LOAD 重載寄存器是個(gè)24 位的寄存器最大計數0xFFFFFF。
3、STK_VAL當前值寄存器
也是個(gè)24 位的寄存器,讀取時(shí)返回當前倒計數的值,寫(xiě)它則使之清零,同時(shí)還會(huì )清除在SysTick 控制及狀態(tài)寄存器中的COUNTFLAG 標志。
4、STK_CALRB 校準值寄存器
位31 NOREF :1=沒(méi)有外部參考時(shí)鐘(STCLK 不可用)0=外部參考時(shí)鐘可用
位30 SKEW:1=校準值不是準確的1ms 0=校準值是準確的1ms
位[23:0] :Calibration value
Indicates the calibration value when the SysTick counter runs on HCLK max/8 as external clock. The value is product dependent, please refer to the Product Reference Manual, SysTick Calibration Value section. When HCLK is programmed at the maximum frequency, the SysTick period is 1ms. If calibration information is not known, calculate the calibration value
required from the frequency of the processor clock or external clock.
二、systick編程
現在我們想通過(guò)Systick 定時(shí)器做一個(gè)精確的延遲函數,比如讓LED 精確延遲1 秒鐘閃亮一次。
思路:利用systick 定時(shí)器為遞減計數器,設定初值并使能它后,它會(huì )每個(gè)系統時(shí)鐘周期計數器減1,計數到0 時(shí),SysTick 計數器自動(dòng)重裝初值并繼續計數,同時(shí)觸發(fā)中斷。
那么每次計數器減到0,時(shí)間經(jīng)過(guò)了:系統時(shí)鐘周期* 計數器初值。我們使用72M 作為系統時(shí)鐘,那么每次計數器減1 所用的時(shí)間是1/72M,計數器的初值如果是72000,那么每次計數器減到0,時(shí)間經(jīng)過(guò)(1/72M) * 72000 = 0.001m,即1ms。
現在我們做出來(lái)的Delay(1),就是 1 毫秒延遲。Delay(1000)就是1 秒。
有了以上的思路后,systick 的編程非常簡(jiǎn)單。
首先,我們需要有一個(gè)72M 的systick 系統時(shí)鐘,那么,使用下面這個(gè)時(shí)鐘就OK!
SystemInit();
這個(gè)函數可以讓主頻運行到72M??梢园阉鳛閟ystick 的時(shí)鐘源。為了配合演示,可以使用LED 顯示來(lái)做,于是我們設置了GPIO_Config(); 初始化函數,初始化了芯達STM32 開(kāi)發(fā)板上的LED4 燈。接著(zhù)開(kāi)始配置systick,實(shí)際上配置systick 的嚴格過(guò)程如下:
使用ST 的函數庫使用systick 的方法:
1、調用SysTick_CounterCmd() -- 失能SysTick 計數器
2、調用SysTick_ITConfig () -- 失能SysTick 中斷
3、調用SysTick_CLKSourceConfig() -- 設置SysTick 時(shí)鐘源。
4、調用SysTick_SetReload() -- 設置SysTick 重裝載值。
5、調用SysTick_ITConfig () -- 使能SysTick 中斷
6、調用SysTick_CounterCmd() -- 開(kāi)啟SysTick 計數器
這里大家一定要注意,必須使得當前寄存器的值VAL 等于0!
SysTick->VAL = (0x00);
只有當VAL 值為0 時(shí),計數器自動(dòng)重載RELOAD。
接下來(lái)就可以直接調用Delay();函數進(jìn)行延遲了。延遲函數的實(shí)現中,要注意的是,全局變量TimingDelay 必須使用volatile,否則可能會(huì )被編譯器優(yōu)化。
以下是一篇systick的問(wèn)答篇總結,摘抄于網(wǎng)絡(luò ),希望對您的理解有幫助。
文章網(wǎng)址:http://blog.ednchina.com/jielove2003/768642/message.aspx
Q:什么是SYSTick定時(shí)器?
SysTick 是一個(gè)24 位的倒計數定時(shí)器,當計到0 時(shí),將從RELOAD 寄存器中自動(dòng)重裝載定時(shí)初值。只要不把它在SysTick 控制及狀態(tài)寄存器中的使能位清除,就永不停息。
Q:為什么要設置SysTick定時(shí)器?
(1)產(chǎn)生操作系統的時(shí)鐘節拍
SysTick定時(shí)器被捆綁在NVIC中,用于產(chǎn)生SYSTICK異常(異常號:15)。在以前,大多操作系統需要一個(gè)硬件定時(shí)器來(lái)產(chǎn)生操作系統需要的滴答中斷,作為整個(gè)系統的時(shí)基。因此,需要一個(gè)定時(shí)器來(lái)產(chǎn)生周期性的中斷,而且最好還讓用戶(hù)程序不能隨意訪(fǎng)問(wèn)它的寄存器,以維持操作系統"心跳"的節律。
(2)便于不同處理器之間程序移植。
Cortex‐M3 處理器內部包含了一個(gè)簡(jiǎn)單的定時(shí)器。因為所有的CM3 芯片都帶有這個(gè)定時(shí)器,軟件在不同CM3 器件間的移植工作得以化簡(jiǎn)。該定時(shí)器的時(shí)鐘源可以是內部時(shí)鐘(FCLK,CM3 上的自由運行時(shí)鐘),或者是外部時(shí)鐘( CM3 處理器上的STCLK 信號)。
不過(guò),STCLK 的具體來(lái)源則由芯片設計者決定,因此不同產(chǎn)品之間的時(shí)鐘頻率可能會(huì )大不相同,你需要檢視芯片的器件手冊來(lái)決定選擇什么作為時(shí)鐘源。SysTick 定時(shí)器能產(chǎn)生中斷,CM3 為它專(zhuān)門(mén)開(kāi)出一個(gè)異常類(lèi)型,并且在向量表中有它的一席之地。它使操作系統和其它系統軟件在CM3 器件間的移植變得簡(jiǎn)單多了,因為在所有CM3 產(chǎn)品間對其處理都是相同的。
(3)作為一個(gè)鬧鈴測量時(shí)間。
SysTick 定時(shí)器除了能服務(wù)于操作系統之外,還能用于其它目的:如作為一個(gè)鬧鈴,用于測量時(shí)間等。要注意的是,當處理器在調試期間被喊停(halt)時(shí),則SysTick 定時(shí)器亦將暫停運作。
Q:Systick如何運行?
首先設置計數器時(shí)鐘源,CTRL->CLKSOURCE(控制寄存器)。設置重載值(RELOAD 寄存器),清空計數寄存器VAL(就是下圖的CURRENT)。置CTRL->ENABLE 位開(kāi)始計時(shí)。
如果是中斷則允許Systick 中斷,在中斷例程中處理。如采用查詢(xún)模式則不斷讀取控制寄存器的COUNTFLAG 標志位,判斷是否計時(shí)至零?;蛘卟扇∠铝幸环N方法
當SysTick 定時(shí)器從1 計到0 時(shí),它將把COUNTFLAG 位置位;而下述方法可以清零之:
1. 讀取SysTick 控制及狀態(tài)寄存器(STCSR)
2. 往SysTick 當前值寄存器(STCVR)中寫(xiě)任何數據
只有當VAL 值為0 時(shí),計數器自動(dòng)重載RELOAD。
Q:如何使用SysTicks作為系統時(shí)鐘?
SysTick 的最大使命,就是定期地產(chǎn)生異常請求,作為系統的時(shí)基。OS 都需要這種"滴答"來(lái)推動(dòng)任務(wù)和時(shí)間的管理。如欲使能SysTick 異常,則把STCSR.TICKINT 置位。另外,如果向量表被重定位到SRAM 中,還需要為SysTick 異常建立向量,提供其服務(wù)例程的入口地址。
Q:如何使用SysTick完成一段延時(shí)?
查詢(xún)方式參考:http://blog.ednchina.com/atom6037/188271/message.aspx
中斷方式參考:
初始化函數SysTick_Configuration(void)放在while()循環(huán)外,執行一次:
view plaincopy to clipboardprint?
1. void SysTick_Configuration(void)
2. {
3. /* Select AHB clock(HCLK) as SysTick clock source 設置AHB 時(shí)鐘為SysTick 時(shí)鐘*/
4. SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
5.
6. /* Set SysTick Priority to 3 設置SysTicks 中斷搶占優(yōu)先級3, 從優(yōu)先級0*/
7. NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 3, 0);
8.
9. /* SysTick interrupt each 1ms with HCLK equal to 72MHz 每1ms 發(fā)生一次SysTick 中斷*/
10. SysTick_SetReload(72000);
11.
12. /* Enable the SysTick Interrupt */
13. SysTick_ITConfig(ENABLE);
14. }
延時(shí)函數,需要延時(shí)處調用:
view plaincopy to clipboardprint?
1. void Delay(u32 nTime)
2. {
3. /* Enable the SysTick Counter 允許SysTick 計數器*/
4. SysTick_CounterCmd(SysTick_Counter_Enable);
5.
6. TimingDelay = nTime;
7.
8. while(TimingDelay != 0)
9. ; //等待計數至0
10.
11. /* Disable the SysTick Counter 禁止SysTick 計數器*/
12. SysTick_CounterCmd(SysTick_Counter_Disable);
13. /* Clear the SysTick Counter 清零SysTick 計數器*/
14. SysTick_CounterCmd(SysTick_Counter_Clear);
15. }
中斷函數,定時(shí)器減至零時(shí)調用,放在stm32f10x_it.c 文件中
view plaincopy to clipboardprint?
1. void SysTickHandler(void)
2. {
3. TimingDelay--;
4. }
評論