FreeRTOS --- 软件定时器

目录

一、软件定时器的特点

二、软件定时器的应用场景

三、软件定时器的基本概念

四、 软件定时器的相关API

五、软件定时器的优缺点

六、 软件定时器整体流程

七、使用示例

八、为什么已经有了硬件定时器还要软件定时器

九、总结


在FreeRTOS中,软件定时器(Software Timer) 是一种实现定时操作的机制。软件定时器允许任务在指定时间间隔后执行特定的回调函数,而无需任务一直占用CPU资源。这种定时器完全基于软件实现,并由FreeRTOS的调度器管理。

硬件定时器:由芯片内部提供,通常用于高精度场景,通过中断处理定时事件。

软件定时器:基于软件模拟定时功能,依赖系统时钟(Tick),适用于需要大量定时器的场景。

一、软件定时器的特点

  1. 完全基于软件:不依赖硬件定时器,由FreeRTOS管理和调度。

  2. 精度依赖系统节拍:软件定时器的精度取决于系统的Tick频率。

  3. 定时器任务独立:定时器的回调函数在FreeRTOS专用的定时器服务任务中执行,不干扰普通任务。

  4. 单次和周期性:支持一次性触发和周期性触发两种模式。

  5. 低功耗支持:在低功耗模式中,FreeRTOS会结合Tickless模式使软件定时器的精度尽可能高。

二、软件定时器的应用场景

  1. 周期性任务:如定时采集传感器数据、定时刷新显示屏。

  2. 一次性延时:如延时启动某功能。

  3. 超时处理:如通信超时、用户输入超时检测。

  4. 简化任务逻辑:避免任务中直接使用延时或循环检查,提高代码可读性。

三、软件定时器的基本概念

  1. 定时器句柄TimerHandle_t 是软件定时器的句柄,用于标识特定的定时器。

  2. 定时器周期:定时器的时间间隔,以系统Tick为单位(可以用 pdMS_TO_TICKS() 转换为毫秒)。

  3. 定时器回调函数:当定时器触发时,FreeRTOS会调用用户定义的回调函数。

  4. 一次性和周期性定时器

    • 一次性定时器:触发后自动停止。

    • 周期性定时器:每隔固定时间触发,直到显式停止。

四、 软件定时器的相关API

1.创建定时器  刚创建的软件定时器默认处于休眠态,不会触发回调函数。可通过 xTimerStart() 启动。

TimerHandle_t xTimerCreate(
    const char *const pcTimerName,     // 定时器名称(调试用)
    const TickType_t xTimerPeriod,    // 定时器周期(Tick数)
    const UBaseType_t uxAutoReload,   // 周期性定时器:pdTRUE;一次性定时器:pdFALSE
    void *const pvTimerID,            // 定时器ID,用户自定义数据
    TimerCallbackFunction_t pxCallbackFunction // 回调函数
);

 返回值:成功返回定时器句柄,失败返回 NULL

2.启动定时器 

BaseType_t xTimerStart(TimerHandle_t xTimer, TickType_t xTicksToWait);

参数xTimer:定时器句柄。ksToWait:阻塞等待时间。

返回值pdPASS 表示启动成功,pdFAIL 表示失败。

3.停止定时器

BaseType_t xTimerStop(TimerHandle_t xTimer, TickType_t xTicksToWait);

参数xTimer:定时器句柄。ksToWait:阻塞等待时间。

4.重启定时器

BaseType_t xTimerStop(TimerHandle_t xTimer, TickType_t xTicksToWait);

 参数xTimer:定时器句柄。ksToWait:阻塞等待时间。

5.修改定时器周期

BaseType_t xTimerChangePeriod(
    TimerHandle_t xTimer,
    TickType_t xNewPeriod,
    TickType_t xTicksToWait
);

 参数xTimer:定时器句柄。xNewPeriod:新周期。ksToWait:阻塞等待时间。

6.删除定时器

BaseType_t xTimerDelete(TimerHandle_t xTimer, TickType_t xTicksToWait);

 参数xTimer:定时器句柄。ksToWait:阻塞等待时间。

7.回调函数在定时器触发时调用。其原型如下:

