七、FreeRTOS学习之 软件定时器

2023-05-16

一、基本概念

在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);   // 正常不会执行到这里 
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

七、FreeRTOS学习之 软件定时器 的相关文章

随机推荐