FreeRTOS学习--56讲 软件定时器

发布时间:2023年12月28日

软件定时器:

? ? ? ? 用户可自定义定时器的周期,当指定时间到达后调用回调函数,用户在回调函数中处理信息

硬件定时器:
? ? ? ? 芯片自带的定时器模块,精度高,能触发中断,用户在中断服务函数中处理信息

软件定时器特点:

? ? ? ? a.在调用函数vTaskStartScheduler()开启任务调度器的时候,会创建一个用于管理软件定时器的任务,这个任务就叫做软件定时器服务任务。软件定时器服务任务,主要负责软件定时器超时的逻辑判断、调用超时软件定时器的超时回调函数以及处理软件定时器命令队列。且回调函数中不能有延时阻塞之类的函数vTaskDelay()vTaskDelayUntil()等

? ? ? ? b.软件定时器刚创建的时候属于休眠态,需要激活才能变为运行态,休眠态其回调函数不会被执行

使用软件定时器的条件:

? ? ? ? a.在FreeRTOSConfig.h中把configCSE_TIMERS置1

? ? ? ? b.configTIMER_TASK_PRIORITY设为31,就是把服务任务的优先级设为最高

? ? ? ? c.configTIMER_QUEUE_LENGTH设为5,把命令队列长度设为5,能接收多个命令

动态创建软件定时器????????xTimerCreate()
TimerHandle_t xTimerCreate(
?????????????????const char * const???????????????? pcTimerName,
?????????????????const TickType_t? ? ? ? ? ? ? ? ? ?xTimerPeriodInTicks,
?????????????????const UBaseType_t????????????? uxAutoReload,
?????????????????void * const? ? ? ? ? ? ? ? ? ? ? ? ? ?pvTimerID,
?????????????????TimerCallbackFunction_t? ? ? pxCallbackFunction);
?参数:
?软件定时器名,定时器超时时间(系统时钟节拍),定时器模式(pdTRUE 周期定时器,pdFALSE 单次定时器),软件定时器ID(用于多个软件定时器公用一个超时回调函数),软件定时器超时回调函数
?返回值:NULL 软件定时器创建失败,其他值 软件定时器创建成功,返回其句柄

开启软件定时器?? ??? ??? ?xTimerStart()
BaseType_t xTimerStart(TimerHandle_t? ? xTimer,const TickType_t? ? xTicksToWait)
参数:待开启软件定时器的句柄,发送命令到软件定时器命令队列的等待时间
返回值:pdPASS 开启成功,pdFAIL 开启失败

停止软件定时器?? ??? ??? ?xTimerStop()
BaseType_t xTimerStop(TimerHandle_t? ?xTimer,const TickType_t? ?xTicksToWait);
参数:待停止软件定时器的句柄,发送命令到软件定时器命令队列的等待时间
返回值:pdPASS 停止成功,pdFAIL 停止失败

复位软件定时器?? ??? ??? ?xTimerReset()
BaseType_t xTimerReset(TimerHandle_t xTimer,const TickType_t xTicksToWait);
参数:待复位软件定时器的句柄,发送命令到软件定时器命令队列的等待时间
返回值:pdPASS 复位成功,pdFAIL 复位失败

更改软件定时器的定时超时时间?? ??? ??? ?
BaseType_t xTimerChangePeriod(TimerHandle_t xTimer,const TickType_t xNewPeriod,const TickType_t xTicksToWait);
参数:待更改软件定时器的句柄,新的定时超时时间,发送命令到软件定时器命令队列的等待时间
返回值:pdPASS 复位成功,pdFAIL 复位失败

删除软件定时器?? ??? ?
BaseType_t xTimerDelete(TimerHandle_t xTimer,const TickType_t xTicksToWait);
参数:待删除软件定时器的句柄,发送命令到软件定时器命令队列的等待时间
返回值:pdPASS 删除成功,pdFAIL 删除失败

软件定时器实验

//freertos_demo.c

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
#include "./MALLOC/malloc.h"
/*FreeRTOS******************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"

/************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#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* pv);
 
 void time1_callback(TimerHandle_t pxTimer);     //申明单次定时器1
 void time2_callback(TimerHandle_t pxTimer);     //申明周期定时器2
/***************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    xTaskCreate((TaskFunction_t    )    start_task,         //创建开始任务
                (char*             )    "start_task", 
                (unsigned portSHORT)    START_TASK_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    START_TASK_PRIO, 
                (TaskHandle_t*     )    &start_task_handler );
    vTaskStartScheduler();
}

TimerHandle_t timer1_handle = 0;        //定义单次定时器
TimerHandle_t timer2_handle = 0;        //定义周期定时器
void start_task(void* pvPara)
{
    taskENTER_CRITICAL();         //进入临界区

    //创建单次定时器
     timer1_handle = xTimerCreate( "timer1", 1000,pdFALSE,(void*)1,time1_callback);//定时器名字,超时周期,单次定时器,ID,回调函数
                                    
    //创建周期定时器
     timer2_handle = xTimerCreate( "timer2", 1000,pdTRUE,(void*)2,time2_callback);//定时器名字,超时周期,周期定时器,ID,回调函数

    xTaskCreate((TaskFunction_t    )    task1,              //创建任务一
                (char*             )    "task1", 
                (unsigned portSHORT)    TASK1_STACK_SIZE, 
                (void *            )    NULL, 
                (portBASE_TYPE     )    TASK1_PRIO, 
                (TaskHandle_t*     )    &task1_handler );
                
                
    vTaskDelete(NULL);              //删除start_task任务
    taskEXIT_CRITICAL();            //退出临界区
}


//任务一 按键扫描并控制软件定时器
void task1(void* pv)
{
    uint8_t key = 0;
    while(1)
    {
        key = key_scan(0);
        if(key == KEY0_PRES)
        {
            xTimerStart(timer1_handle,portMAX_DELAY);    //开启定时器1
            xTimerStart(timer2_handle,portMAX_DELAY);    //开启定时器2
        }else if(key == KEY1_PRES)
        {
            xTimerStop(timer1_handle,portMAX_DELAY);   //暂停定时器1
            xTimerStop(timer2_handle,portMAX_DELAY);   //暂停定时器2
        }
        vTaskDelay(10);
    }
}

//time1的超时回调函数
void time1_callback(TimerHandle_t pxTimer)
{
    static uint32_t timer = 0;      //加静态是避免每次进入都初始化一遍
    printf("time1的允许次数:%d\r\n",++timer);
}

//time2的超时回调函数
void time2_callback(TimerHandle_t pxTimer)  //注意里面不能有延时阻塞函数
{
    static uint32_t timer = 0;      //加静态是避免每次进入都初始化一遍
    printf("time2的允许次数:%d\r\n",++timer);
}

文章来源:https://blog.csdn.net/weixin_60444711/article/details/135268828
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。