FreeRTOS 软件定时器

目录

定时器:

硬件定时器:

软件定时器:

软件定时器优缺点? 

FreeRTOS软件定时器特点 

软件定时器的命令队列

软件定时器的相关配置

软件定时器的状态

单次定时器和周期定时器

软件定时器结构体成员介绍

FreeRTOS软件定时器相关API函数

创建软件定时器API函数 

开启软件定时器API函数 

 停止软件定时器API函数

 复位软件定时器API函数

 更改软件定时器超时时间API函数

FreeRTOS软件定时器实验

 实验代码


软件定时器的简介

定时器:

        从指定的时刻开始,经过一个指定时间,然后触发一个超时事件,用户可自定义定时器的周期。

硬件定时器:

        芯片本身自带的定时器模块,硬件定时器的精度一般很高,每次在定时时间到达之后就会自动触发一个中断,用户在中断服务函数中处理信息。

软件定时器:

        是指具有定时功能的软件,可设置定时周期,当指定时间到达后要调用回调函数(也称超时函数),用户在回调函数中处理信息

软件定时器优缺点? 

优点:

  • 硬件定时器数量有限,而软件定时器理论上只需有足够内存,就可以创建多个;
  • 使用简单、成本低

缺点:

  • 软件定时器相对硬件定时器来说,精度没有那么高(因为它以系统时钟为基准,系统时钟中断优先级又是最低,容易被打断)。 对于需要高精度要求的场合,不建议使用软件定时器。

FreeRTOS软件定时器特点 

  • 可裁剪:软件定时器是可裁剪可配置的功能, 如果要使能软件定时器,需将configUSE_TIMERS  配置项配置成 1  
  • 单次和周期:软件定时器支持设置成:单次定时器或周期定时器

注意:软件定时器的超时回调函数是由软件定时器服务任务调用的,软件定时器的超时回调函数本身不是任务,因此不能在该回调函数中使用可能会导致任务阻塞的 API 函数。

软件定时器服务任务:在调用函数 vTaskStartScheduler()开启任务调度器的时候,会创建一个用于管理软件定时器的任务,这个任务就叫做软件定时器服务任务。

软件定时器服务任务作用

  1. 负责软件定时器超时的逻辑判断 
  2. 调用超时软件定时器的超时回调函数
  3. 处理软件定时器命令队列 

软件定时器的命令队列

        FreeRTOS 提供了许多软件定时器相关的 API 函数,这些 API 函数大多都是往定时器的队列中写入消息(发送命令),这个队列叫做软件定时器命令队列,是提供给 FreeRTOS 中的软件定时器使用的,用户是不能直接访问的。 

软件定时器的相关配置

  • 当FreeRTOS 的配置项 configUSE_TIMERS 设置为1,在启动任务调度器时,会自动创建软件定时器的服务/守护任务 prvTimerTask( )
  • 软件定时器服务任务的优先级为 configTIMER_TASK_PRIORITY  =  31;
  • 定时器的命令队列长度为 configTIMER_QUEUE_LENGTH  = 5

注意:软件定时器的超时回调函数是在软件定时器服务任务中被调用的,服务任务不是专为某个定时器服务的,它还要处理其他定时器。

所以,定时器的回调函数不要影响其他 “ 人 ” 

  1. 回调函数要尽快实行,不能进入阻塞状态,即不能调用那些会阻塞任务的 API 函数,如:vTaskDelay () 
  2. 访问队列或者信号量的非零阻塞时间的 API 函数也不能调用。 

软件定时器的状态

 软件定时器共有两种状态:

休眠态:软件定时器可以通过其句柄被引用,但因为没有运行,所以其定时超时回调函数不会被执行

运行态: 运行态的定时器,当指定时间到达之后,它的超时回调函数会被调用

注意:新创建的软件定时器处于休眠状态 ,也就是未运行的! 发送命令队列让软件定时器从休眠态转变为运行态 

单次定时器和周期定时器

 FreeRTOS 提供了两种软件定时器:

单次定时器:单次定时器的一旦定时超时,只会执行一次其软件定时器超时回调函数,不会自动重新开启定时,不过可以被手动重新开启。

周期定时器:周期定时器的一旦启动以后就会在执行完回调函数以后自动的重新启动 ,从而周期地执行其软件定时器回调函数。 

  • Timer1:周期定时器,定时超时时间为 2 个单位时间,开启后,一直以2个时间单位间隔重复执行;
  • Timer2:单次定时器,定时超时时间为 1 个单位时间,开启后,则在第一个超时后就不在执行了。 

单次定时器状态转换图:

周期定时器状态转换图: 

软件定时器结构体成员介绍

typedef    struct
    {
        const char * 			   pcTimerName		       /* 软件定时器名字 */
        ListItem_t 				   xTimerListItem		   /* 软件定时器列表项 */
        TickType_t 				   xTimerPeriodInTicks;    /* 软件定时器的周期 */     
        void * 					   pvTimerID			   /* 软件定时器的ID */
        TimerCallbackFunction_t	   pxCallbackFunction;     /* 软件定时器的回调函数 */

        #if ( configUSE_TRACE_FACILITY == 1 )
         UBaseType_t 				uxTimerNumber	/*  软件定时器的编号,调试用  */
        #endif
        uint8_t 					ucStatus;       /*  软件定时器的状态  */
    } xTIMER;

