FreeRTOS 软件定时器

       软件定时器是指具有定时功能的软件,FreeRTOS 提供的软件定时器允许在创建前设置一个 软件定时器定时超时时间,在软件定时器成功创建并启动后,软件定时器开始定时,当软件定 时器的定时时间达到或超过先前设置好的软件定时器定时器超时时间时,软件定时器就处于超 时状态,此时软件定时器就会调用相应的回调函数,一般这个回调函数的处理的事务就是需要 周期处理的事务。
       FreeRTOS 提供的软件定时器还能够根据需要设置成单次定时器和周期定时器。当单次定时 器定时超时后,不会自动启动下一个周期的定时,而周期定时器在定时超时后,会自动地启动 下一个周期的定时。
       FreeRTOS 提供的软件定时器功能,属于 FreeRTOS 的中可裁剪可配置的功能,如果要使能 软件定时器功能,那需要在 FreeRTOSConfig.h 文件中将 configUSE_TIMERS 配置项配置成 1。
       要注意的是,软件定时器的超时回调函数是由软件定时器服务任务调用的,软件定定时器 的超时回调函数本身不是任务,因此不能在该回调函数中使用可能会导致任务阻塞的 API 函数, 例如 vTaskDelay()、vTaskDelayUntil()和一些会到时任务阻塞的等到事件函数,这些函数将会导 致软件定时器服务任务阻塞,这是不可以出现的。
软件定时器的状态
      软件定时器可以处于一下两种状态中一种: 
1. 休眠态 休眠态软件定时器可以通过其句柄被引用,但是因为没有运行,所以其定时超时回调函数 不会被执行。
2. 运行态 处于运行态或在上次定时超时后再次定时超时的软件定时器,会执行其定时超时回调函数。
单次定时器和周期定时器
      FreeRTOS 提供了两种软件定时器,如下:
1. 单次定时器 单次定时器的一旦定时超时,只会执行一次其软件定时器超时回调函数,超时后可以被手 动重新开启,但单次定时器不会自动重新开启定时。
2. 周期定时器 周期定时器的一旦被开启,会在每次超时时,自动地重新启动定时器,从而周期地执行其 软件定时器回调函数。
        单次定时器和周期定时器之间的差异如下图所示:

       上图展示了单次定时器和周期定时器之间的差异,图中的垂直虚线的间隔时间为一个单位 时间,可以理解为一个系统时钟节拍。其中 Timer1 为周期定时器,定时超时时间为 2 个单位时 间,Timer2 为单次定时器,定时超时时间为 1 个单位时间。可以看到,Timer1 在开启后,一直 以 2 个时间单位的时间间隔重复执行,为 Timer2 则在第一个超时后就不在执行了。

复位软件定时器

       除了开启和停止软件定时器的定时,还可以对软件定时器进行复位。复位软件定时器会使 软件定时器的重新开启定时,复位后的软件定时器以复位时的时刻作为开启时刻重新定时,软 件定时器的复位示意图如下图所示:

       上图展示了软件定时器的复位过程,图中在 t0 时刻创建并启动了一个超时时间为 5 个单位 时间的软件定时器,接着在 t3 时刻对软件定时器进行了复位,复位后软件定时器的超时时刻以 复位时刻为开启时刻重新计算,在 t7 时刻又再次对软件定时器进行了复位,最终计算出软件定 时器的超时时刻为最后一次复位的时刻(t7)加上软件定时器的超时时间(5 个单位时间),于 是该软件定时器在 t12 时刻超时,并执行其超时回调函数。

FreeRTOS 软件定时器相关配置

         前面说过软件定时器功能是可选的,用户可以根据需要配置 FreeRTOSConfig.h 文件中的 configUSE_TIMERS,同时 FreeRTOSConfig.h 文件中还有一些其他与软件定时器相关的配置项, 这部分在第三章《FreeRTOS 配置项》中都有讲解,但现在结合前面对软件定时器的了解再对这些配置项进行说明。FreeRTOSConfig.h 文件中软件定时器相关的配置项说明如下:
1. configUSE_TIMERS 此宏用于使能软件定时器功能,如果要使用软件定时器功能,则需要将该宏定义定义为 1。 开启软件定时器功能后,系统会系统创建软件定时器服务任务。
2. configTIMER_TASK_PRIORITY 此宏用于配置软件定时器服务任务的任务优先级,当使能了软件定时器功能后,需要配置 该宏定义,此宏定义可以配置为 0~(configMAX_PRIORITY-1)的任意值。
3. configTIMER_QUEUE_LENGTH 此宏用于配置软件定时器命令队列的队列长度,当使能了软件定时器功能后,需要配置该 宏定义,若要正常使用软件定时器功能,此宏定义需定义成一个大于 0 的值。
4. configTIMER_TASK_STACK_DEPTH 此宏用于配置软件定时器服务任务的栈大小,当使能了软件定时器功能后,需要配置该宏定义,由于所有软件定时器的定时器超时回调函数都是由软件定时器服务任务调用的,因此这 些软件定时器超时回调函数运行时使用的都是软件定时器服务任务的栈。
FreeRTOS 软件定时器相关 API 函数
      FreeRTOS 提供了软件定时器的一些相关操作函数,其中常用的软件定时器相关 API 函数, 如下表所示:
创建软件定时器
       FreeRTOS 提供了两种创建软件定时器的方式,分别为动态方式创建软件定时器和静态方 式创建软件定时器,两者的区别在于静态方式创建软件定时器时,需要用户提供创建软件定时 器所需的内存空间,而使用动态方式创建软件定时器时,FreeRTOS 会自动从 FreeRTOS 管理的 堆中分配创建软件定时器所需的内存空间。
       动态方式创建软件定时器 API 函数的函数原型如下所示:
       函数 xTimerCreate()的形参描述,如下表所示:

