软件定时器 API 函数详解

FreeRTOS 软件定时器 API 函数详解

FreeRTOS 的 软件定时器(Software Timer) 允许在指定时间间隔或单次触发后执行回调函数,由守护任务(Timer Task)统一管理。适用于周期性任务调度或延时操作,无需占用硬件定时器资源。以下是软件定时器相关 API 的全面讲解,涵盖动态/静态创建、启停控制及中断安全操作。


核心概念

  • 守护任务:系统自动创建的优先级可配置的任务(由 configTIMER_TASK_PRIORITY 定义),负责处理定时器到期事件。
  • 回调函数:定时器触发时执行,不可阻塞(如使用 vTaskDelay() 或队列操作)。
  • 单次/自动重载:定时器可配置为单次触发(pdFALSE)或周期性触发(pdTRUE)。
  • 内存管理
    • 动态创建:使用 FreeRTOS 堆内存。
    • 静态创建:需用户预先分配内存。

API 函数详解

1. 创建定时器
(1) 动态创建:xTimerCreate()
TimerHandle_t xTimerCreate(
    const char * const pcTimerName,        // 定时器名称(调试用)
    const TickType_t xTimerPeriodInTicks,  // 周期(单位:系统节拍)
    const UBaseType_t uxAutoReload,        // 自动重载模式(pdTRUE/pdFALSE)
    void * const pvTimerID,                // 用户标识符(用于区分多个定时器)
    TimerCallbackFunction_t pxCallbackFunction // 回调函数
);
  • 返回值:成功返回定时器句柄,失败返回 NULL
  • 示例
    TimerHandle_t xTimer = xTimerCreate(
        "MyTimer", 
        1000 / portTICK_PERIOD_MS, // 1秒周期
        pdTRUE,                    // 自动重载
        (void*)1,                  // ID标识
        vTimerCallback             // 回调函数
    );
    
(2) 静态创建:xTimerCreateStatic()
TimerHandle_t xTimerCreateStatic(
    const char * const pcTimerName,
    const TickType_t xTimerPeriodInTicks,
    const UBaseType_t uxAutoReload,
    void * const pvTimerID,
    TimerCallbackFunction_t pxCallbackFunction,
    StaticTimer_t *pxTimerBuffer           // 用户分配的静态内存
);
  • 特点:需预先定义 StaticTimer_t 结构体,避免动态内存分配。
  • 示例
    StaticTimer_t xTimerBuffer;
    TimerHandle_t xTimer = xTimerCreateStatic(..., &xTimerBuffer);
    

2. 启动定时器
(1) 标准启动:xTimerStart()
BaseType_t xTimerStart(
    TimerHandle_t xTimer,        // 定时器句柄
    TickType_t xTicksToWait      // 阻塞时间(若守护任务队列满)
);
  • 返回值
    • pdPASS:启动命令成功发送到守护任务队列。
    • pdFAIL:队列已满且超时(仅当 xTicksToWait > 0 时可能发生)。
