软件定时器用法

以下是一个基于 FreeRTOS 的软件定时器(Software Timer) 的完整示例代码,包含初始化、定时器创建、启动和回调函数实现,适用于实际应用场景(如周期性任务控制)。


示例场景

使用软件定时器实现以下功能:

  1. 每隔 1秒 打印一次系统运行时间。
  2. 每隔 500毫秒 切换 LED 状态。

代码实现

1. 配置 FreeRTOS(FreeRTOSConfig.h
#define configUSE_TIMERS                 1   // 启用软件定时器
#define configTIMER_TASK_PRIORITY       (configMAX_PRIORITIES - 1)  // 定时器任务优先级(建议较高)
#define configTIMER_QUEUE_LENGTH        10  // 定时器命令队列长度
#define configTIMER_TASK_STACK_DEPTH    (configMINIMAL_STACK_SIZE * 2)  // 定时器任务堆栈大小
2. 定义定时器句柄和回调函数
#include "FreeRTOS.h"
#include "timers.h"

// 定义定时器句柄
TimerHandle_t xPrintTimerHandle = NULL;
TimerHandle_t xLedTimerHandle = NULL;

// 定时器1回调函数:打印系统时间
void vPrintTimerCallback(TimerHandle_t xTimer) {
    static uint32_t tickCount = 0;
    tickCount = xTaskGetTickCount(); // 获取系统节拍数
    printf("[Timer] System Ticks: %lu ms\n", tickCount);
}

// 定时器2回调函数:切换LED状态
void vLedTimerCallback(TimerHandle_t xTimer) {
    static bool ledState = false;
    ledState = !ledState;
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, ledState ? GPIO_PIN_SET : GPIO_PIN_RESET);
    printf("[Timer] LED Toggled\n");
}
3. 创建并启动定时器(在任务中初始化)
void StartDefaultTask(void *argument) {
    // 创建定时器1:1秒周期,自动重载
    xPrintTimerHandle = xTimerCreate(
        "PrintTimer",                // 定时器名称(调试用)
        pdMS_TO_TICKS(1000),         // 定时周期(1秒)
        pdTRUE,                      // 自动重载(周期性)
        (void *)0,                   // 定时器ID(可传递参数)
        vPrintTimerCallback          // 回调函数
    );

    // 创建定时器2:500毫秒周期,自动重载
    xLedTimerHandle = xTimerCreate(
        "LedTimer",
        pdMS_TO_TICKS(500),
        pdTRUE,
        (void *)0,
        vLedTimerCallback
    );

    // 启动定时器
    if (xPrintTimerHandle != NULL && xLedTimerHandle != NULL) {
        xTimerStart(xPrintTimerHandle, 0); // 第二个参数是阻塞时间(0表示不阻塞)
        xTimerStart(xLedTimerHandle, 0);
    }

    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000)); // 主任务延时(非必要)
    }
}
4. 主函数中启动调度器
int main(void) {
    // 硬件初始化(如LED GPIO、串口等)
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART1_UART_Init();

    // 创建启动任务
    xTaskCreate(StartDefaultTask, "StartTask", 128, NULL, 1, NULL);

    // 启动FreeRTOS调度器
    vTaskStartScheduler();

    while (1) {}
}

关键解释

  1. 定时器创建

    • xTimerCreate():动态分配定时器对象,需指定名称、周期、重载模式、ID 和回调函数。
    • pdMS_TO_TICKS():将毫秒时间转换为 FreeRTOS 节拍数(依赖 configTICK_RATE_HZ)。
  2. 定时器启动

    • xTimerStart():启动定时器,第二个参数是等待命令发送到队列的最大时间(0表示不阻塞)。
  3. 回调函数特性

    • 回调函数在 定时器任务(Timer Task) 中执行,优先级由 configTIMER_TASK_PRIORITY 决定。
    • 不可调用阻塞函数(如 vTaskDelay),否则会阻塞定时器任务。

输出结果

[Timer] System Ticks: 1000 ms
[Timer] LED Toggled
[Timer] LED Toggled
[Timer] System Ticks: 2000 ms
[Timer] LED Toggled
[Timer] LED Toggled
...

常见问题

  1. 定时器回调未执行

    • 检查 configTIMER_TASK_PRIORITY 是否足够高,避免被其他任务阻塞。
    • 确保定时器任务堆栈(configTIMER_TASK_STACK_DEPTH)足够。
  2. 定时精度不足

    • 软件定时器精度依赖系统节拍(如 configTICK_RATE_HZ=1000 时最小间隔 1ms)。
    • 高精度需求请改用硬件定时器。

实际应用扩展

  • 超时检测:用于通信协议等待应答超时。
  • 任务看门狗:定期检查任务是否存活。
  • 数据采集:周期性读取传感器数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

九层指针

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

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

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

打赏作者

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

抵扣说明:

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

余额充值