【STM32】04.SysTick定时器

一、问题引入

我们需要实现一个延时,是这样实现的:
// STM32F103C8T6(72MHz) 专用毫秒级延时函数 // 实测:1ms误差±0.02ms,1000ms误差±15ms,满足外设控制需求 void delay_ms(uint32_t ms) { volatile uint32_t i, j; // 72MHz主频精准校准值,一行修改完成适配,核心逻辑不变 uint32_t calibrate = 8000; // 该值严格对应72MHz下约1ms延时 for(j = 0; j < ms; j++) { for(i = 0; i < calibrate; i++) { // volatile变量保证空循环不被编译器优化,延时有效 ; } } }
calibrate = 8000 是通过实验得到的近似值,并非准确值。如果使用这个延时函数,做一些精准延时的功能,是会有问题的。在STM32 裸机开发中(非操作系统),我们可以使用SysTick定时器,实现精准延时的需求,例如实现毫秒级、微秒级的延时。

二、SysTick简介

SysTick定时器,又名系统定时器、滴答定时器,是属于Cortex-M3内核中的一个外设,内嵌在NVIC中。系统定时器是一个24bit的向下递减的计数器。SysTick定时器的应用

  1. 操作系统定时器:在RTOS(实时操作系统)中,SysTick定时器常被用作系统定时器,用于实现任务调度和定时器管理。
  2. 软件定时器:在没有RTOS的情况下,也可以利用SysTick定时器实现简单的软件定时功能。
  3. 周期性任务:可以用来定期执行一些周期性的任务,如采样ADC、刷新LCD显示等。

三、SysTick定时器的寄存器


四、 SysTick定时器工作原理

1. 时钟来源

SysTick定时器有两种时钟来源可选择:内核时钟、外部参考时钟。内核时钟频率为 HCLK ,外部参考时钟频率为 HCLK / 8。

2. 定时原理

2. 1 递减计数

SysTick是一个24位递减计数器,当前值寄存器从预设的初始值开始,每个时钟周期自动减1,当计数达到0时产生中断并自动重新加载初始值,如此循环往复。

2. 2 重载值设定

通过LOAD寄存器设置重装载值(预设的初始值)。

2. 3 时序图理解


发生中断间隔时间 = 一个脉冲时间 * (重装载值 + 1)
注意:一个脉冲周期时间 = 1 / 频率
根据公式,使用内核时钟 72MHz ,期待每间隔 1ms,发生一次中断:
重装载值 = 1ms * 72MHz - 1 = 72000 - 1 = 71999
注意:重装载的值不能超过 24bit 存储的范围,即不能超过16777215。

五、STM32CubeMX生成的延时ms函数

利用上述定时原理,STM32CubeMX默认生成了 延时 ms 级别精度 的函数HAL_Delay(),使用示例如下:
// 替代main函数中的while循环 void app_main(void) { while (1) { HAL_Delay(1000); // 延时1000ms HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); } }
接下来我们分析其实现的代码:

六、SysTick定时器实现us精度延时

void delay_us(uint32_t us) { uint32_t save_LOAD; // 备份原SysTick->LOAD值 uint32_t target_ticks;// 目标us对应的SysTick重载值 // 1. 备份原始LOAD值(核心!延时结束必须恢复,否则HAL_Delay无法使用) save_LOAD = SysTick->LOAD; // 2. 计算目标us对应的重载值:SystemCoreClock(Hz) → 当前内核时钟的主频位72MHz,对应1us计数为72个脉冲 target_ticks = (1UL * SystemCoreClock / 1000000) * us; // 3.关闭SysTick中断,CTRL寄存器的bit1清零 SysTick->CTRL &=~0x02; // 4. 配置SysTick为「目标us计数模式」,启动计数 SysTick->LOAD=target_ticks - 1; // 重载值=计数值-1,(999->0总共是1000个计数) SysTick->VAL=0UL; // 计数器清零,同时也会同步清空 SysTick->CTRL的COUNTFLAG标志位,立刻开始计数 // 5. 硬件等待:直到计数完成(COUNTFLAG置1) while ((SysTick->CTRL&(1<<16))==0); // 6. 完全复原:恢复原始LOAD值,保证SysTick原理周期1ms不变 SysTick->LOAD=save_LOAD; SysTick->VAL=0; // 7. 恢复SysTick中断(否则HAL_Delay无法使用) SysTick->CTRL|=0x02; }
注意: 重载值最大值为16777215,即该函数最大延时约233毫秒(内核时钟72MHz)。强烈建议延时 ms 时,用 HAL_Delay() 函数。

七、STMCubemx配置的SysTick中断优先级

相关推荐
我叫洋洋20 小时前
Allegro 画布“垃圾显示“清理指南:把板子调成干净工作台(实战总结)
c语言·c++·单片机·嵌入式硬件·eda·嘉立创
xiangw@GZ20 小时前
SPI Flash 接口模式与 XIP 技术详解
单片机·嵌入式硬件
香吧香20 小时前
GitHub Actions 详解
git
沐欣工作室_lvyiyi20 小时前
基于STM32的人体健康检测设计(论文+源码)
stm32·单片机·嵌入式硬件
艾络迅Acceleronix20 小时前
气象监测:STM32+EG800Z AT + 艾络迅平台实战|气压/光照/雨量采集全流程
stm32·单片机·嵌入式硬件·mcu·物联网·1024程序员节
深圳老胡20 小时前
FDC2212 + STM32G030 液面探测:IIC 读数跳动导致下探深度不一致的排查与解决
笔记·stm32·单片机·代码规范·1024程序员节
硅基造物主20 小时前
STM32 从 0 到 1 做智能家居(一):先想清楚要做什么
stm32·mqtt·嵌入式·智能家居·hal库·esp-12f
xiangw@GZ20 小时前
两线 JTAG(cJTAG / IEEE 1149.7)技术专题
单片机·嵌入式硬件
Madison-No720 小时前
Git版本控制工具(三)
git
comyccccc21 小时前
晶振区禁铺铜,三大保险丝护航电路安全学习笔记
单片机·嵌入式硬件