FreeRTOS学习六(软件定时器)

        软件定时器允许设置一段时间,当设置的时间到达之后就执行指定的功能函数,被定时器调用的这个功能函数叫做定时器的回调函数。回调函数的两次执行间隔叫做定时器的定时周期,简而言之,当定时器的定时周期到了以后就会执行回调函数。

        软件定时器的回调函数是在定时器服务任务中执行的,所以一定不能在回调函数中调用任何会阻塞任务的API函数。比如,定时器回调函数中不能调佣vTaskDelay()、vTaskDelayUnti(),还有一些访问队列或者信号量的非零阻塞时间的API函数。

        软件定时器时一个可选项,不属于FreeRTOS内核的功能,它是由定时器服务(或Daemon)任务来提供的。FreeRTOS中所使用的定时器相关API函数,大部分是使用FreeRTOS的队列发送命令给定时器服务任务的。这个队列叫做定时器命令队列。定时器命令队列是提供给FreeRTOS的软件定时器使用的,用户不能直接使用

        软件定时器的相关宏定义配置在FreeRTOSConfig.h文件中。

#define configUSE_TIMERS                1 //软件定时器开启

#define configTIMER_TASK_PRIORITY       ( configMAX_PRIORITIES - 1 ) //优先级

#define configTIMER_QUEUE_LENGTH        10 //定时器命令队列长度

#define configTIMER_TASK_STACK_DEPTH    ( configMINIMAL_STACK_SIZE * 2 ) //定时器服务任务的任务堆栈大小。

        软件定时器分为两种:单次定时器周期定时器,单次定时器的话定时器回调函数就执行一次,然后定时器就会停止。单次定时器可以再次手动重新启动,但是不能自动重启。周期定时器一旦启动后,当定时器超时执行完回调函数以后会自动重新启动,这样回调函数就会周期性的执行。

        有时候需要在定时器运行的时候重新复位软件定时器,复位软件定时器的话会清零计数,并且重新计算定时周期到达的时间点。

1.xTimerCreate() 创建软件定时器(动态内存)

此函数用于创建一个软件定时器,所需要的内存通过动态内存管理方法分配。新创建的软件定时器处于休眠状态,也就是未运行的状态。

函数原型:

TimerHandle_t xTimerCreate( const char * const pcTimerName, const TickType_t xTimerPeriodInTicks,

const UBaseType_t uxAutoReload,

void * const pvTimerID,

TimerCallbackFunction_t pxCallbackFunction )

参数:

pcTimerName:软件定时器名字,名字是一串字符串,用于调试使用

xTimerPeriodInTicks:软件定时器的定时器周期,单位是时钟节拍数,可以通过设置(周期ms/portTICK_PERIOD_MS)转换为需要的时间周期,单位ms。

uxAutoReload:设置定时器模式。pdTRUE 为周期定时器,pdFALSE 为单次定时器。

pvTimerID:定时器ID号,一般情况下每个定时器都有一个回调函数,FreeRTOS支持多个定时器共用一个回调函数,在回调函数中根据定时器ID号来处理不同的定时器。

pxCallbackFunction:定时器回调函数。

返回值:

NULL:创建失败

其他值:创建成功,返回定时器句柄。

实例:

TimerHandle_t xTimer_test;

xTimer_test = xTimerCreate("Test timer",       /* Just a text name, not used by the kernel. */

                (1 * 50 / portTICK_PERIOD_MS),    /* The timer period in ticks. */

                pdFALSE,        /* The timers will auto-reload themselves when they expire. */

                 NULL,   /* Assign each timer a unique id equal to its array index. */

                 test_timer_callback /* Each timer calls the same callback when it expires. */

                                    );

2.xTimerCreateStatic()创建软件定时器(静态内存)

此函数用于创建一个软件定时器,所需要的内存需要用户自行分配。新创建的软件定时器处于休眠状态。

函数原型:

TimerHandle_t xTimerCreateStatic( const char * const pcTimerName,

const TickType_t xTimerPeriodInTicks,

const UBaseType_t uxAutoReload,

void * const pvTimerID,

TimerCallbackFunction_t pxCallbackFunction,

StaticTimer_t *pxTimerBuffer )

参数:

pcTimerName:软件定时器名字,名字是一串字符串,用于调试使用

xTimerPeriodInTicks:软件定时器的定时器周期,单位是时钟节拍数,可以通过设置(周期ms/portTICK_PERIOD_MS)转换为需要的时间周期,单位ms。

uxAutoReload:设置定时器模式。pdTRUE 为周期定时器,pdFALSE 为单次定时器。

pvTimerID:定时器ID号,一般情况下每个定时器都有一个回调函数,FreeRTOS支持多个定时器共用一个回调函数,在回调函数中根据定时器ID号来处理不同的定时器

pxCallbackFunction:定时器回调函数。

pxTimerBuffer :指向一个StaticTimer_t类型的变量,用来保存定时器结构体。

返回值:

NULL:创建失败

其他值:创建成功,返回定时器句柄。

实例:

static StaticTimer_t xTimerBuffer;
TimerHandle_t xTimer ;

xTimer = xTimerCreateStatic( "T1",             // Text name for the task.  Helps debugging only.  Not used by FreeRTOS.
                                   xTimerPeriod,     // The period of the timer in ticks.
                                  pdTRUE,           // This is an auto-reload timer.
                                  ( void * ) &uxVariableToIncrement,    // A variable incremented by the software timer's callback function
                                  prvTimerCallback, // The function to execute when the timer expires.
                                  &xTimerBuffer );  // The buffer that will hold the software timer structure.

