400-035-6699
当前位置: 首页 » 技术支持 » 博文资讯 »

STM32系统滴答定时器SysTick配置详解与实现步骤

在微控制器编程中,SysTick滴答定时器是一种常见的工具,用于创建精确的时间间隔。以往,配置这个定时器需要直接操作寄存器,查找内核编程手册来确定正确的设置。但在某些微控制器的头文件,比如core_cm4.h中,已经为我们提供了方便的配置函数。
首先,我们需要确认一个条件:__Vendor_SysTickConfig必须等于0,我们才能使用这个配置函数。好消息是,在STM32f4xx.h头文件中,这个宏已经被定义为0,因此我们可以直接使用。
SysTick_Config函数是核心的配置函数,它的原型是__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)。此函数接受一个参数ticks,它代表定时器的重装载值。要注意的是,如果设置的值超出了24位的范围,函数将返回错误信息。
在函数内部,首先检查ticks值是否超出允许的最大值,然后设置SysTick的重装载寄存器LOAD,清零当前值寄存器VAL,并配置控制寄存器CTRL以启动定时器和中断。如果一切设置正确,函数返回0,表示成功。
SysTick定时器的时钟源通常与处理器时钟相同。以168MHz为例,每秒可以进行168,000,000次计数,这意味着每毫秒可以计数168,000次,每微秒计数168次。由于装载值是24位的,最大值是16777215,因此理论上最大延时大约是100毫秒。
在具体的应用中,我们不再需要自己编写延时函数。只需要包含core_cm4.h头文件,并在程序中调用SysTick_Config函数,传入计算好的延时值即可。然后,在中断服务例程中编写我们想要重复执行的代码。
以一个LED闪烁的例子来说,假设我们想要每50毫秒翻转一次LED的状态,我们可以在主函数中这样写:
```cpp #include "stm32f4xx.h" #include "led.h" #include "core_cm4.h"
int main() { LED_Init(); // 初始化LED灯 SysTick_Config(8400000); // 延时50ms的配置
while(1) { // 主循环保持空,所有工作在中断服务例程中完成 } }
void SysTick_Handler() { static u8 cnt = 0; SysTick->CTRL &= ~(1 << 16); // 清除计数标志位 cnt++; if(cnt == 10) { LED_Toggle(DS0); // 翻转LED状态 cnt = 0; } } ```
这里,中断服务例程通过计数器实现了一个简单的分频,因为50ms太短,人眼可能无法察觉LED的闪烁。通过在计数器达到10时才翻转LED,实际上我们将闪烁间隔增加到了500ms。
最后,将编译好的程序烧写到开发板上,如果LED能够按预期闪烁,那么就说明SysTick配置函数调用成功了。通过这种方式,我们能够以更加简洁和高效的方式利用微控制器的内置功能,提升程序的开发效率。

之前使用SysTick滴答定时器都是通过查找内核编程手册配置寄存器让SysTick滴答定时器工作的。其实在内核相关的头文件core_cm4.h中已经有SysTick滴答定时器的相关配置了。

STM32系统滴答定时器SysTick配置详解与实现步骤

图片

条件__Vendor_SysTickConfig == 0成立,配置函数才能使用。

图片

刚好在stm32f4xx.h中定义了__Vendor_SysTickConfig = 0,所以可以使用该配置函数。

观察函数__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks),其中的寄存器和我们在Systick查询定时中用到的寄存器其实是一样的。

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) {
  //SysTick_LOAD_RELOAD_Msk为24,如果装载值超过24位,返回错误信息
  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 */
}

这种方式没有分频,时钟速度为168Mhz,每秒可计数168000000次,每毫秒可计数168000次,每微秒计数168次。装载值为24位,最大为16777215,可以算得最大延时时间为100ms。

这次的程序不需要上次写的delay文件了,只要在主文件加入SysTick配置函数的头文件core_cm4.h,根据想要定时的时间,计算相应的数值,初始化SysTick配置函数。再调用中断接口封装中断函数,就可以实现SysTick中断了。

如果中断函数像之前那样可能会看不到现象,因为定时时间过短,人眼可能识别不出led灯在闪烁,这里可以添加个计数,相当于定时更长时间才执行想要的程序。

#include "stm32f4xx.h"
#include "led.h"
#include "core_cm4.h"


int main() {
  LED_Init();              //初始化LED灯
  SysTick_Config(8400000);//延时50ms 168000000/8400000=20 1000/20=50

  while(1)
  {
  }
}


void SysTick_Handler() {
  static u8 cnt = 0;
  SysTick- >CTRL  &=~  (1< < 16);    //清计数标志位
  cnt++;
  if(cnt == 10)
  {
    LED_Toggle(DS0);              //LED灯闪烁
    cnt = 0; 
  }
}

编译工程项目并烧入开发板,LED灯闪烁,SysTick配置函数调用成功。

【限时免费】一键获取网络规划系统模板+传输架构设计+连通性评估方案

相关文章

服务电话:
400-035-6699
企服商城