当前位置: 首页 > news >正文

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

http://www.lryc.cn/news/622700.html

相关文章:

  • 343整数拆分
  • 后量子密码算法ML-DSA介绍及开源代码实现
  • 【Qt开发】常用控件(四)
  • 算法提升之树上问题-(tarjan求LCA)
  • 基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
  • MySQL 配置性能优化赛技术文章
  • Win10、Win11电脑之间无法Ping通解决办法
  • 设计模式之【快速通道模式】,享受VIP的待遇
  • Python - 100天从新手到大师:第十一天常用数据结构之字符串
  • OpenCV Python——图像拼接(一)(图像拼接原理、基础知识、单应性矩阵 + 图像变换 + 拼接)
  • redis基本类型之哈希
  • 爬机 验证服务器是否拒绝请求
  • 衡石使用指南嵌入式场景实践之仪表盘嵌入
  • 【Docker项目实战】使用Docker部署Notepad轻量级记事本
  • 《吃透 C++ 类和对象(中):const 成员函数与取地址运算符重载解析》
  • js原生实现手写签名与使用signature_pad库实现手写签名
  • 【Java Web 快速入门】十一、Spring Boot 原理
  • Flutter开发 网络请求
  • Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析
  • Flutter Provider 模式实现:基于 InheritedWidget 的状态管理实现
  • SQL183 近三个月未完成试卷数为0的用户完成情况
  • 力扣(LeetCode) ——142. 环形链表 II(C语言)
  • JavaWeb 30 天入门:第十一天 ——Java 反射机制详解
  • 【环境变量与程序地址空间详解】
  • vue3动态的控制表格列的展示简单例子
  • 从希格斯玻色子到 QPU:C++ 的跨维度征服
  • KingbaseES高可用架构深度解析——从读写分离到异地灾备的全方位守护
  • 【C++】异常详解(万字解读)
  • 力扣hot100 | 矩阵 | 73. 矩阵置零、54. 螺旋矩阵、48. 旋转图像、240. 搜索二维矩阵 II
  • [1Prompt1Story] 生成行为控制器 | 语义向量重加权(SVR)