FreeRTOS软件定时器(1-18)

本文详细介绍了软件定时器的工作原理,比较了与硬件定时器的优缺点,探讨了FreeRTOS中的软件定时器实现,包括创建、启动、停止、复位和更改周期等操作,以及如何避免回调函数中的阻塞问题。
摘要由CSDN通过智能技术生成

软件定时器简介

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

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

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

软件定时器的优缺点

优点:

1:硬件定时器数量有限,软件定时器理论上只需要有足够的内存,就可以创建多个

2:使用简单,成本低

缺点:

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

 软件定时器的特点

1:可以裁剪,软件定时器是可裁剪可配置功能,如果要使用软件定时器,需要将configUSE_TIMERS 配置为 1。

2:单次和周期,软件定时器支持设置为:单次定时器周期或周期定时器

注:

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

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

软件定时器服务任务作用

1:可以裁剪,软件定时器是可裁剪可配置功能,如果要使用软件定时器,需要将configUSE_TIMERS 配置为 1。

2:单次和周期,软件定时器支持设置为:单次定时器周期或周期定时器

注:

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

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

软件定时器服务任务作用

1:负责软件定时器超时的逻辑判断

2:调用超时软件定时器的超时回调函数

3:处理软件定时器的命令队列

【软件定时器在开始创建的时候处于休眠状态,要通过命令队列唤醒工作】

软件定时器命令队列

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

【往软件定时器发送一个命令】

软件定时器相关配置

1:宏定义配置,当freeRTOS的配置项configUSE_TIMERS 设置为 1,在启动任务调度器时,会自动创建软件定时器的服务/守护任务preTimerTask();

2:软件定时器服务任务优先级configTIMER_TASK_PRIORITY = 31

3: 定时器的命令长度为configTIMER_QUEUE_LENGTH = 5;

注:

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

so:

1:定时器回调函数要尽快实行,不能进入阻塞状态,即不能调用那些会阻塞任务的API函数,如vTaskDelay();

2:访问队列或者信号量的非零阻塞时间的API函数也不能调用

软件定时器的状态

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

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

注:

1:新创建的软件定时器处于休眠的状态,是没有运行的

2:通过发送命令队列的方式可以让软件定时器从休眠的状态转换为运行的状态

单次定时器和周期定时器

FreeRTOS提供了两种软件定时器

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

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

软件定时器状态转换图

软件定时器结构体成员

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;

软件定时器API函数

函数描述
xTimerCreadte()动态方式创建软件定时器
xTimerCreateStatic()静态方式创建软件定时器
xTimerStart()开启软件定时器定时
xTimerStartFromISR()在中断中开启软件定时器定时
xTimerStop()停止软件定时器定时
xTimerStopFromISR()在中断中停止软件定时器定时
xTimerReaet()复位软件定时器定时
xTimerResetFromISR()在中断中复位软件定时器定时
xTimerChangePeriod()更改软件电视器定时超时时间
xTimerChangePeriodFromISR()在中断中更改定时超时时间

创建软件定时器

要使用定时器,需要先创建它,得到它的句柄。 有两种方法创建定时器:动态分配内存、静态分配内存。函数原型如下:

/*
  使用动态分配内存的方式创建软件定时器
  *	pcTimerName:定时器名字, 用处不大, 尽在调试时用到
  *	xTimerPeriodInTicks: 周期, 以Tick为单位
  *	uxAutoReload: 类型, pdTRUE表示自动加载, pdFALSE表示一次性
  *	pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
  *	pxCallbackFunction: 回调函数
  *	返回值: 成功则返回TimerHandle_t, 否则返回NULL
*/
TimerHandle_t xTimerCreate( const char * const pcTimerName,
                            const TickType_t xTimerPeriodInTicks,
                            const UBaseType_t uxAutoReload,
                            void * const pvTimerID,   
                            TimerCallbackFunction_t pxCallbackFunction  );

/*
静态创建软件定时器
*	pcTimerName:定时器名字, 用处不大, 尽在调试时用到
*	xTimerPeriodInTicks: 周期, 以Tick为单位
*	uxAutoReload: 类型, pdTRUE表示自动加载, pdFALSE表示一次性
*	pvTimerID: 回调函数可以使用此参数, 比如分辨是哪个定时器
*	pxCallbackFunction: 回调函数
*	pxTimerBuffer: 传入一个StaticTimer_t结构体, 将在上面构造定时器
*	返回值: 成功则返回TimerHandle_t, 否则返回NULL
*/
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
                                 TickType_t xTimerPeriodInTicks,
                                 UBaseType_t uxAutoReload,
                                 void * pvTimerID,
                                 TimerCallbackFunction_t                                                pxCallbackFunction,  StaticTimer_t                                      *pxTimerBuffer
  );

开启定时器的API函数

BaseType_t xTimerStart(TimerHandle_t    xTimer,
                       const TickType_t xTicksToWait
 );
 /*
    参数含义
    xTimer       待开启软件定时器句柄
    xTickToWait  发送命令到软件定时器命令队列的最大等待时间
    返回值
    PSPASS       软件定时器开启成功
    pdFALSE      软件定时器开启失败
 */

停止软件定时器的API函数

BaseType_t xTimerStop(TimerHandle_t xTimer,
                      const TickType_t xTickToWait
);
/*
   参数含义
   xTimer          待停止的软件定时器句柄
   xTickToWait     发送命令到软件定时器命令队列的最大等待时间
   返回值
   PdPASS          停止成功
   pdFALSE         停止失败
*/

复位软件定时器

该功能将使软件定时器的重新开启定时,复位后的软件定时器以复位时的时刻作为开启时刻重新定时,(按下复位键之后,重新开始从原来的时间继续计时)。

BaseType_t xTimerReset(TimerHandle_t    xTimer,
                       const TickType_t xTickToWait
);
/*
   参数含义
   xTimer        待复位的软件定时器句柄
   xTickToWait   发送命令到软件定时器命令队列的最大等待时间
   返回值
   PdPASS          软件定时器复位成功
   pdFALSE         软件定时器复位失败
*/

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

BaseType_t xTimerChangePeriod(TimerHandle_t     xTimer,
                              const TickType_t  xNewPeriod,
                              const TickType_t  xTicksToWait
);
/*
   定时器参数
   xTimer     待更新的软件定时器句柄
   xNewPeriod 新的定时器超时时间,单位:系统时钟节拍
   xTickToWait 发送命令到软件定时器命令队列的最大等待时间
   返回值
   PdPASS          软件定时器定时超时时间修改成功
   pdFALSE         软件定时器定时超时时间修改失败
*/

软件定时器项目实战

【参考自正点原子视频和伟东山老师文档】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值