打印
[软件资料]

使用系统定时器SysTick实现精确延时微秒和毫秒函数

[复制链接]
782|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
maudlu|  楼主 | 2025-4-28 22:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

SysTick定时器简介

SysTick定时器是存在于系统内核的一个滴答定时器,只要是ARM Cortex-M0/M3/M4/M7内核的MCU都包含这个定时器,它是一个24位的递减定时器,当计数到 0 时,将从RELOAD 寄存器中自动重装载定时初值,开始新一轮计数。使用内核的SysTick定时器来实现延时,可以不占用系统定时器,由于和MCU外设无关,所以代码的移植,在不同厂家的Cortex-M内核MCU之间,可以很方便的实现。而东芝的这款TT_M3HQ开发板使用的TMPM3HQFDFG芯片,正好是ARM Cortex-M3内核,所以以前使用的延时函数,可以直接拿过来使用,无需任何修改。

精确延时函数的实现

在core_cm3.h文件中,有这样一个SysTickConfig函数:

__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定时器进行初始化,配置初始计数值,使能中断,使能定时器等。对应的中断函数为:

void SysTick_Handler(void)
{   
}

这个默认是空的,需要我们自己来实现。

如果SysTick初始化为:

SysTick_Config(SystemCoreClock / 1000);     //定时1ms

即SysTick定时器每1ms中断一次,如果我们定义全局变量,然后在中断函数中,让此变量递减,而在延时函数中,一直判断此变量是否减到了0,那么这样就实现了一个延时毫秒的函数。同理改变定时器的计数值为:

SysTick_Config(SystemCoreClock / 1000000);  //定时1us

那么就实现了每1us中断一次,所以延时微秒和延时毫秒函数的实现:

uint32_t fac_us=0;                          //us延时倍乘数
uint32_t fac_ms=0;                          //ms延时倍乘数,在ucos下,代表每个节拍的ms数

void delay_init(void)
{
    SystemCoreClockUpdate();        //可以省略
}
void SysTick_Handler(void)
{
    if(fac_us) fac_us--;
    if(fac_ms) fac_ms--;
}
void delay_us(uint32_t nus)
{   
    SysTick_Config(SystemCoreClock / 1000000);  //定时1us
    fac_us = nus;
    while(fac_us != 0);  
}

void delay_ms(uint32_t nms)
{               
    SysTick_Config(SystemCoreClock / 1000);     //定时1ms
    fac_ms = nms;
    while(fac_ms != 0);           
}

在使用延时函数之前,只需要进行系统时钟的更新即可,当然也可以不更新,因为在程序之前之前,系统启动文件中已经执行了系统时钟更新。

总结

由于SysTick定时器是所有的ARM Cortex-M内核MCU都有的一个定时器,所以以上延时微秒和延时毫秒的函数适用于任何 Cortex-M内核的MCU。有了精确延时函数,那么使用通用GPIO软件模拟一些通信协议,如IIC、SPI等串行协议,就可以驱动很多硬件设备了,如EEPROM、温湿度传感器、显示屏等等。

使用特权

评论回复
沙发
Betty1299| | 2025-6-8 11:38 | 只看该作者
使用系统定时器SysTick实现精确延时微秒和毫秒函数是一种常见的嵌入式开发技术。

使用特权

评论回复
板凳
HeimdallHoney| | 2025-6-8 11:43 | 只看该作者
时钟配置,确保SystemCoreClock变量已正确设置为系统时钟频率。

使用特权

评论回复
地板
Candic12e| | 2025-6-8 12:42 | 只看该作者
SysTick定时器是一个24位的倒计时定时器,通常用于操作系统的时间基准或简单的延时功能。

使用特权

评论回复
5
Belle1257| | 2025-6-8 13:49 | 只看该作者
首先,确保SysTick定时器已经配置好,并且时钟源已经设置正确。SysTick定时器的时钟源通常是系统时钟(HCLK)。

使用特权

评论回复
6
Alina艾| | 2025-6-8 16:02 | 只看该作者
由于SysTick定时器是24位的,最大延时为16.777毫秒(对于72MHz的系统时钟),因此微秒级延时需要更精确的控制。

使用特权

评论回复
7
BetrayalNO| | 2025-6-8 17:08 | 只看该作者
毫秒级延时可以使用SysTick的中断功能来实现。

使用特权

评论回复
8
MercuryStar| | 2025-6-8 18:55 | 只看该作者
在main函数中初始化SysTick定时器,并使用延时函数。

使用特权

评论回复
9
Euphoriaxixi| | 2025-6-9 09:02 | 只看该作者
中断优先级,确保SysTick的中断优先级设置正确,以避免被其他高优先级中断打断。

使用特权

评论回复
10
Espoironenext| | 2025-6-9 10:13 | 只看该作者
延时精度,由于SysTick是一个24位定时器,最大延时为16.777毫秒。对于更长的延时,需要使用多个SysTick中断或采用其他定时器。

使用特权

评论回复
11
B1lanche| | 2025-6-9 13:10 | 只看该作者
代码可移植性,在不同的MCU上,SysTick定时器的配置和中断处理可能略有不同,请根据具体硬件手册调整代码。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

1547

帖子

0

粉丝