[其他] 延时函数的实现方式有多少?

[复制链接]
 楼主| yiy 发表于 2025-3-31 17:45 | 显示全部楼层 |阅读模式
1. 阻塞式延时(忙等待)
(1) 空循环延时(软件延时)
原理:通过执行空循环占用 CPU 时间实现延时。

代码示例:
  1. void delay_us(uint32_t us) {
  2.   for (volatile uint32_t i = 0; i < us * 100; i++); // 根据时钟频率调整循环次数
  3. }
优点:无需硬件支持,简单直接。

缺点:

精度低:受编译器优化、时钟频率影响。

浪费 CPU 资源:阻塞其他任务执行。

适用场景:简单裸机程序,对实时性要求不高。

(2) 定时器查询延时
原理:通过轮询定时器寄存器判断时间是否到达。

代码示例:
  1. void delay_ms(uint32_t ms) {
  2.   uint32_t start_time = TIMER->CNT;  // 假设 TIMER 是硬件定时器
  3.   while ((TIMER->CNT - start_time) < (ms * 1000)); // 根据定时器频率计算
  4. }
优点:比空循环更精确。

缺点:仍占用 CPU 资源,需配置定时器硬件。

 楼主| yiy 发表于 2025-3-31 17:47 | 显示全部楼层
2. 非阻塞式延时
(1) 定时器中断延时
原理:利用定时器中断触发延时结束事件。

代码示例:
  1. volatile uint8_t delay_done = 0;

  2. void TIMER_IRQ_Handler() {
  3.   if (TIMER->SR & TIMER_FLAG_UPDATE) {
  4.     delay_done = 1;
  5.     TIMER->SR &= ~TIMER_FLAG_UPDATE;
  6.   }
  7. }

  8. void delay_ms(uint32_t ms) {
  9.   TIMER->ARR = ms * 1000;  // 设置定时器自动重装载值
  10.   TIMER->CR1 |= TIMER_ENABLE;  // 启动定时器
  11.   while (!delay_done);        // 等待中断标志
  12.   delay_done = 0;
  13. }
优点:释放 CPU 资源,可与其他任务并行执行。

缺点:需配置中断和定时器,代码复杂度稍高。

(2) 硬件定时器 + 非阻塞查询
原理:使用硬件定时器记录时间戳,通过差值计算是否超时。

代码示例:
  1. uint32_t get_tick() {
  2.   return TIMER->CNT;  // 获取当前定时器计数值
  3. }

  4. void delay_non_blocking(uint32_t start_tick, uint32_t delay_ticks) {
  5.   while ((get_tick() - start_tick) < delay_ticks);
  6. }

  7. // 调用示例:
  8. uint32_t start = get_tick();
  9. delay_non_blocking(start, 1000); // 延时 1000 个定时器周期
优点:非阻塞,适合主循环中处理多任务。

缺点:需主动调用时间检查。

3. 高级延时方案
(1) SysTick 定时器(ARM Cortex-M 内核)
原理:利用 Cortex-M 内置的 SysTick 定时器实现精准延时。

代码示例:
  1. void SysTick_Init() {
  2.   SysTick->LOAD = SystemCoreClock / 1000 - 1; // 1ms 中断一次
  3.   SysTick->VAL = 0;
  4.   SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
  5. }

  6. void delay_ms(uint32_t ms) {
  7.   uint32_t start = SysTick->VAL;
  8.   while (ms--) {
  9.     while (((start - SysTick->VAL) & 0xFFFFFF) >= (SystemCoreClock / 1000));
  10.     start = SysTick->VAL;
  11.   }
  12. }
优点:高精度,与内核时钟同步。

缺点:依赖特定硬件(如 ARM Cortex-M)。

(2) RTOS 延时(如 FreeRTOS)
原理:利用实时操作系统(RTOS)的任务调度机制实现延时。

代码示例:
  1. #include "FreeRTOS.h"
  2. #include "task.h"

  3. void task_function() {
  4.   while (1) {
  5.     vTaskDelay(pdMS_TO_TICKS(100)); // 延时 100ms
  6.     // 执行其他任务
  7.   }
  8. }
优点:完全非阻塞,支持多任务并发。

缺点:需引入 RTOS,增加系统复杂度。

(3) PWM 或 DMA 硬件延时
原理:利用 PWM 输出或 DMA 传输自动控制延时(如生成精确脉冲)。

适用场景:需要硬件级精准延时的场景(如 WS2812 LED 驱动)。

4. 其他特殊实现
看门狗定时器:复用看门狗定时器实现超时检测(需谨慎使用)。

低功耗模式延时:在低功耗模式下使用 RTC 或低功耗定时器唤醒。

 楼主| yiy 发表于 2025-3-31 17:47 | 显示全部楼层
场景                                                推荐方案
简单裸机程序                                空循环或定时器查询
高精度需求                                硬件定时器(如 SysTick)
多任务系统                                RTOS 延时
低功耗场景                                RTC 或低功耗定时器 + 中断唤醒
硬件级精准控制(如 PWM)        专用硬件模块(PWM/DMA)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

yiy

114

主题

1929

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部
yiy

114

主题

1929

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部