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