一、基本概念
在freertos中,软件定时器的功能跟单片机中使用的定时器差不多,通过设置一段时间,等到时间到达,定时器进入中断,执行相应的功能函数,被调用的函数叫做定时器的回调函数,它可以是一次性的,执行一次回调函数后,定时器会停止运行,要再次使用需要手动重启,不会自动重启;也可以是周期性的,其中两次执行回调函数的时间叫做定时周期。因此回调函数中不能调用会阻塞的API函数。
二、API 函数
注意:要使用软件定时器需要在FreeRTOSConfig.h中使能
#define configUSE_TIMERS 1 //使能软件定时器
#define configTIMER_TASK_PRIORITY 2 // 软件定时器的优先级
#define configTIMER_QUEUE_LENGTH 10 // 软件定时器的队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) // 软件定时器的堆栈空间大小(单位是字)
1、定时器创建
动态创建
TimerHandle_t xTimerCreate(
const char * const pcTimerName,//定时器名字
const TickType_t xTimerPeriodInTicks,
/* 计时器周期以tick周期的倍数指定。可以使用pdMS_TO_TICKS()宏
将以毫秒为单位的时间转换为以节拍为单位的时间。例如,如果计时
器必须在100个滴答之后过期,那么可以直接将xNewPeriod设置为100。
或者,如果计时器必须在500ms后过期,则可以将xNewPeriod设置
为pdMS_TO_TICKS(500),前提是configTICK_RATE_HZ小于或等于1000。
*/
const UBaseType_t uxAutoReload,
/* 设置为pdTRUE可以创建一个自动重新加载计时器。
设置为pdFALSE可以创建一个一次性计时器。
*/
void * const pvTimerID,
/* 分配给正在创建的计时器的标识符。可以使用vTimerSetTimerlD()
API函数更新标识符。如果同一个回调函数被分配给多个计时器,那么可以
在回调函数内部检查计时器标识符,以确定哪个计时器实际上已经过期。
此外,计时器标识符可以用于在调用计时器的回调函数之间存储一个值。
*/
TimerCallbackFunction_t pxCallbackFunction
/* 当计时器过期时调用的函数。回调函数必须具有TimerCallbackFunction_t
类型定义的原型。
原型:void vCallbackFunctionExample(TimerHandle_t xTimer );
*/
)
/*返回值:返回NULL,软件定时器无法创建,没有足够的FreeRTOS堆内存来分配定时器数据结构。
返回创建的软件计时器的句柄,软件计时器创建成功。
*/
静态创建
TimerHandle_t xTimerCreateStatic(
const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t *pxTimerBuffer
)
/*与动态创建的区别:静态创建要事先创建指向StaticTimer_t类型的指针变量,该变量用于保存计时器的状态。
返回值:成功返回句柄, 否则返回NULL
*/
2、启动
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
/*
参数:xTimer: 要启动的定时器句柄
xTicksToWait:如果定时器命令队列已满,设置的阻塞时间。
返回值:返回pdPASS,启动命令成功发送到定时器命令队列。
返回pdFAIL,启动命令向定时器命令队列发送启动命令失败,定时器命令队列已满。
*/
// 中断版本
BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken );
3、停止
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );
// 中断版本
BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken );
/*
xTimer: 定时器句柄
pxHigherPriorityTaskWoken: xTimerStopFromISR()向计时器命令队列写入一条命令。
如果写入定时器命令队列导致定时
器服务任务离开阻塞状态,并且定
时器服务任务的优先级等于或大于
当前正在执行的任务(被中断的任务),
那么xTimerStopFromISR()函数内部
将*pxHigherPriorityTaskWoken
设置为pdTRUE。
返回值: pdFAIL表示"停止命令"无法写入队列
pdPASS表示成功
*/
4、删除
BaseType_t xTimerDelete(
TimerHandle_t xTimer,// 定时器句柄
TickType_t xTicksToWait //超时时间
)
//返回值:返回pdPASS:成功发送delete命令到定时器命令队列。
// 返回pdFAIL:定时器命令队列发送delete命令失败,因为定时器命令队列已满。
5、复位
/*
如果计时器在此期间没有被停止、删除或重置,那么在调用xTimerReset()之后,与计时器关联的回调函数将被
调用'n' ticks,其中'n'是计时器定义的周期。
如果在启动调度器之前调用xTimerReset(),则计时器在启动 调度器之前不会开始运行,计时器的过期时间将
相对于启动调度器的时间
*/
BaseType_t xTimerReset(
TimerHandle_t xTimer, //定时器句柄
TickType_t xTicksToWait //超时时间
);
//返回值:返回pdPASS ,命令成功发送到timer命令队列。
// 返回pdFAIL,由于队列已满,没命令发送到timer命令队列。
三、运用
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "timers.h"
TimerHandle_t xBacklightTimer = NULL;
void vBacklightTimerCallback( TimerHandle_t pxTimer )
{
vSetBacklightState( BACKLIGHT_OFF );
}
void vKeyPressEventHandler( char cKey )
{
vSetBacklightState( BACKLIGHT_ON );
if( xTimerReset( xBacklightTimer, 10 ) != pdPASS )
{
printf("reset command was not executed successfully");
}
}
int main( void )
{
xBacklightTimer = xTimerCreate( "BcklghtTmr" ,//名字
pdMS_TO_TICKS( 5000 ),//计时器周期(单位为ticks)。
pdFALSE, //一次
0, //ID
vBacklightTimerCallback //回调函数
);
if( xBacklightTimer == NULL )
{
printf("The timer was not created")
}
if( xTimerStart( xBacklightTimer, 0 ) != pdPASS )
{
printf("The timer could not be set into the Active state")
}
vTaskStartScheduler(); // 启动任务,开启调度
while(1); // 正常不会执行到这里
}
版权声明:本文为m0_72750024原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。