STM32-Systick滴答定时器-延时函数
1.STM32-Systick滴答定時器
-
Systick定時器,是一個簡單的定時器,對于ST的CM3,CM4,CM7內核芯片,都有Systick定時器。
-
Systick定時器常用來做延時,或者實時系統的心跳時鐘。這樣可以節省MCU資源,不用浪費一個定時器。比如UCOS中,分時復用,需要一個最小的時間戳,一般在STM32+UCOS系統中,都采用Systick做UCOS心跳時鐘。
-
Systick定時器就是系統滴答定時器,一個24 位的倒計數定時器,計到0 時,將從RELOAD 寄存器中自動重裝載定時初值。只要不把它在SysTick 控制及狀態寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
-
SysTick定時器被捆綁在NVIC中,用于產生SYSTICK異常(異常號:15)。
-
Systick中斷的優先級也可以設置。
-
4個Systick寄存器
CTRL SysTick 控制和狀態寄存器 LOAD SysTick 自動重裝載除值寄存器 VAL SysTick 當前值寄存器 CALIB SysTick 校準值寄存器
可在core-core_cm7.h文件中找到
typedef struct {__IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */__IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */__IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */__IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ } SysTick_Type;SysTick 控制和狀態寄存器- CTRL:
對于STM32,外部時鐘源是 HCLK(AHB總線時鐘)的1/8。內核時鐘是 HCLK時鐘。配置函數:HAL_SYSTICK_CLKSourceConfig();
SysTick重裝載數值寄存器-LOAD
SysTick當前數值寄存器-VAL
HAL庫中的Systick相關函數:
stm32f7xx_hal_cortex.c文件中:HAL_SYSTICK_CLKSourceConfig () ; //Systick時鐘源選擇
如果SysTick的時鐘源自HCLK,假設外部晶振為25M,倍頻到216MHZ,那么SysTick的時鐘即為216MHZ,也就是SysTick的計數器VAL每減1,就代表時間過了1/216us。
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource) {/* Check the parameters */assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource));if (CLKSource == SYSTICK_CLKSOURCE_HCLK){SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;}else{SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK;} }可以看一下CLKSource可以有哪幾種:找到IS_SYSTICK_CLK_SOURCE的定義,發現可以為SYSTICK_CLKSOURCE_HCLK和SYSTICK_CLKSOURCE_HCLK_DIV8,也就是不分頻或者8分頻。
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SYSTICK_CLKSOURCE_HCLK) || \((SOURCE) == SYSTICK_CLKSOURCE_HCLK_DIV8))core_cm7.h文件中:SysTick_Config (uint32_t ticks) //初始化systick,時鐘為HCLK,并開啟中斷。
ticks:經過多少個systick周期發生一次中斷。用來配置SysTick定時器經過多少個ticks發生一次中斷。
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) {if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk){return (1UL); /* Reload value impossible */}SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */SysTick->VAL = 0UL; /* Load the SysTick Counter Value */SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |SysTick_CTRL_TICKINT_Msk |SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */return (0UL); /* Function successful */ }首先看到SysTick_LOAD_RELOAD_Msk,由于Systick是一個24 位的倒計數定時器,所以值不能太大。
#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/)Systick中斷服務函數:void SysTick_Handler (void);
2.delay函數
//初始化延遲函數 //當使用ucos的時候,此函數會初始化ucos的時鐘節拍 //SYSTICK的時鐘固定為AHB時鐘的1/8 //SYSCLK:系統時鐘頻率 void delay_init(u8 SYSCLK) { #if SYSTEM_SUPPORT_OS //如果需要支持OS.u32 reload; #endifHAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick頻率為HCLKfac_us=SYSCLK; //不論是否使用OS,fac_us都需要使用 #if SYSTEM_SUPPORT_OS //如果需要支持OS.reload=SYSCLK; //每秒鐘的計數次數 單位為K reload*=1000000/delay_ostickspersec; //根據delay_ostickspersec設定溢出時間//reload為24位寄存器,最大值:16777216,在216M下,約合77.7ms左右 fac_ms=1000/delay_ostickspersec; //代表OS可以延時的最少單位 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//開啟SYSTICK中斷SysTick->LOAD=reload; //每1/OS_TICKS_PER_SEC秒中斷一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //開啟SYSTICK #endif }在main中調用delay_init(216);//延時初始化。1微秒等于10的負6次方秒,1MHZ等于10^6赫茲。
fac_us=SYSCLK;系統時鐘是216MHZ,fac_us=216意思是:systick運行1us,需要多少個systick周期。由于systick是216MHZ,所以需要216個周期。后面如果需要延時n個微秒,只需要n*fac_us即可。由于設置的SysTick頻率為HCLK,所以調用delay_init函數中的參數SYSCLK就是216 。
delay_us函數思路:
在循環里檢測當前值,如果當前值小于前一次的值,說明沒有減到0,通過told-tnow就可以知道當前跑了幾個周期。否則,說明已經溢出了,也就是說當前跑了reload-tnow+told個周期。最后如果時間超過/等于要延遲的時間,則退出。
總結
以上是生活随笔為你收集整理的STM32-Systick滴答定时器-延时函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 个人计算机的组成及相关功能,计算机的组成
- 下一篇: java 定义和导入包