你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 SysTick定时器

[复制链接]
STMCU小助手 发布时间:2022-6-11 21:08
01. SysTick定时器概述
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。

Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。

02. SysTick定时器寄存器描述
SysTick控制及状态寄存器(地址:0xE000_E010)

XOXG[EB1]FJW]D{{5V)0BPL.png

SysTick重装载数值寄存器(地址:0xE000_E014)

20200830102443823.png

SysTick当前数值寄存器(地址:0xE000_E018)

20200830102451227.png

SysTick校准数值寄存器(地址:0xE000_E01C)

VY_K(VW~3_EQM2O6IILW7I7.png

03. 相关函数实现
core_cm4.h文件

  1. /** \brief  System Tick Configuration

  2.     The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
  3.     Counter is in free running mode to generate periodic interrupts.

  4.     \param [in]  ticks  Number of ticks between two interrupts.

  5.     \return          0  Function succeeded.
  6.     \return          1  Function failed.

  7.     \note     When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
  8.     function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>
  9.     must contain a vendor-specific implementation of this function.

  10. */
  11. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
  12. {
  13.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }    /* Reload value impossible */

  14.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  15.   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  16.   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  17.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
  18.                    SysTick_CTRL_TICKINT_Msk   |
  19.                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  20.   return (0UL);                                                     /* Function successful */
  21. }
复制代码

misc.c文件

  1. /**
  2.   * @brief  Configures the SysTick clock source.
  3.   * @param  SysTick_CLKSource: specifies the SysTick clock source.
  4.   *   This parameter can be one of the following values:
  5.   *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
  6.   *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
  7.   * @retval None
  8.   */
  9. void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
  10. {
  11.   /* Check the parameters */
  12.   assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
  13.   if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
  14.   {
  15.     SysTick->CTRL |= SysTick_CLKSource_HCLK;
  16.   }
  17.   else
  18.   {
  19.     SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
  20.   }
  21. }
复制代码

04. 延时函数实现
delay.h文件

  1. #ifndef __DELAY_H
  2. #define __DELAY_H                           
  3. #include <sys.h>         

  4. void delay_init(u8 SYSCLK);
  5. void delay_ms(u16 nms);
  6. void delay_us(u32 nus);

  7. #endif
复制代码

delay.c文件

  1. static u8  fac_us=0;                                                        //us延时倍乘数                           
  2. static u16 fac_ms=0;                                                        //ms延时倍乘数,在os下,代表每个节拍的ms数

  3. //初始化延迟函数
  4. //当使用OS的时候,此函数会初始化OS的时钟节拍
  5. //SYSTICK的时钟固定为AHB时钟的1/8
  6. //SYSCLK:系统时钟频率
  7. void delay_init(u8 SYSCLK)
  8. {

  9.          SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
  10.         fac_us=SYSCLK/8;                                                //不论是否使用OS,fac_us都需要使用

  11.         fac_ms=(u16)fac_us*1000;                                //非OS下,代表每个ms需要的systick时钟数   
  12. }               

  13. //延时nus
  14. //nus为要延时的us数.        
  15. //注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)
  16. void delay_us(u32 nus)
  17. {               
  18.         u32 temp;                     
  19.         SysTick->LOAD=nus*fac_us;                                 //时间加载                           
  20.         SysTick->VAL=0x00;                                        //清空计数器
  21.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数         
  22.         do
  23.         {
  24.                 temp=SysTick->CTRL;
  25.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
  26.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
  27.         SysTick->VAL =0X00;                                       //清空计数器
  28. }

  29. //延时nms
  30. //注意nms的范围
  31. //SysTick->LOAD为24位寄存器,所以,最大延时为:
  32. //nms<=0xffffff*8*1000/SYSCLK
  33. //SYSCLK单位为Hz,nms单位为ms
  34. //对168M条件下,nms<=798ms
  35. void delay_xms(u16 nms)
  36. {                                    
  37.         u32 temp;                  
  38.         SysTick->LOAD=(u32)nms*fac_ms;                        //时间加载(SysTick->LOAD为24bit)
  39.         SysTick->VAL =0x00;                                   //清空计数器
  40.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数
  41.         do
  42.         {
  43.                 temp=SysTick->CTRL;
  44.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
  45.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器
  46.         SysTick->VAL =0X00;                                       //清空计数器                     
  47. }

  48. //延时nms
  49. //nms:0~65535
  50. void delay_ms(u16 nms)
  51. {                  
  52.         u8 repeat=nms/540;                                                //这里用540,是考虑到某些客户可能超频使用,
  53.                                                                                         //比如超频到248M的时候,delay_xms最大只能延时541ms左右了
  54.         u16 remain=nms%540;
  55.         while(repeat)
  56.         {
  57.                 delay_xms(540);
  58.                 repeat--;
  59.         }
  60.         if(remain)delay_xms(remain);
  61. }
复制代码

05. 应用示例
用中断的方式实现delay延时

  1. static __IO uint32_t TimingDelay;
  2. void Delay(__IO uint32_t nTime)
  3. {
  4.    TimingDelay = nTime;
  5.    while(TimingDelay != 0);
  6. }
  7. void SysTick_Handler(void)
  8. {
  9.     if (TimingDelay != 0x00)
  10.      {
  11.        TimingDelay--;
  12.      }
  13. }
  14. int main(void)
  15. {  …
  16.     if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms
  17.      {
  18.      while (1);
  19.      }
  20.     while(1)
  21.      { Delay(200);//2ms
  22.      …
  23.      }
  24. }
复制代码



收藏 评论0 发布时间:2022-6-11 21:08

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版