定时器和延时函数选型

1,定时器和延时使用场景对比

场景分类 具体子场景 推荐方式 原因/备注
硬件初始化 时钟稳定等待(如 PLL 起振) 硬件循环 delay 调度器未启动,不能用 OS 延时
外设复位释放(如 LCD 复位脉冲 100ms) 硬件循环 delay 同上,或者用硬件定时器(如 SysTick 裸机轮询)
软件初始化 数据结构、变量赋值 无需延时 -
等待其他模块就绪标志(如传感器上电初始化完成) 阻塞 delay + 检查标志 简单实现,但会占用任务;推荐用事件/队列
任务内操作 周期性读取传感器(允许抖动) vTaskDelay 阻塞任务,适合低优先级周期任务
高精度周期控制(PWM、电机控制) 硬件定时器 OS 软件定时器精度不足(受 tick 限制)
一次性延时后修改 GPIO 软件定时器 不占用任务堆栈,不影响其他任务实时性
与多个异步事件同步(如等待超时或收到消息) 队列/事件组 + 超时 vTaskDelay 无法同时等待事件
中断上下文 中断中需要短延时(去抖动、总线保持) 绝对禁止 delay 必须用硬件定时器或直接退出中断
中断后需要延时处理(如按键长按检测) 启动软件定时器 中断中启动定时器,回调中处理长按逻辑
低功耗 CPU 进入睡眠模式,需要定时唤醒 硬件定时器(RTC/WDT) OS 软件定时器依赖系统 tick,睡眠时可能不工作
空闲任务自动休眠(Tickless) OS 内置机制 FreeRTOS/LiteOS 支持 tickless,使用硬件定时器作为唤醒源
通信 UART/I2C 接收超时检测 软件定时器或带超时的队列接收 队列接收时直接使用 xQueueReceive(..., timeout) 更好,内部阻塞不占CPU
模拟 I2C 的 SCL 时钟延时 硬件循环 delay 微秒级延时,OS 无法满足
用户交互 按键消抖(20ms) 软件定时器 避免阻塞主任务,消抖期间系统仍可响应其他操作
LED 闪烁(1Hz) 软件定时器或任务 + delay 定时器方式更节省任务资源;任务方式更直观
调试与监测 串口打印心跳 vTaskDelay 简单,无需额外创建定时器
看门狗喂狗 周期软件定时器 喂狗必须可靠且不依赖某个任务可能被饿死
系统行为 系统启动后先进行 500ms 预热 起始任务中 vTaskDelay 预热期间无需做其他事,阻塞当前任务即可
多个外设需要按顺序延时上电(如先开 3.3V,20ms 后再开 1.8V) 软件定时器链或任务顺序 delay 简单用任务 delay,复杂用定时器链(首个定时器回调启动第二个)

系统启动后(复位后),某个 GPIO 引脚立即输出高电平 ,经过 10ms 后自动恢复为低电平

2,定时器实现

复制代码
#include "los_swtmr.h"
#include "gpio.h"

// 定时器回调函数
void TimerCallback(UINT32 arg) {
    GPIO_SetLow(PIN_LED);   // 恢复低电平
}

void main(void) {
    // 硬件初始化
    GPIO_Init(PIN_LED, OUTPUT);
    GPIO_SetHigh(PIN_LED);

    // 创建单次软件定时器
    UINT32 timerId;
    SWTMR_CTRL_S stCtrl = {0};
    stCtrl.uwMode = LOS_SWTMR_MODE_ONCE;   // 单次模式
    stCtrl.uwInterval = 10;                // 10ms(注意:LiteOS 定时器单位是 tick,默认 1ms/tick)
    stCtrl.pfnHandler = (SWTMR_PROC_FUNC)TimerCallback;
    LOS_SwtmrCreate(&stCtrl, &timerId);
    LOS_SwtmrStart(timerId);

    // 启动 LiteOS 调度器
    LOS_Start();
}

任务内使用 LOS_TaskDelay(阻塞)

复制代码
#include "los_task.h"
#include "gpio.h"

UINT32 vPulseTask(UINT32 arg) {
    GPIO_Init(PIN_LED, OUTPUT);
    GPIO_SetHigh(PIN_LED);
    LOS_TaskDelay(10);      // 阻塞当前任务 10ms
    GPIO_SetLow(PIN_LED);
    return LOS_OK;
}

