目的
软件定时器是一个非常常用且非常好用的功能,这篇文章将对FreeRTOS中相关内容做个介绍。
本文代码测试环境见前面的文章:《FreeRTOS入门(01):基础说明与使用演示》
基础说明
软件定时器和基本的硬件定时器有点像,功能比较单一,就是设定一个时间,经过该时间后执行某个回调函数。这个功能看似简单,但是实际开发中还是非常常用的。
使用软件定时器前需要在 FreeRTOSConfig.h
文件中进行下面设置:
/* Software timer definitions. */
// 设置为1来使用软件定时器
#define configUSE_TIMERS 1
// 设置软件定时器后台服务程序(其实就是个任务,在这个场景下下也被叫做守护进程)优先级
#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
// 设置软件定时器命令队列长度
#define configTIMER_QUEUE_LENGTH 4
// 设置软件定时器任务栈大小
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
软件定时器使用时需要注意的是和硬件定时器一样回调函数(中断函数)中执行的任务不要阻塞。
使用演示
#include "debug.h"
#include "FreeRTOS.h" // 引入头文件
#include "task.h" // 引入头文件
#include "timers.h" // 引入头文件
TimerHandle_t xTimer1; // 定时器句柄
TimerHandle_t xTimer2; // 定时器句柄
// 定时器回调函数
void timer1(TimerHandle_t xTimer) {
printf("%u timer 1: %s\r\n", xTaskGetTickCount(), pvTimerGetTimerID(xTimer));
}
// 定时器回调函数
void timer2(TimerHandle_t xTimer) {
printf("%u timer 2: %s\r\n", xTaskGetTickCount(), pvTimerGetTimerID(xTimer));
}
int main(void) {
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
xTimer1 = xTimerCreate("timer1", 500, pdTRUE, "t1", timer1); // 创建并设置定时器周期执行
xTimer2 = xTimerCreate("timer2", 1000, pdFALSE, "t2", timer2); // 创建并设置定时器单次执行
xTimerStart(xTimer1, 0); // 启动定时器
xTimerStart(xTimer2, 0); // 启动定时器
vTaskStartScheduler(); // 任务调度,任务将在这里根据情况开始运行,程序将在这里无序循环
while(1) {} // 程序不会运行到这里
}
相关函数
// 创建软件定时器
// pcTimerName 分配给定时器的可读文本名称
// xTimerPeriod 定时周期,以tick为单位
// uxAutoReload 如果该值为pdTRUE,则定时器会重复执行;如果为pdFALSE,则执行一次后休眠
// pvTimerID 回调函数可以使用此参数, 比如分辨是哪个定时器或者使用set/get函数来保存使用一个值
// pxCallbackFunction 定时时间到之后执行的回调函数,函数原型如下
// typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer )
TimerHandle_t xTimerCreate( const char * const pcTimerName,
const TickType_t xTimerPeriod,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction );
// 删除软件定时器
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xBlockTime );
// 启动软件定时器
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xBlockTime );
BaseType_t xTimerStartFromISR ( TimerHandle_t xTimer, BaseType_t *pxHigherPriorityTaskWoken );
// 停止软件定时器
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xBlockTime );
BaseType_t xTimerStopFromISR ( TimerHandle_t xTimer, BaseType_t *pxHigherPriorityTaskWoken );
// 重置软件定时器
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xBlockTime );
BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, BaseType_t *pxHigherPriorityTaskWoken );
// 查询软件定时器是否处于活动状态
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer );
// 获取定时器周期
TickType_t xTimerGetPeriod( TimerHandle_t xTimer );
// 改变软件定时器周期
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, TickType_t xNewPeriod, TickType_t xBlockTime );
BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, TickType_t xNewPeriod, BaseType_t *pxHigherPriorityTaskWoken );
// 设置与返回定时器是否自动重置
void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload );
BaseType_t xTimerGetReloadMode( TimerHandle_t xTimer );
// 获取与修改ID
void *pvTimerGetTimerID( TimerHandle_t xTimer );
void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID );
// 获取定时器可读文本名称
const char * pcTimerGetName( TimerHandle_t xTimer );
// 返回定时器下一次触发时间
TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer );
// 获得软件定时器守护进程句柄
TaskHandle_t xTimerGetTimerDaemonTaskHandle( void );
总结
软件定时器使用比较简单,但非常好用,虽然没有硬件的基本定时器来的精确,但是一般使用是足够了,还可以创建非常多个(毕竟只受内存限制)。