(2) 中断安全版本:xTimerStartFromISR()
BaseType_t xTimerStartFromISR(
    TimerHandle_t xTimer,
    BaseType_t *pxHigherPriorityTaskWoken // 标记是否需触发上下文切换
);
  • 使用示例
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xTimerStartFromISR(xTimer, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    

3. 停止定时器
(1) 标准停止:xTimerStop()
BaseType_t xTimerStop(
    TimerHandle_t xTimer,
    TickType_t xTicksToWait
);
  • 功能:停止定时器,若定时器未运行则无操作。
(2) 中断安全版本:xTimerStopFromISR()
BaseType_t xTimerStopFromISR(
    TimerHandle_t xTimer,
    BaseType_t *pxHigherPriorityTaskWoken
);

4. 重置定时器
(1) 标准重置:xTimerReset()
BaseType_t xTimerReset(
    TimerHandle_t xTimer,
    TickType_t xTicksToWait
);
  • 功能:重新开始计时,若定时器未运行则启动它。
(2) 中断安全版本:xTimerResetFromISR()
BaseType_t xTimerResetFromISR(
    TimerHandle_t xTimer,
    BaseType_t *pxHigherPriorityTaskWoken
);

5. 修改定时器周期
(1) 标准修改:xTimerChangePeriod()
BaseType_t xTimerChangePeriod(
    TimerHandle_t xTimer,
    TickType_t xNewPeriod,      // 新周期(单位:系统节拍)
    TickType_t xTicksToWait
);
  • 特点:立即生效,若定时器正在运行,重新计算到期时间。
(2) 中断安全版本:xTimerChangePeriodFromISR()
BaseType_t xTimerChangePeriodFromISR(
    TimerHandle_t xTimer,
    TickType_t xNewPeriod,
    BaseType_t *pxHigherPriorityTaskWoken
);

6. 查询定时器状态
(1) 查询是否运行:xTimerIsTimerActive()
BaseType_t xTimerIsTimerActive(TimerHandle_t xTimer);
  • 返回值pdTRUE(运行中)或 pdFALSE(未运行)。
(2) 获取定时器ID:pvTimerGetTimerID()
void *pvTimerGetTimerID(TimerHandle_t xTimer);
  • 用途:在回调函数中区分不同定时器。

7. 删除定时器
(1) 动态删除:xTimerDelete()
BaseType_t xTimerDelete(
    TimerHandle_t xTimer,
    TickType_t xTicksToWait
);
  • 注意:仅对动态创建的定时器有效,静态定时器需手动释放内存。

回调函数模板

void vTimerCallback(TimerHandle_t xTimer) {
    void *pvID = pvTimerGetTimerID(xTimer); // 获取定时器ID
    switch((uint32_t)pvID) {
        case 1:
            // 处理定时器1事件
            break;
        case 2:
            // 处理定时器2事件
            break;
    }
}

使用示例

创建并启动周期性定时器
void vTimerCallback(TimerHandle_t xTimer) {
    static int count = 0;
    count++;
    printf("Timer triggered, count = %d\n", count);
}

void main() {
    TimerHandle_t xTimer = xTimerCreate(
        "PeriodicTimer",
        1000 / portTICK_PERIOD_MS, // 1秒周期
        pdTRUE,                    // 自动重载
        (void*)1,                  // ID
        vTimerCallback
    );
    if (xTimer != NULL) {
        xTimerStart(xTimer, 0);    // 立即启动
    }
    vTaskStartScheduler();
}
中断中重启定时器
void vInterruptHandler(void) {
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xTimerResetFromISR(xTimer, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

注意事项

  1. 回调函数限制

    • 不可阻塞:避免使用 vTaskDelay(), xQueueSend() 等阻塞函数。
    • 快速执行:长时间操作会阻塞守护任务,影响其他定时器触发。
  2. 守护任务配置

    • 优先级:通过 configTIMER_TASK_PRIORITY 设置(通常高于应用任务)。
    • 队列长度:由 configTIMER_QUEUE_LENGTH 定义(默认 10),若定时器操作频繁需增大。
  3. 静态定时器生命周期

    • 需确保 StaticTimer_t 内存的有效性,避免提前释放。
  4. 中断安全操作

    • 在 ISR 中必须使用 FromISR 版本,并处理任务切换。

总结表格:关键API对比

API 函数功能中断安全版本
xTimerCreate动态创建定时器
xTimerCreateStatic静态创建定时器
xTimerStart启动定时器xTimerStartFromISR
xTimerStop停止定时器xTimerStopFromISR
xTimerReset重置定时器xTimerResetFromISR
xTimerChangePeriod修改定时器周期xTimerChangePeriodFromISR
xTimerDelete删除动态定时器
xTimerIsTimerActive查询定时器是否激活

通过合理使用软件定时器,可实现精准的周期性任务调度,优化系统资源分配。务必遵循回调函数的设计规范,确保系统的实时性和稳定性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九层指针

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值