一、简介
使能了软件定时器功能后,在调用函数 vTaskStartScheduler()开启任务调度器的时候,会创
建一个用于管理软件定时器的任务,这个任务就叫做软件定时器服务任务。软件定时器服务任
务,主要负责软件定时器超时的逻辑判断、调用超时软件定时器的超时回调函数以及处理软件
定时器命令队列。
二、软件定时器的状态
1. 休眠态
休眠态软件定时器可以通过其句柄被引用,但是因为没有运行,所以其定时超时回调函数不会被执行。
2. 运行态
处于运行态或在上次定时超时后再次定时超时的软件定时器,会执行其定时超时回调函数。
三、软件定时器的两种类型
1. 单次定时器
单次定时器的一旦定时超时,只会执行一次其软件定时器超时回调函数,超时后可以被手动重新开启,但单次定时器不会自动重新开启定时。
2. 周期定时器
周期定时器的一旦被开启,会在每次超时时,自动地重新启动定时器,从而周期地执行其
软件定时器回调函数。
四、单次定时器和周期定时器之间的差异
五、 FreeRTOS 软件定时器相关配置
用户可以根据需要配置 FreeRTOSConfig.h 文件中的configUSE_TIMERS,FreeRTOSConfig.h 文件中还有一些其他与软件定时器相关的配置项,FreeRTOSConfig.h 文件中软件定时器相关的配置项说明如下:
1. configUSE_TIMERS
此宏用于使能软件定时器功能,如果要使用软件定时器功能,则需要将该宏定义定义为 1。开启软件定时器功能后,系统会系统创建软件定时器服务任务。
2. configTIMER_TASK_PRIORITY
此宏用于配置软件定时器服务任务的任务优先级,当使能了软件定时器功能后,需要配置该宏定义,此宏定义可以配置为 0~(configMAX_PRIORITY-1)的任意值。
3. configTIMER_QUEUE_LENGTH
此宏用于配置软件定时器命令队列的队列长度,当使能了软件定时器功能后,需要配置该宏定义,若要正常使用软件定时器功能,此宏定义需定义成一个大于 0 的值。
4. configTIMER_TASK_STACK_DEPTH
此宏用于配置软件定时器服务任务的栈大小,当使能了软件定时器功能后,需要配置该宏定义,由于所有软件定时器的定时器超时回调函数都是由软件定时器服务任务调用的,因此这些软件定时器超时回调函数运行时使用的都是软件定时器服务任务的栈。
六、软件定时器实验
//创建一个单次定时器和一个周期定时器,打开两个定时器然后等待10s关闭定时器,此时会发现单次定时器打印1次停止,周期定时器打印5次停止
#include "FreeRTOS_demo.h"
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1( void * pvParameters );
void timer1_callback( TimerHandle_t pxTimer );
void timer2_callback( TimerHandle_t pxTimer );
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t ) start_task,
(char * ) "start_task",
(configSTACK_DEPTH_TYPE ) START_TASK_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t * ) &start_task_handler );
vTaskStartScheduler();
}
TimerHandle_t timer1_handle = 0; /* 单次定时器 */
TimerHandle_t timer2_handle = 0; /* 周期定时器 */
void start_task( void * pvParameters )
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 单次定时器 */
timer1_handle = xTimerCreate( "timer1",
500,
pdFALSE,
(void *)1,
timer1_callback );
/* 周期定时器 */
timer2_handle = xTimerCreate( "timer2",
2000,
pdTRUE,
(void *)2,
timer2_callback );
xTaskCreate((TaskFunction_t ) task1,
(char * ) "task1",
(configSTACK_DEPTH_TYPE ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(TaskHandle_t * ) &task1_handler );
vTaskDelete(NULL);
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/* 任务一,按键扫描并控制软件定时器 */
void task1( void * pvParameters )
{
uint8_t key = 0;
xTimerStart(timer1_handle,portMAX_DELAY);
xTimerStart(timer2_handle,portMAX_DELAY);
vTaskDelay(10000);
xTimerStop(timer1_handle,portMAX_DELAY);
xTimerStop(timer2_handle,portMAX_DELAY);
while(1)
{
}
}
/* timer1的超时回调函数 */
void timer1_callback( TimerHandle_t pxTimer )
{
static uint32_t timer = 0;
printf("timer1的运行次数:%d\r\n",++timer);
}
/* timer2的超时回调函数 */
void timer2_callback( TimerHandle_t pxTimer )
{
static uint32_t timer = 0;
printf("timer2的运行次数:%d\r\n",++timer);
}