void vTimerCallback(TimerHandle_t xTimer) { // 定时器触发后的处理逻辑 }

参数 xTimer 是触发回调的定时器句柄,可以通过它获取定时器相关信息。

8.软件定时器的工作流程

  1. 创建定时器:使用 xTimerCreate() 函数创建一个定时器,并指定其触发周期和回调函数。

  2. 启动定时器:调用 xTimerStart() 启动定时器。

  3. 定时器到期:在定时器的周期到期时,FreeRTOS会自动调用回调函数。

  4. 停止或重启定时器:根据应用需求,调用 xTimerStop()xTimerReset() 控制定时器。

五、软件定时器的优缺点

优点

  1. 节省硬件资源:多个定时器共享系统Tick,无需硬件定时器支持。

  2. 灵活性高:支持大量定时器,只需内存足够即可。可以动态调整定时器的周期和行为。

  3. 任务间解耦:通过回调函数处理定时器事件,简化任务逻辑。

  4. 易于实现:不需要额外的硬件资源。

缺点

  1. 依赖系统Tick:定时器精度受系统Tick频率限制,Tick太长会降低精度。

  2. 占用CPU时间:当定时器服务任务频繁执行时,会占用CPU资源。

  3. 受调度影响:系统优先级较低的任务可能会推迟回调函数的执行。

六、 软件定时器整体流程

  1. 创建列表与队列

    • 初始化定时器列表:

      vListInitialise( &xActiveTimerList1 ); vListInitialise( &xActiveTimerList2 );

    • 创建定时器命令队列:

      xTimerQueue = xQueueCreate();

  2. 启动任务调度器

    vTaskStartScheduler();

  3. 创建定时器服务任务: 定时器服务任务是专门处理软件定时器逻辑的任务,在调度器启动时被创建:

    xTimerCreateTimerTask();

  4. 软件定时器启动

    • 使用 xTimerStart() 启动计时。
    • 定时器通过命令队列与服务任务交互。
  5. 定时器超时逻辑

    • 服务任务判断定时器是否超时:

      prvGetNextExpireTime();

    • 若超时,调用用户定义的回调函数。
  6. 定时器命令处理

    • 添加、停止、复位等操作通过命令队列实现:

      prvProcessTimerOrBlockTask(); prvProcessReceivedCommands();

七、使用示例

周期性定时器示例

#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"

// 定时器回调函数
void vTimerCallback(TimerHandle_t xTimer) {
    printf("Timer Callback Triggered\n");
}

int main(void) {
    // 创建周期性定时器,周期为1000ms
    TimerHandle_t xTimer = xTimerCreate(
        "PeriodicTimer",          // 名称
        pdMS_TO_TICKS(1000),      // 周期
        pdTRUE,                   // 周期性
        NULL,                     // 定时器ID
        vTimerCallback            // 回调函数
    );

    if (xTimer != NULL) {
        // 启动定时器
        xTimerStart(xTimer, 0);
    }

    // 启动调度器
    vTaskStartScheduler();

    for (;;);
}

单次定时器示例

TimerHandle_t xTimer = xTimerCreate(
    "OneShotTimer",
    pdMS_TO_TICKS(5000), // 5秒超时
    pdFALSE,             // 单次定时器
    NULL,
    vTimerCallback
);
xTimerStart(xTimer, 0); // 启动定时器

八、为什么已经有了硬件定时器还要软件定时器

1. 数量限制:硬件定时器的数量通常有限(例如STM32中有4-14个定时器),而软件定时器理论上只需有足够的内存,就可以创建任意数量的定时器。因此,当需要大量定时器时,软件定时器是必要的。

2. 灵活性容易修改:可以动态调整定时周期,而硬件定时器需要重新配置寄存器。动态创建和销毁:可以在运行时根据需求创建和删除,而硬件定时器通常需要在初始化时固定分配。支持复用:可以通过软件定时器来实现复杂的定时逻辑,例如周期任务、延时启动等。

3. 简化任务管理:直接通过回调函数处理定时事件,不需要用户处理复杂的中断逻辑。不会阻塞或影响主任务的执行。

4. 节约硬件资源:硬件定时器是宝贵的资源,应优先用于需要高精度和实时响应的场景。如果可以用软件定时器满足需求,就可以节约硬件定时器资源供其他关键任务使用。

5.支持跨平台;硬件定时器的配置通常与具体的MCU型号和厂商紧密相关,而软件定时器基于操作系统,具有良好的跨平台性。

使用建议

高精度、实时性需求:使用硬件定时器。

数量多、灵活性需求:优先使用软件定时器。

复杂场景:两者结合使用,硬件定时器处理关键任务,软件定时器处理辅助任务。

九、总结

FreeRTOS软件定时器是一种灵活高效的定时机制,可以用于多种应用场景,如周期任务、超时处理和延时操作。在需要多个定时器且硬件资源有限时,软件定时器是一个非常实用的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值