STM32 延时函数详解

发布于:2025-08-18 ⋅ 阅读:(12) ⋅ 点赞:(0)

在嵌入式开发中,延时操作是最常见也最基础的一项任务。无论是初始化外设、等待传感器响应,还是处理简单的任务调度,延时函数都扮演着重要角色。本文将以 STM32 系列(以 STM32F103 为例)为基础,详细讲解如何使用 SysTick 定时器 实现微秒、毫秒和秒级延时。


一、延时函数接口定义

delay.h 中,我们定义了以下三个延时函数接口:

#ifndef __DELAY_H
#define __DELAY_H

void 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秒
}


网站公告

今日签到

点亮在社区的每一天
去签到