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);
}
注意事项
-
回调函数限制:
- 不可阻塞:避免使用
vTaskDelay()
,xQueueSend()
等阻塞函数。 - 快速执行:长时间操作会阻塞守护任务,影响其他定时器触发。
- 不可阻塞:避免使用
-
守护任务配置:
- 优先级:通过
configTIMER_TASK_PRIORITY
设置(通常高于应用任务)。 - 队列长度:由
configTIMER_QUEUE_LENGTH
定义(默认 10),若定时器操作频繁需增大。
- 优先级:通过
-
静态定时器生命周期:
- 需确保
StaticTimer_t
内存的有效性,避免提前释放。
- 需确保
-
中断安全操作:
- 在 ISR 中必须使用
FromISR
版本,并处理任务切换。
- 在 ISR 中必须使用
总结表格:关键API对比
API 函数 | 功能 | 中断安全版本 |
---|---|---|
xTimerCreate | 动态创建定时器 | 无 |
xTimerCreateStatic | 静态创建定时器 | 无 |
xTimerStart | 启动定时器 | xTimerStartFromISR |
xTimerStop | 停止定时器 | xTimerStopFromISR |
xTimerReset | 重置定时器 | xTimerResetFromISR |
xTimerChangePeriod | 修改定时器周期 | xTimerChangePeriodFromISR |
xTimerDelete | 删除动态定时器 | 无 |
xTimerIsTimerActive | 查询定时器是否激活 | 无 |
通过合理使用软件定时器,可实现精准的周期性任务调度,优化系统资源分配。务必遵循回调函数的设计规范,确保系统的实时性和稳定性。