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);
}
相关推荐
旖旎夜光2 小时前
C++(17)
c++·学习
Larry_Yanan3 小时前
Qt多进程(三)QLocalSocket
开发语言·c++·qt·ui
醒过来摸鱼3 小时前
Java classloader
java·开发语言·python
superman超哥3 小时前
仓颉语言中元组的使用:深度剖析与工程实践
c语言·开发语言·c++·python·仓颉
小鸡吃米…4 小时前
Python - 继承
开发语言·python
JIngJaneIL4 小时前
基于java+ vue农产投入线上管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
祁思妙想4 小时前
Python中的FastAPI框架的设计特点和性能优势
开发语言·python·fastapi
唐装鼠4 小时前
rust自动调用Deref(deepseek)
开发语言·算法·rust
Lucas555555554 小时前
现代C++四十不惑:AI时代系统软件的基石与新征程
开发语言·c++·人工智能
源代码•宸4 小时前
goframe框架签到系统项目(BITFIELD 命令详解、Redis Key 设计、goframe 框架教程、安装MySQL)
开发语言·数据库·经验分享·redis·后端·mysql·golang