3.xTimerStart() 启动软件定时器

        启动软件定时器。软件定时器在创建好之后会处于等待状态,调用该函数之后会将定时器转为运行状态。如果软件定时器正在运行的话,调用函数xTimerStart()的结果和xTimerReset()是一样的。

函数原型:

#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )

参数:

xTimer:要开启的软件定时器的句柄

xTicksToWait :设置阻塞时间,调用该函数开启软件定时器其实就是向定时器命令队列发送一条tmrCOMMAND_START命令,既然是向队列发送消息,那肯定会涉及到入队阻塞时间的设置。

返回值:

pdPASS:启动成功

pdFALL:启动失败。

实例:

if( xTimerStart( xTimers[ x ], 0 ) != pdPASS )
 {
 // The timer could not be set into the Active state.
}

4.xTimerStartFromISR()在中断中启动软件定时器

函数原型:

#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )

参数:

xTimer:要开启的软件定时器的句柄

pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换。当设置为pdTRUE时,退出中断服务函数之前一定会进行一次任务切换。

返回值:

pdPASS:启动成功

pdFALL:启动失败。

实例:

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS )
{
        // The start command was not executed successfully.  Take appropriate
        // action here.
}

5.xTimerStop()停止软件定时器

        此函数用于停止一个软件定时器,此函数用于任务中。

函数原型:

#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )

参数:

xTimer:要停止的软件定时器的句柄

xTicksToWait :设置阻塞时间,调用该函数停止软件定时器其实就是向定时器命令队列发送一条tmrCOMMAND_STOP命令既然是向队列发送消息,那肯定会涉及到入队阻塞时间的设置。

返回值:

pdPASS:停止成功

pdFALL:停止失败。

实例:

 xTimerStop( pxTimer, 0 );

6.xTimerStopFromISR()中断中停止软件定时器

函数原型:

#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U )

参数:

xTimer:要停止的软件定时器的句柄

pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换。当设置为pdTRUE时,退出中断服务函数之前一定会进行一次任务切换。

返回值:

pdPASS:停止成功

pdFALL:停止失败。

实例:

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS )
{
     // The stop command was not executed successfully.  Take appropriate
     // action here.
}

7.xTimerReset() 复位软件定时器

复位一个软件定时器,此函数只能用于任务中,不能用于中断中。

函数原型:

#define xTimerReset( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )

参数:

xTimer:要复位的软件定时器的句柄

xTicksToWait :设置阻塞时间,调用该函数停止软件定时器其实就是向定时器命令队列发送一条tmrCOMMAND_RESET命令既然是向队列发送消息,那肯定会涉及到入队阻塞时间的设置。

返回值:

pdPASS:复位成功

pdFALL:复位失败。

实例:

if( xTimerReset( xBacklightTimer, 100 ) != pdPASS )

{
   // The reset command was not executed successfully.  Take appropriate
   // action here.
}

8.xTimerResetFromISR()中断中复位软件定时器

函数原型:

#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U )

参数:

xTimer:要复位的软件定时器的句柄

pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换。当设置为pdTRUE时,退出中断服务函数之前一定会进行一次任务切换。

返回值:

pdPASS:复位成功

pdFALL:复位失败。

实例:

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS )
{
   // The reset command was not executed successfully.  Take appropriate
   // action here.
}

代码验证:

创建一个任务,在任务中开启一个1秒周期的定时器,定时器定时打印。

static TimerHandle_t xTimer_test;

static const uint32_t timer_id = 2;

任务1

static void vTestTask1_H(void *pvParameters)
{
xTimer_test = xTimerCreate("Test timer",       /* Just a text name, not used by the kernel. */
                                     (1000 / portTICK_PERIOD_MS),    /* The timer period in ticks. */
                                     pdTRUE,        /* The timers will auto-reload themselves when they expire. */
                                     (void *)timer_id,   /* Assign each timer a unique id equal to its array index. */
                                     vTimerCallback /* Each timer calls the same callback when it expires. */
                                    );

    if(xTimer_test == NULL)   
    {
        LOG_I(common,"[TASK1]:Timer create fail");  //失败
    }
    else
    {
        LOG_I(common,"[TASK1]:Timer create sucess");  //成功
        if( xTimerStart( xTimer_test, 0 ) != pdPASS )
        {
          LOG_I(common,"[TASK1]:Timer start fail");  //失败
        }
}
vTaskDelete(NULL);
}

定时器回调函数:

void vTimerCallback( TimerHandle_t pxTimer )
{
    configASSERT( pxTimer );
    static uint32_t time_cnt = 0;
    time_cnt++;
    int32_t lArrayIndex = 0;
    lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer );
    LOG_I(common,"[DEBUG]:timer name:%stimer id:%d",pcTimerGetName(pxTimer),lArrayIndex);
    if(lArrayIndex = timer_id)
    {
        LOG_I(common,"[DEBUG]:time cnt:%d",time_cnt);
    }
}

结果:

         在创建定时器的时候,设置了timer_id为2。在回调函数中,通过pvTimerGetTimerID()函数来获取timer_id通过pcTimerGetName()函数来获取定时器名字并打印出来。结果可以看到都是相互对应的。并且定时器时个周期定时器,间隔1秒钟会打印一次。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值