开启软件定时器定时

       FreeRTOS 提供了两个用于开启软件定时器定时的 API 函数,这个两个函数分别用于在任 务和在中断中开启软件定时器定时。 在任务中开启软件定时器定时 API 函数的函数原型如下所示:

      函数 xTimerStart()的形参描述,如下表所示:

停止软件定时器定时
        FreeRTOS 提供了两个用于停止软件定时器定时的 API 函数,这个两个函数分别用于在任 务和在中断中停止软件定时器定时。 在任务中停止软件定时器定时 API 函数的函数原型如下所示:
 
       函数 xTimerStop()的形参描述,如下表所示:

复位软件定时器定时       

       FreeRTOS 提供了两个用于复位软件定时器定时的 API 函数,这个两个函数分别用于在任 务和在中断中复位软件定时器定时。 在任务中复位软件定时器定时 API 函数的函数原型如下所示:

      函数 xTimerReset()的形参描述,如下表所示:

更改软件定时器的定时超时时间

        FreeRTOS 提供了两个分别用于任务和中断的更改软件定时器的定时超时时间的 API 函数。 在任务中更改软件定时器的定时超时时间 API 函数的函数原型如下所示:

       函数 xTimerChangePeriod()的形参描述,如下表所示:

删除软件定时器

       FreeRTOS 提供了用于删除软件定时器的 API 函数,函数原型如下所示:

      函数 xTimerDelete()的形参描述,如下表所示:

FreeRTOS 软件定时器操作实验

程序设计:设计两个任务,task1和task2,task1任务用于周期性定时器任务,task2任务用于单次定时器任务。同时task1任务累计执行10次之后即关闭定时器。
首先是FreeRTOSConfig.h文件的配置:
#define configUSE_TIMERS              1
#define configTIMER_TASK_PRIORITY     (3)
#define configTIMER_QUEUE_LENGTH      10
#define configTIMER_TASK_STACK_DEPTH  256

然后是定时器1和定时器2任务的定义:

这里特别注意关于ID号的定义和设置。

TimerHandle_t Timer1Timer_Handler;
TimerHandle_t Timer2Timer_Handler;

unsigned char timer1_id = 1;
unsigned char timer2_id[] = "ID02";

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();    
    
    Timer1Timer_Handler = xTimerCreate(
        (const char*)"Timer1",
        (TickType_t) 1000,
        (UBaseType_t)pdTRUE,
        (void *)     &timer1_id,
        (TimerCallbackFunction_t)Timer1Callback);
    
    Timer2Timer_Handler = xTimerCreate(
        (const char*)"Timer2",
        (TickType_t) 1000,
        (UBaseType_t)pdFALSE,
        (void *)     timer2_id,
        (TimerCallbackFunction_t)Timer2Callback);

    xTaskCreate((TaskFunction_t )task_1_task,            
              (const char*    )"task_1_task",          
              (uint16_t       )TASK_1_STK_SIZE,        
              (void*          )NULL,                  
              (UBaseType_t    )TASK_1_PRIO,       
              (TaskHandle_t*  )&Task_1_Task_Handler);
                                                    
    vTaskDelete(StartTask_Handler);    
                            
    taskEXIT_CRITICAL();
}

然后是定时器1和定时器2回调函数的定义:

这里也需要特别注意关于ID号的处理操作。

void Timer1Callback(TimerHandle_t xTimer)
{
    unsigned char *id;
    
    printf("定时器名称:%s.\r\n", pcTimerGetName(Timer1Timer_Handler));
    id = (unsigned char *)pvTimerGetTimerID(Timer1Timer_Handler);
    printf("定时器ID号:%d.\r\n", *id);
    
    timer1_run_counter++;
    printf("定时器运行次数:%d.\r\n", timer1_run_counter);
}

void Timer2Callback(TimerHandle_t xTimer)
{
    unsigned char *id;
    
    printf("定时器名称:%s.\r\n", pcTimerGetName(Timer2Timer_Handler));
    id = (unsigned char *)pvTimerGetTimerID(Timer2Timer_Handler);
    printf("定时器ID号:%s.\r\n", id);
    
    timer2_run_counter++;
    printf("定时器运行次数:%d.\r\n", timer2_run_counter);
}

最后是定时器1和定时器2开启和关闭逻辑函数:

void task_1_task(void *pvParameters)
{
     if(Timer1Timer_Handler != NULL)
     {
         printf("定时器1创建成功!\r\n");
         xTimerStart((TimerHandle_t)Timer1Timer_Handler, (TickType_t)portMAX_DELAY);
         printf("定时器1开启成功!\r\n");
     }
     
     if(Timer2Timer_Handler != NULL)
     {
         printf("定时器2创建成功!\r\n");
         xTimerStart((TimerHandle_t)Timer2Timer_Handler, (TickType_t)portMAX_DELAY);
         printf("定时器2开启成功!\r\n");
     }
     
     while(1)
     {    
          if(timer1_run_counter >= 10)
            {
                 xTimerStop((TimerHandle_t)Timer1Timer_Handler, (TickType_t)portMAX_DELAY);
                 printf("定时器1关闭成功!\r\n");
                 printf("任务删除");
                 vTaskDelete(Task_1_Task_Handler);
            }
          vTaskDelay(500);
     }
}

下载验证

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

moon2shine

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值