日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32-Systick滴答定时器-延时函数

發布時間:2025/3/12 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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個周期。最后如果時間超過/等于要延遲的時間,則退出。

//延時nus //nus:要延時的us數. //nus:0~204522252(最大值即2^32/fac_us@fac_us=21) void delay_us(u32 nus) { u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD; //LOAD的值 ticks=nus*fac_us; //需要的節拍數 delay_osschedlock(); //阻止OS調度,防止打斷us延時told=SysTick->VAL; //剛進入時的計數器值while(1){tnow=SysTick->VAL; if(tnow!=told){ if(tnow<told)tcnt+=told-tnow; //這里注意一下SYSTICK是一個遞減的計數器就可以了.else tcnt+=reload-tnow+told; told=tnow;if(tcnt>=ticks)break; //時間超過/等于要延遲的時間,則退出.} };delay_osschedunlock(); //恢復OS調度 }

總結

以上是生活随笔為你收集整理的STM32-Systick滴答定时器-延时函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。