void main(void) {
    UINT32 taskId;
    TSK_INIT_PARAM_S taskParam = {0};
    taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)vPulseTask;
    taskParam.usTaskPrio = 1;
    taskParam.uwStackSize = 0x800;
    taskParam.pcName = "PulseTask";
    LOS_TaskCreate(&taskId, &taskParam);
    LOS_Start();
}
特性 软件定时器(单次/周期) delay(阻塞延时)
是否阻塞 不阻塞任何任务(回调在定时器任务/中断中执行) 阻塞调用该函数的任务
上下文要求 回调中不能调用阻塞 API(如队列接收、delay) 只能在任务中调用
CPU 占用 极低,仅系统时钟中断 + 定时器任务 阻塞期间让出 CPU,唤醒后继续
精度 取决于系统时钟 tick,通常 1ms ~ 10ms 相同
典型用途 超时处理、非阻塞的延时动作、周期性维护 简单的顺序延时、初始化等待

补充: freertos的实现

复制代码
#include "FreeRTOS.h"
#include "timers.h"
#include "gpio.h"   // 假设的 GPIO 操作函数

// 定时器回调函数:将引脚设为低电平
void vTimerCallback(TimerHandle_t xTimer) {
    GPIO_SetLow(PIN_LED);   // 恢复低电平
}

void main(void) {
    // 硬件初始化
    GPIO_Init(PIN_LED, OUTPUT);
    GPIO_SetHigh(PIN_LED);  // 立即输出高电平

    // 创建单次定时器,周期 10ms(单位:Tick,假设 configTICK_RATE_HZ = 1000)
    TimerHandle_t xTimer = xTimerCreate("OneShot", pdMS_TO_TICKS(10), pdFALSE,
                                         NULL, vTimerCallback);
    if (xTimer != NULL) {
        xTimerStart(xTimer, 0);  // 启动定时器,非阻塞
    }

    // 启动调度器(之后定时器会在系统时钟中断/软件定时器任务中执行)
    vTaskStartScheduler();

    // 不会执行到这里
    for(;;);
}
  • xTimerStart 立即返回,不阻塞当前上下文。

  • 10ms 后系统自动调用回调,在软件定时器任务(或中断)中完成电平切换。

  • 不影响其他任务运行,适合在多任务环境中让高电平脉冲独立完成。

延时函数实现

复制代码
#include "FreeRTOS.h"
#include "task.h"
#include "gpio.h"

void vPulseTask(void *pvParameters) {
    GPIO_Init(PIN_LED, OUTPUT);
    GPIO_SetHigh(PIN_LED);      // 高电平
    vTaskDelay(pdMS_TO_TICKS(10)); // 阻塞当前任务 10ms
    GPIO_SetLow(PIN_LED);       // 低电平
    vTaskDelete(NULL);          // 任务结束,可选
}

void main(void) {
    xTaskCreate(vPulseTask, "Pulse", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    vTaskStartScheduler();
}
  • 任务进入阻塞状态,让出 CPU 给其他就绪任务。

  • 实现简单,但占用一个任务堆栈,且该任务在 10ms 内无法做其他事。

相关推荐
水利行业RTU手艺人7 小时前
RTU固件中的“数据保险箱”——离线数据补发系统设计
c++·stm32·单片机·物联网
2301_793121049 小时前
基于单片机的水平角度仪系统设计
单片机·嵌入式硬件
KaifuZeng9 小时前
通信与接口协议面试十、PCIe
单片机·嵌入式硬件·面试·通信与接口协议
lzx1864884370210 小时前
【AH8966】可替代 KP3211 非隔离 AC110220V转12V 0.5A 降压转换芯片
人工智能·单片机·嵌入式硬件·集成测试·硬件工程·ic
csg110711 小时前
PIC单片机防破解:从硬件到软件的全面防护
单片机·嵌入式硬件·物联网·自动化
电化学仪器白超11 小时前
低阻域 ADC 与参考源选型理论分析
人工智能·python·单片机·嵌入式硬件·自动化
小小的代码里面挖呀挖呀挖11 小时前
杰理蓝牙耳机开发--LE Audio与游戏耳机应用
笔记·单片机·物联网·学习
张海森-16882012 小时前
怎么算进程 总共运行时间
单片机
bu_shuo13 小时前
STM32-BOOT的三种启动方式
stm32·单片机·嵌入式硬件
sramdram14 小时前
低功耗MCU芯片电机控制专用
单片机·嵌入式硬件·mcu·低功耗mcu·mcu芯片