FreeRTOS软件定时器
软件定时器
对某些精度要求不高的场合,可以不使用硬件定时器
定时器服务任务本身也是一个任务(系统自动创建的任务)
用户对寄存器操作的指令实际上是通过定时器指令队列传给这个任务,然后这个任务来执行操作
定时器到期后执行回调函数,回调函数无法阻塞,无法延时
(1)USE_TIMERS
- 功能:启用或禁用整个软件定时器功能。
- 默认值:
Enabled(启用)。 - 关键特性:一旦启用,不可修改(在CubeMX中灰色显示,无法禁用)。启用后,FreeRTOS内核会自动创建定时器服务任务和指令队列。
- 建议:始终保持启用,除非系统绝对不需要软件定时器功能。
(2)TIMER_TASK_PRIORITY
- 功能:设置定时器服务任务的优先级。
- 默认值:
2。 - 设置范围:
0到55(因为FreeRTOS优先级总数通常为56)。 - 优先级上下文:比空闲任务(优先级
0)高,确保定时器服务总能及时运行。但低于许多应用任务(典型应用任务优先级在3及以上)。 - 配置建议:提高优先级(如
5以上):如果定时器回调需要快速响应(如实时控制)。降低优先级(如1):如果定时器操作不紧急,避免抢占关键任务。避免与硬件中断冲突:优先级不应高于系统关键中断处理任务。
(3)TIMER_QUEUE_LENGTH
- 功能:设置定时器指令队列的长度(即队列可存储的消息数量)。
- 默认值:未明确显示,但通常为
10(根据FreeRTOS常见默认)。 - 设置范围:
1到255。 - 作用:该队列用于缓冲定时器操作命令(如启动、停止、复位定时器)。
- 配置建议:小型系统:设置
5-10(少量定时器操作)。大型系统:设置20-50(频繁定时器操作,防止队列溢出)。监控队列使用:如果队列常满,增加长度以避免命令丢失。
(4)TIMER_TASK_STACK_DEPTH
- 功能:设置定时器服务任务的栈空间大小**(以字(Word)为单位)。
- 默认值:
256words(通常对应1KB栈空间,假设1 word = 4字节)。 - 设置范围:
128到32768words。 - 重要性:栈空间不足会导致定时器服务任务崩溃,影响所有定时器。
- 配置建议:基础应用:
256-512words(简单回调函数)。复杂回调:1024-2048words(回调函数使用较多局部变量或调用深层函数)。调试方法:使用FreeRTOS的栈溢出检查功能(如configCHECK_FOR_STACK_OVERFLOW)。
常见问题与解决方案
- 问题1:定时器回调执行延迟或不执行。原因:定时器服务任务优先级过低,被高优先级任务阻塞。解决:提高
TIMER_TASK_PRIORITY(如设为4或5)。 - 问题2:系统不稳定或崩溃。原因:定时器服务任务栈溢出。解决:增加
TIMER_TASK_STACK_DEPTH,并检查回调函数是否过于复杂。 - 问题3:定时器操作(如启动)失败。原因:指令队列已满。解决:增加
TIMER_QUEUE_LENGTH或减少并发定时器操作。
定时器服务任务如果比一般任务的优先级高,则先执行
否则仅仅是让定时器服务收到接受指令后仅仅进入就绪状态
仅仅是定时器服务任务处理定时器指令的时机是不同的,定时器的起始时间都是从发送“启动定时器”指令到队列才开始计算的
定时器相关函数
1 | TimerHandle_t xTimerCreate(const char* const pcTimerName, |
pcTimerName- 定时器名称
xTimerPeriodInTicks`- 定时周期
uxAutoReload- 定时器类型
pdTRUE:周期定时器(自动重载),定时器到期自动重启pdFALSE:单次定时器,只执行一次后进入休眠状态
重要特性:定时器类型在创建后无法修改
pvTimerID- 定时器标识符
当多个定时器共享同一个回调函数时,用于区分不同定时器
pxCallbackFunction- 回调函数
- 初始状态:新创建的定时器处于休眠状态(Dormant)
- 启动定时器:必须调用
xTimerStart()或xTimerReset()启动定时器
设置定时器周期
1 |
xTimer:目标定时器的句柄(TimerHandle_t类型)xNewPeriod:新的定时周期(以系统节拍数表示)可使用pdMS_TO_TICKS()宏将毫秒转换为节拍数示例:pdMS_TO_TICKS(500)表示500毫秒xTicksToWait:指令发送等待时间0:不等待,立即返回portMAX_DELAY:无限期等待直到指令队列有空间其他值:等待指定节拍数
返回值
pdTRUE:指令成功发送到定时器指令队列pdFALSE:等待超时,指令未能发送到队列
底层通用函数 xTimerGenericCommand()
1 | BaseType_t xTimerGenericCommand( |
查询定时器周期
xTimerGetPeriod()
以系统节拍数(Ticks) 表示的周期值
xTimerIsTimerActive() - 查询运行状态
pdTRUE:定时器正在运行(已启动且在计时)pdFALSE:定时器处于休眠状态(未启动或已停止)
xTimerStart() / xTimerStartFromISR() - 启动定时器
注意启动时机,发送到队列里就开始执行了,而不是从定时器服务任务执行指令的时刻开始算
停止定时器
#define xTimerStop(xTimer, xTicksToWait) \ xTimerGenericCommand((xTimer), tmrCOMMAND_STOP, 0U, NULL, (xTicksToWait))
复位定时器
xTimerReset()
- 休眠状态:等效于
xTimerStart()(启动定时器) - 运行状态:重置计时起始点为当前时刻(重新开始计时)
具体示例
osTimeonce是单次 ostimerperiodic是周期

