SysTick定时器的一个简单应用
?
SysTick即為系統(tǒng)定時(shí)器,又稱嘀嗒定時(shí)器,是Cortex-M3內(nèi)核的一個(gè)外設(shè),集成在NVIC中。SysTick是一個(gè)24bit的向下遞減的計(jì)數(shù)器,每計(jì)數(shù)一次的時(shí)間為1/SYSCLK(SYSCLK一般為72MHz)。操作系統(tǒng)需要執(zhí)行多任務(wù)管理,用SysTick產(chǎn)生中斷,確保單個(gè)任務(wù)不會(huì)鎖定整個(gè)系統(tǒng)。同時(shí)SysTick還可用于鬧鐘定時(shí)、時(shí)間測(cè)量等。
由于Cortex-M3芯片都有SysTick,所以軟件可以很容易地在Cortex-M3的產(chǎn)品間移植。
我們待會(huì)兒將利用SysTick產(chǎn)生1s的時(shí)基,讓LED一秒鐘閃爍一次,以完成SysTick的定時(shí)實(shí)驗(yàn)。
注:本文所用芯片為stm32f103。
SysTick寄存器
SysTick定時(shí)器由四個(gè)寄存器控制,如圖7-1所示。
?
圖7-1?
上圖是對(duì)四個(gè)寄存器各個(gè)位的描述。其中最后一個(gè)校準(zhǔn)值寄存器(STK_CALIB)在定時(shí)實(shí)驗(yàn)中并沒(méi)有用到,這里暫且不介紹,有興趣的讀者可以自行查找其他資料閱讀。
編程要點(diǎn)
SysTick屬于內(nèi)核外設(shè),其相關(guān)的寄存器定義和庫(kù)函數(shù)都在core_cm3.h中。如圖7-2為core_cm3.h頭文件里配置SysTick的源碼截圖。
圖7-2
SysTick_Config()庫(kù)函數(shù)即是按照上述的編程要點(diǎn)完成SysTick配置的。我們?cè)趯?shí)際項(xiàng)目中時(shí)可以直接調(diào)用這個(gè)庫(kù)函數(shù)來(lái)完成配置。而形參ticks用來(lái)設(shè)置STK_LOAD的值,最大不超過(guò)2^24。然后配置中斷優(yōu)先級(jí),清空STK_VAL,最后配置STK_CTRL。其中,在配置中斷優(yōu)先級(jí)時(shí)調(diào)用了NVIC_SetPriority()庫(kù)函數(shù),傳入的優(yōu)先級(jí)實(shí)參為(1<<__NVIC_PRIO_BITS) - 1,其中宏__NVIC_PRIO_BITS為4,則可得其優(yōu)先級(jí)為15,則可以看出其默認(rèn)設(shè)置的優(yōu)先級(jí)在內(nèi)核外設(shè)中是最低的。
那么如果我們同時(shí)設(shè)置了內(nèi)核外設(shè)和片上外設(shè)的優(yōu)先級(jí),該如何判斷孰高孰低呢?
在專欄(stm32):stm32中斷初識(shí)與實(shí)踐(上)里說(shuō)過(guò),在配置外設(shè)中斷優(yōu)先級(jí)時(shí),需要先分組,再設(shè)置搶占優(yōu)先級(jí)及子優(yōu)先級(jí),那么我們把內(nèi)核外設(shè)的優(yōu)先級(jí)也用同一配置方式分解為這三個(gè)部分。
假設(shè)配置一個(gè)外設(shè)的中斷優(yōu)先級(jí)分組為3,搶占優(yōu)先級(jí)為2,子優(yōu)先級(jí)為1,而SysTick優(yōu)先級(jí)為4。則將SysTick優(yōu)先級(jí)4轉(zhuǎn)換為二進(jìn)制,為0100(0b),在分組為3時(shí),SysTick搶占優(yōu)先級(jí)為010(0b),即為2,子優(yōu)先級(jí)為0。我們先比較搶占優(yōu)先級(jí),發(fā)現(xiàn)相同,那么比較子優(yōu)先級(jí),此時(shí)SysTick子優(yōu)先級(jí)為0,而我們假設(shè)的外部中斷子優(yōu)先級(jí)為1,所以SysTick優(yōu)先級(jí)大于假設(shè)的外設(shè)優(yōu)先級(jí)(數(shù)值越小,優(yōu)先級(jí)越高)。
中斷時(shí)間計(jì)算
SysTick的計(jì)數(shù)器執(zhí)行的是倒計(jì)時(shí),我們要計(jì)算中斷計(jì)數(shù)時(shí)間,需要知道計(jì)數(shù)總量(STK_LOAD的值)、時(shí)鐘源頻率等兩個(gè)參數(shù)。打個(gè)比方,這相當(dāng)于我們要計(jì)算運(yùn)動(dòng)時(shí)間,需要知道距離和速度,那么STK_LOAD的值即為距離,時(shí)鐘源頻率即為速度。則中斷計(jì)數(shù)時(shí)間為(假設(shè)STK_LOAD的值為VALUE,時(shí)鐘源頻率為CLK,中斷計(jì)數(shù)時(shí)間為T):
T = VALUE / CLK(其中,CLK為72MHz)當(dāng)STK_LOAD的值VALUE減到0時(shí),即可產(chǎn)生中斷。如果設(shè)置VALUE=72000,那么中斷一次的時(shí)間T = 72000 / 72MHz = 1ms。
定時(shí)時(shí)間計(jì)算
得出中斷一次的時(shí)間后,我們可以設(shè)置一個(gè)變量n,用來(lái)記錄中斷次數(shù),那么最終的定時(shí)時(shí)間即為T*n。
回到開(kāi)頭的實(shí)驗(yàn)說(shuō)明中,我們需要產(chǎn)生1s時(shí)基,來(lái)實(shí)現(xiàn)LED燈1s閃爍一次,則n為1000時(shí)滿足要求。
#define SysTick_CTRL_ENABLE_Pos 0 #define SysTick_CTRL_ENABLE_Msk (1ul << SysTick_CTRL_ENABLE_Pos)/** * @brief 毫秒級(jí)的定時(shí)函數(shù) * @param n:毫秒數(shù),如n為1000,則計(jì)時(shí)1000*1ms=1s * @retval 無(wú) */ void SysTick_Delay_ms(uint32_t n){ uint32_t i; SysTick_Config(72000); // 產(chǎn)生1ms的中斷(72000 / 72MHz = 1ms) for(i=0; i<n; i++){ while(!((SysTick->CTRL)&(1<<16))); } SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 失能SysTick }由于SysTick不會(huì)自動(dòng)停止,所以我們需要在異常/中斷處理中將其停止,即失能SysTick。
到這里為止,一個(gè)簡(jiǎn)單的SysTick定時(shí)實(shí)驗(yàn)完成了,之后只要在main函數(shù)中調(diào)用SysTick_Delay_ms(1000)函數(shù),即可實(shí)現(xiàn)1s的精確SysTick定時(shí),而不是使用普通的不精確延時(shí)函數(shù)。
轉(zhuǎn)載于:https://www.cnblogs.com/fire909090/p/8875420.html
總結(jié)
以上是生活随笔為你收集整理的SysTick定时器的一个简单应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [摘抄] Bezier曲线、B样条和NU
- 下一篇: 7 ArcMap能复制,不能粘贴