stm32 SysTick
SysTick是系統(tǒng)定時(shí)器,屬于 CM3 內(nèi)核中的一個(gè)外設(shè),內(nèi)嵌在 NVIC 中。系統(tǒng)定時(shí)器是一個(gè) 24bit 的向下遞減的計(jì)數(shù)器,計(jì)數(shù)器每計(jì)數(shù)一次的時(shí)間為 1/SYSCLK,一般設(shè)置系統(tǒng)時(shí)鐘 SYSCLK 等于 72M。當(dāng)重裝載數(shù)值寄存器的值遞減到 0 的時(shí)候,系統(tǒng)定時(shí)器就產(chǎn) 生一次中斷,以此循環(huán)往復(fù)。
main.c
效果就是,利用 SysTick 產(chǎn)生的時(shí)基,讓LED 以一定頻率閃爍。 Delay_us函數(shù)和SysTick_Delay_Ms函數(shù)是用兩種方法做的定時(shí)。
#include "stm32f10x.h" #include "bsp_SysTick.h" #include "bsp_led.h"/** t : 定時(shí)時(shí)間 * Ticks : 多少個(gè)時(shí)鐘周期產(chǎn)生一次中斷 * f : 時(shí)鐘頻率 72000000* t = Ticks * 1/f = (72000000/100000) * (1/72000000) = 10us */ /*** @brief 主函數(shù)* @param 無(wú) * @retval 無(wú)*/ int main(void) { /* LED 端口初始化 */LED_GPIO_Config();/* 配置SysTick 為10us中斷一次 */SysTick_Init();// for(;;) // {// LED1( ON ); // Delay_us(100000); // 100000 * 10us = 1000ms // //Delay_ms(100); // LED1( OFF ); // // LED2( ON ); // Delay_us(100000); // 100000 * 10us = 1000ms // //Delay_ms(100); // LED2( OFF ); // // LED3( ON ); // Delay_us(100000); // 100000 * 10us = 1000ms // //Delay_ms(100); // LED3( OFF ); // } for(;;){LED1( ON ); SysTick_Delay_Ms( 1000 );LED1( OFF );LED2( ON );SysTick_Delay_Ms( 1000 );LED2( OFF );LED3( ON );SysTick_Delay_Ms( 1000 );LED3( OFF );} }SysTick.c
下面這個(gè)函數(shù)用來(lái)配置SysTick,ticks用來(lái)設(shè)置重裝載寄存器的值,最大不能超過(guò)2^24。當(dāng)重裝載寄存器的值遞減到 0 的時(shí)候產(chǎn)生中斷,然后重裝載寄存器的值又重新裝載往下遞減計(jì)數(shù),以此循環(huán)往復(fù)。SysTick_Config函數(shù)主要配置了 SysTick 中的三個(gè)寄存器:LOAD、VAL 和 CTRL。
CTRL寄存器位段:
LOAD寄存器位段:
VAL寄存器位段:(同時(shí)還會(huì)清除在 SysTick 控制及狀態(tài)寄存器中的COUNTFLAG 標(biāo)志)
static __INLINE uint32_t SysTick_Config(uint32_t ticks)下面這個(gè)函數(shù)用來(lái)SysTick 初始化,通過(guò)設(shè)置SysTick_Config的ticks,來(lái)決定系統(tǒng)定時(shí)器重裝載寄存器中的值。SystemCoreClock = 72M,SystemCoreClock / 100000=720,也就是說(shuō),重裝載寄存器的值是720。
SysTick中斷時(shí)間:SysTick 定時(shí)器的計(jì)數(shù)器是向下遞減計(jì)數(shù)的,計(jì)數(shù)一次的時(shí)間 T1=1/CLK,當(dāng)重裝載寄存器中的值 V減到0的時(shí)候,產(chǎn)生中斷,可知中斷一次的時(shí)間T=V*T1=V/CLK,如果設(shè)置重裝載寄存器的值是720,那么 SysTick 定時(shí)器中斷一次的時(shí)間也就是720/72=10微秒。
void SysTick_Init(void)SysTick定時(shí),定時(shí)有兩種方法,一種是設(shè)置好中斷時(shí)間,再設(shè)置一個(gè)變量 t,用來(lái)記錄進(jìn)入中斷的次數(shù),變量 t 乘以中斷的時(shí)間 就可以計(jì)算出需要定時(shí)的時(shí)間。下面這個(gè)函數(shù)就是us延時(shí)程序,10us為一個(gè)單位,參數(shù)是nTime,延時(shí)就是nTime * 10us。里面的TimingDelay是一個(gè)全局變量,值等于延時(shí)函數(shù)中傳進(jìn)去的 nTime 的值,變量 TimingDelay 在中斷函數(shù)中遞減,即 SysTick 每進(jìn)一次中斷即 10us 的時(shí)間 TimingDelay 遞減一次。
void Delay_us(__IO u32 nTime)下面是SysTick 中斷服務(wù)函數(shù),里面調(diào)用了TimingDelay_Decrement函數(shù),由此可見(jiàn), SysTick 每進(jìn)一次中斷TimingDelay 遞減一次。
void SysTick_Handler(void) {TimingDelay_Decrement(); } void TimingDelay_Decrement(void) {if (TimingDelay != 0x00){ TimingDelay--;} }SysTick定時(shí)第二種方法,systick 的 counter (計(jì)數(shù)器)從 reload (重裝載數(shù)值寄存器)值往下遞減到 0 的時(shí)候,CTRL 寄存器的位 16:countflag 會(huì)置 1,且讀取該位的值可清 0, 所以可使用軟件查詢的方法來(lái)實(shí)現(xiàn)延時(shí)。
下面是實(shí)現(xiàn)代碼。
void SysTick_Delay_Us( __IO uint32_t us) {uint32_t i;SysTick_Config(SystemCoreClock/1000000);for(i=0;i<us;i++){// 當(dāng)計(jì)數(shù)器的值減小到0的時(shí)候,CRTL寄存器的位16會(huì)置1 while( !((SysTick->CTRL)&(1<<16)) );}// 關(guān)閉SysTick定時(shí)器SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; }完整代碼:
#include "bsp_SysTick.h" #include "core_cm3.h" #include "misc.h"static __IO u32 TimingDelay;/*** @brief 啟動(dòng)系統(tǒng)滴答定時(shí)器 SysTick* @param 無(wú)* @retval 無(wú)*/ void SysTick_Init(void) {/* SystemFrequency / 1000 1ms中斷一次* SystemFrequency / 100000 10us中斷一次* SystemFrequency / 1000000 1us中斷一次*/ // if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0庫(kù)版本if (SysTick_Config(SystemCoreClock / 100000)) // ST3.5.0庫(kù)版本{ /* Capture error */ while (1);} }/*** @brief us延時(shí)程序,10us為一個(gè)單位* @param * @arg nTime: Delay_us( 1 ) 則實(shí)現(xiàn)的延時(shí)為 1 * 10us = 10us* @retval 無(wú)*/ void Delay_us(__IO u32 nTime) { TimingDelay = nTime; // 使能滴答定時(shí)器 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;while(TimingDelay != 0); }/*** @brief 獲取節(jié)拍程序* @param 無(wú)* @retval 無(wú)* @attention 在 SysTick 中斷函數(shù) SysTick_Handler()調(diào)用*/ void TimingDelay_Decrement(void) {if (TimingDelay != 0x00){ TimingDelay--;} }#if 0 // 這個(gè) 固件庫(kù)函數(shù) 在 core_cm3.h中 static __INLINE uint32_t SysTick_Config(uint32_t ticks) { // reload 寄存器為24bit,最大值為2^24if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);// 配置 reload 寄存器的初始值 SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;// 配置中斷優(yōu)先級(jí)為 1<<4-1 = 15,優(yōu)先級(jí)為最低NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); // 配置 counter 計(jì)數(shù)器的值SysTick->VAL = 0;// 配置systick 的時(shí)鐘為 72M// 使能中斷// 使能systickSysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; return (0); } #endif// couter 減1的時(shí)間 等于 1/systick_clk // 當(dāng)counter 從 reload 的值減小到0的時(shí)候,為一個(gè)循環(huán),如果開(kāi)啟了中斷則執(zhí)行中斷服務(wù)程序, // 同時(shí) CTRL 的 countflag 位會(huì)置1 // 這一個(gè)循環(huán)的時(shí)間為 reload * (1/systick_clk)void SysTick_Delay_Us( __IO uint32_t us) {uint32_t i;SysTick_Config(SystemCoreClock/1000000);for(i=0;i<us;i++){// 當(dāng)計(jì)數(shù)器的值減小到0的時(shí)候,CRTL寄存器的位16會(huì)置1 while( !((SysTick->CTRL)&(1<<16)) );}// 關(guān)閉SysTick定時(shí)器SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; }void SysTick_Delay_Ms( __IO uint32_t ms) {uint32_t i; SysTick_Config(SystemCoreClock/1000);for(i=0;i<ms;i++){// 當(dāng)計(jì)數(shù)器的值減小到0的時(shí)候,CRTL寄存器的位16會(huì)置1// 當(dāng)置1時(shí),讀取該位會(huì)清0while( !((SysTick->CTRL)&(1<<16)) );}// 關(guān)閉SysTick定時(shí)器SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk; }/*********************************************END OF FILE**********************/SysTick.h
#ifndef __SYSTICK_H #define __SYSTICK_H#include "stm32f10x.h"void SysTick_Init(void); void Delay_us(__IO u32 nTime); #define Delay_ms(x) Delay_us(100*x) //單位msvoid SysTick_Delay_Us( __IO uint32_t us); void SysTick_Delay_Ms( __IO uint32_t ms);#endif /* __SYSTICK_H */ 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的stm32 SysTick的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Leetcode-3 无重复字符的最长子
- 下一篇: java pc端软件抓包,如何通过抓包工