FREERTOS_定时器——创建和基本使用

一、核心基础概念

  1. 软件定时器本质:基于系统时钟 tick 实现,由内核的 "定时器服务任务" 管理,触发时执行预设回调函数;
  2. 两种工作模式
    • 周期模式:定时器到期后自动重装载,持续触发回调(如周期性闪烁);
    • 单次模式:定时器到期后停止,仅触发一次回调(如延时 3 秒后恢复默认状态);
  3. 回调函数限制 :必须是void vCallback(TimerHandle_t xTimer)格式,不能调用阻塞 API (如vTaskDelay()xQueueReceive()),仅执行短时间操作。

二、定时器的创建与启动流程

1、包含头文件
复制代码
#include "FreeRTOS.h"
#include "timers.h" // 定时器API声明在此头文件
2、定义定时器句柄
复制代码
TimerHandle_t xMyTimer; // 定时器句柄
3、创建定时器(核心步骤)
复制代码
xMyTimer = xTimerCreate(
  "MyTimer",            // 定时器名称(仅调试用,可自定义)
  pdMS_TO_TICKS(500U),  // 定时周期(毫秒转FreeRTOS tick数)
  pdTRUE,               // 工作模式:pdTRUE=周期,pdFALSE=单次
  (void *)0,            // 定时器ID(区分多个定时器,自定义)
  vMyTimerCallback      // 定时器到期回调函数(必须实现)
);
4、启动定时器

创建后需调用xTimerStart()启动,否则定时器不会工作

复制代码
if(xMyTimer != NULL) {
  xTimerStart(xMyTimer, 0); // 0=非阻塞启动,立即返回
}

三、定时器的基本使用(核心操作)

1、 回调函数实现(核心逻辑载体)
复制代码
// 定时器回调函数(必须符合格式要求)
void vMyTimerCallback(TimerHandle_t xTimer) {
  // 示例:翻转LED(仅执行短时间操作)
  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
  
  // 注意:不能调用 vTaskDelay()、xQueueReceive() 等阻塞API
}
2、常用API(动态操作定时器)
函数 作用 关键参数说明
xTimerStart() 启动定时器(创建后首次启动) xTicksToWait:启动超时时间(0 = 非阻塞)
xTimerReset() 重置定时器(重新开始计时) 适用于单次模式重复触发,或周期模式重新计时
xTimerChangePeriod() 动态修改定时器周期 第 3 个参数为超时时间(如 0 = 非阻塞修改)
xTimerStop() 停止定时器(停止后需重新启动才生效) xTicksToWait:停止超时时间
3、周期与 tick 数转换

FreeRTOS 定时器周期以 "tick 数" 为单位,需用pdMS_TO_TICKS(ms)将毫秒转换为 tick 数(适配系统时钟频率):

复制代码
// 500毫秒 → 对应tick数(自动适配 configTICK_RATE_HZ)
pdMS_TO_TICKS(500U)

四、例子------单次

时器启动后只触发一次回调函数,触发完成后就自动停止,不会重复执行

创建
复制代码
TimerHandle_t xSwitchTimer; // 模式切换定时器(单次模式)
void vSwitchTimerCallback(TimerHandle_t xTimer); // 模式切换定时器回调函数

  // 1.2 模式切换定时器(单次模式,触发后只执行一次)
  xSwitchTimer = xTimerCreate(
    "SwitchTimer",
    pdMS_TO_TICKS(SWITCH_TIMER_DELAY),
    pdFALSE,               // 单次模式
    (void *)1,             // 定时器ID=1
    vSwitchTimerCallback
  );
回调函数
复制代码
/* 模式切换定时器回调函数:3秒后执行,恢复默认模式 */
void vSwitchTimerCallback(TimerHandle_t xTimer)
{
  // 定时器到期,恢复LED默认模式
  xCurrentLedMode = LED_MODE_DEFAULT;
}

xSwitchTimer单次模式 ,代码中没有在初始化时启动它,而是在按键任务中通过 xTimerReset() 启动 / 重置。

这里我要根据按键触发启动及再次启动它,所以增加了按下按键后再次开启它

复制代码
xTimerReset(xSwitchTimer, 0); // 重置定时器 若定时器已在运行,重置为3秒后触发

五、例子------周期

创建
复制代码
TimerHandle_t xBlinkTimer;  // 基础闪烁定时器(周期模式)
void vBlinkTimerCallback(TimerHandle_t xTimer); // 闪烁定时器回调函数

// 1.1 基础闪烁定时器(周期模式,自动重装载)
  xBlinkTimer = xTimerCreate(
    "BlinkTimer",          // 定时器名称(仅调试用)
    pdMS_TO_TICKS(BLINK_TIMER_PERIOD), // 周期(毫秒转FreeRTOS ticks)
    pdTRUE,                // 模式:pdTRUE=周期模式,pdFALSE=单次模式
    (void *)0,             // 定时器ID(区分多个定时器)
    vBlinkTimerCallback    // 定时器到期回调函数
  );
启动
复制代码
   xTimerStart(xBlinkTimer, 0); // 启动闪烁定时器(0=非阻塞启动)
回调函数
复制代码
/* 定时器回调函数:定时器到期时执行(控制LED翻转)xBlinkTimer  */
void vBlinkTimerCallback(TimerHandle_t xTimer)
{
  // 根据当前LED模式,调整闪烁周期
  switch(xCurrentLedMode) {
    case LED_MODE_FAST:
      // 快闪:修改定时器周期为200ms
      xTimerChangePeriod(xBlinkTimer, pdMS_TO_TICKS(200U),0);
      break;
    case LED_MODE_SLOW:
      // 慢闪:修改定时器周期为800ms
      xTimerChangePeriod(xBlinkTimer, pdMS_TO_TICKS(800U),0);
      break;
    case LED_MODE_DEFAULT:
    default:
      // 默认:恢复500ms周期
      xTimerChangePeriod(xBlinkTimer, pdMS_TO_TICKS(500U),0);
      break;
  }

  // 翻转LED(回调函数中避免长时间操作,仅执行简单逻辑)
  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_10);
}
相关推荐
扣脚大汉在网络32 分钟前
关于一句话木马
开发语言·网络安全
暗然而日章34 分钟前
C++基础:Stanford CS106L学习笔记 5 内存与指针
c++·笔记·学习
秋深枫叶红34 分钟前
嵌入式第二十六篇——数据结构双向链表
c语言·数据结构·学习·链表
学技术的大胜嗷35 分钟前
如何在 VSCode 中高效开发和调试 C++ 程序:面向用过 Visual Studio 的小白
c++·vscode·visual studio
ExiFengs37 分钟前
使用Java 8函数式编程优雅处理多层嵌套数据
java·开发语言·python
liu****39 分钟前
10.指针详解(六)
c语言·开发语言·数据结构·c++·算法
美味小鱼40 分钟前
DupFinder:一个用 Rust 编写的高性能重复文件查找工具
开发语言·后端·rust
报错小能手42 分钟前
C++流类库 标准输入流的安全性与成员函数 ostream 成员函数与自定义类型的IO
开发语言·c++·cocoa
黑客思维者42 分钟前
凌科芯安LKT6850安全MCU的技术特性与多领域应用
单片机·嵌入式硬件·安全·硬件加密