FreeRTOS软件定时器相关API函数

函数

描述

xTimerCreate()

动态方式创建软件定时器

xTimerCreateStatic()

静态方式创建软件定时器

xTimerStart()

开启软件定时器定时

xTimerStartFromISR()

在中断中开启软件定时器定时

xTimerStop()

停止软件定时器定时

xTimerStopFromISR()

在中断中停止软件定时器定时

xTimerReset()

复位软件定时器定时

xTimerResetFromISR()

在中断中复位软件定时器定时

xTimerChangePeriod()

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

xTimerChangePeriodFromISR()

在中断中更改定时超时时间

创建软件定时器API函数 

TimerHandle_t  xTimerCreate (const char * const       pcTimerName,				
                             const TickType_t         xTimerPeriodInTicks,				
	                         const UBaseType_t        uxAutoReload,				
                             void * const 	          pvTimerID,			
	                         TimerCallbackFunction_t  pxCallbackFunction ); 

形参

描述

pcTimerName

软件定时器名

xTimerPeriodInTicks

定时超时时间,单位:系统时钟节拍

uxAutoReload

定时器模式, pdTRUE:周期定时器, pdFALSE:单次定时器

pvTimerID

软件定时器 ID,用于多个软件定时器公用一个超时回调函数

pxCallbackFunction

软件定时器超时回调函数

返回值

描述

NULL

软件定时器创建失败

其他值

软件定时器创建成功,返回其句柄

开启软件定时器API函数 

BaseType_t  xTimerStart (TimerHandle_t     xTimer,
				         const TickType_t  xTicksToWait ); 

形参

描述

xTimer

待开启的软件定时器的句柄

xTickToWait

发送命令到软件定时器命令队列的最大等待时间

返回值

描述

pdPASS

软件定时器开启成功

pdFAIL

软件定时器开启失败

 停止软件定时器API函数

BaseType_t  xTimerStop( TimerHandle_t     xTimer,
				        const TickType_t  xTicksToWait);

形参

描述

xTimer

待停止的软件定时器的句柄

xTickToWait

发送命令到软件定时器命令队列的最大等待时间

返回值

描述

pdPASS

软件定时器停止成功

pdFAIL

软件定时器停止失败

 复位软件定时器API函数

BaseType_t  xTimerReset( TimerHandle_t 	    xTimer,
           				 const TickType_t 	xTicksToWait); 

        该功能将使软件定时器的重新开启定时,复位后的软件定时器以复位时的时刻作为开启时刻重新定时。

形参

描述

xTimer

待复位的软件定时器的句柄

xTickToWait

发送命令到软件定时器命令队列的最大等待时间

返回值

描述

pdPASS

软件定时器复位成功

pdFAIL

软件定时器复位失败

 更改软件定时器超时时间API函数

BaseType_t  xTimerChangePeriod( TimerHandle_t 		xTimer,
					            const TickType_t 	xNewPeriod,
                                const TickType_t 	xTicksToWait); 

形参

描述

xTimer

待更新的软件定时器的句柄

xNewPeriod

新的定时超时时间,单位:系统时钟节拍

xTickToWait

发送命令到软件定时器命令队列的最大等待时间

返回值

描述

pdPASS

软件定时器定时超时时间更改成功

pdFAIL

软件定时器定时超时时间更改失败

FreeRTOS软件定时器实验

实验目的:学习 FreeRTOS 的软件定时器相关 API 函数的使用 。

实验设计:将设计三个任务:start_task、task1、task2

三个任务的功能如下:

  • start_task:用来创建task1任务,并创建两个定时器(单次和周期)
  • task1:用于按键扫描,并对软件定时器进行开启、停止操作
  • task2:用于按键扫描,并对软件定时器进行开启、停止操作

 实验代码

void timer1_callback( TimerHandle_t pxTimer );
void timer2_callback( TimerHandle_t pxTimer );
TimerHandle_t timer1_handle = 0;    /* 单次定时器 */
TimerHandle_t timer2_handle = 0;    /* 周期定时器 */

void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();               /* 进入临界区 */
    
    /* 单次定时器 */
    timer1_handle = xTimerCreate( "timer1", 
                                    500,
                                    pdFALSE,
                                    (void *)1,
                                    timer1_callback );
                            
    /* 周期定时器 */
    timer2_handle = xTimerCreate( "timer2", 
                                    2000,
                                    pdTRUE,
                                    (void *)2,
                                    timer2_callback );
                                    
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK1_PRIO,
                (TaskHandle_t *         )   &task1_handler );
                                             
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();                /* 退出临界区 */
}

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

/* timer1的超时回调函数 */
void timer1_callback( TimerHandle_t pxTimer )
{
    static uint32_t timer = 0;
    printf("timer1的运行次数:%d\r\n",++timer);
}

/* timer2的超时回调函数 */
void timer2_callback( TimerHandle_t pxTimer )
{
    static uint32_t timer = 0;
    printf("timer2的运行次数:%d\r\n",++timer);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值