stm32项目中用SysTick实现Delay代码编写
·
SysTick(System Tick Timer,系统滴答定时器)是 ARM Cortex-M 内核内部集成的一个24位倒计数定时器。
可以把它理解为芯片内部自带的一个“超级秒表”或“心跳节拍器”。它不属于 STM32 的外设(所以不需要配置时钟树),而是直接挂在 ARM 内核上的。
1. SysTick 的核心作用
- 提供精准的系统时基:它通常被配置为每 1ms(毫秒)或 1us(微秒)产生一次中断,为整个操作系统或程序提供统一的时间基准。
- 实现延时函数:我们在单片机开发中经常用的
Delay_ms()或Delay_us(),底层绝大多数都是基于 SysTick 实现的。 - RTOS 的心脏:如果你以后用 FreeRTOS 或 RT-Thread 等实时操作系统,SysTick 就是用来给任务调度的。
2. 它是怎么工作的?
SysTick 的结构非常简单,主要由 4 个寄存器组成:
- CTRL(控制寄存器):用来开启/关闭定时器,以及是否使能中断。
- LOAD(重装载值寄存器):设定倒计数的起点。比如系统时钟是 72MHz,你想 1ms 触发一次,就把这个值设为
72000 - 1。 - VAL(当前值寄存器):它从 LOAD 的值开始,每个时钟周期减 1,减到 0 时自动重新装载 LOAD 的值,并产生一个标志位或中断。
- CALIB(校准寄存器):用于校准时钟频率。
3.代码编写
delay.c
#include "delay.h"
/**
* @brief 微秒级延时函数(基于SysTick定时器,系统主频72MHz)
* @param us: 需要延时的微秒数值
* @retval 无
*/
//1s 72000,000 1us 72 最大定时时间 233ms
void delay_us(uint16_t us)
{
SysTick->CTRL = 0; // 关闭SysTick定时器,清空控制寄存器
SysTick->LOAD = 72*us - 1; // 设置重载初值:72MHz下,1us对应72个系统时钟周期
SysTick->VAL = 0; // 清空当前计数器寄存器,从头开始计数
SysTick->CTRL = 5; // 配置SysTick:bit2=1(使用外部HCLK时钟)、bit0=1(开启定时器),二进制101即十进制5
while((SysTick->CTRL & 0x00010000) == 0); // 等待计数完成:判断COUNTFLAG标志位(第16位),计数到0后置1
SysTick->CTRL = 0; // 延时结束,关闭SysTick定时器,停止计数
}
/**
* @brief 毫秒级延时函数(72MHz系统时钟)
* @param ms: 要延时的毫秒数
* @retval 无
*/
//1s 72000,000 1ms 72000 1ms = 1000μs
void delay_ms(uint16_t ms)
{
while(ms--) // 循环ms次,每次产生1ms延时,累加得到总延时ms毫秒
{
SysTick->CTRL = 0;
SysTick->LOAD = 72000 - 1; // 装载1ms对应的计数初值(72MHz:72000个周期=1ms)
SysTick->VAL = 0;
SysTick->CTRL = 5;
while((SysTick->CTRL & 0x00010000) == 0);
SysTick->CTRL = 0;
}
}
/**
* @brief 秒级阻塞延时函数
* @param s: 需要延时的秒数
* @retval 无
* @note 依赖已实现的 delay_ms(),1秒 = 1000毫秒
*/
void delay_s(uint16_t s)
{
while(s--)
{
delay_ms(1000);
}
}
delay.h
#ifndef _DELAY_H_
#define _DELAY_H_
#include "stm32f10x.h" // Device header
#include <stdint.h>
void delay_us(uint16_t us);
void delay_ms(uint16_t ms);
void delay_s(uint16_t s);
#endif
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)