STM32 延时函数详解
在嵌入式开发中,延时操作是最常见也最基础的一项任务。无论是初始化外设、等待传感器响应,还是处理简单的任务调度,延时函数都扮演着重要角色。本文将以 STM32 系列(以 STM32F103 为例)为基础,详细讲解如何使用 SysTick 定时器 实现微秒、毫秒和秒级延时。
一、延时函数接口定义
在 delay.h
中,我们定义了以下三个延时函数接口:
#ifndef __DELAY_H
#define __DELAY_Hvoid Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
void Delay_s(uint32_t s);#endif
接口说明:
Delay_us()
:实现微秒级延时Delay_ms()
:实现毫秒级延时Delay_s()
:实现秒级延时
二、使用 SysTick 实现延时
1. 微秒级延时:Delay_us()
void Delay_us(uint32_t xus)
{SysTick->LOAD = 72 * xus;SysTick->VAL = 0x00;SysTick->CTRL = 0x00000005;while(!(SysTick->CTRL & 0x00010000));SysTick->CTRL = 0x00000004;
}
实现原理:
- 使用 Cortex-M3 内核自带的 SysTick 24 位定时器
- 假设系统时钟为 72MHz,那么 1 微秒 ≈ 72 个时钟周期
- 设置
LOAD = 72 * xus
,SysTick 开始递减计数直到为 0
注意事项:
- 最大延时时间 ≈ 233015 微秒(24 位最大值)
- 精度较高,适用于短时间延时场合
2. 毫秒级延时:Delay_ms()
void Delay_ms(uint32_t xms)
{while(xms--){Delay_us(1000);}
}
实现原理:
- 通过调用
Delay_us(1000)
实现 1 毫秒延时 - 循环 xms 次实现毫秒级延时
注意事项:
- 会占用 CPU(阻塞式)
- 对精度要求高时,需要考虑误差累积
3. 秒级延时:Delay_s()
void Delay_s(uint32_t xs)
{while(xs--){Delay_ms(1000);}
}
实现原理:
- 基于
Delay_ms()
实现每秒延时 - 循环实现多秒延时
注意事项:
- 不适合用于长时间延时场景
- CPU 会在整个延时期间被阻塞,效率低
三、SysTick 延时的优缺点
✅ 优点:
- 实现简单,适合快速开发与测试
- 精度高(微秒级),可控性强
❌ 缺点:
- 阻塞式延时:CPU 在延时期间无法执行其他任务
- 不可打断:不适用于多任务或需要实时响应的系统
- 不适合长时间延时
四、进阶优化建议
在实际工程中,若对性能、功耗或响应速度有更高要求,建议使用以下方式替代阻塞式延时:
- 使用硬件定时器(TIM)中断方式:实现非阻塞延时
- 使用 RTOS(如 FreeRTOS)提供的
vTaskDelay()
- 利用
HAL_GetTick()
结合时间差轮询,实现延时但不阻塞
示例(非阻塞式轮询):
uint32_t start = HAL_GetTick();
while(HAL_GetTick() - start < 1000) {// 执行其他任务,等待1秒
}