【FreeRTOS】11 软件定时器

定时器是MCU常用的外设,我们在学习各种单片机时必然会学习它的硬件定时器。但是,MCU自带的硬件定时器资源是有限的,而且一般会用在实时性要求很强的地方。

在freeRTOS中提供了软件定时器的功能,来实现更多的定时器资源。本节我们就来学习软件定时器。

1)freeRTOS的软件定时器介绍

freeRTOS的软件定时器,可以设置为单次执行、周期性执行;

定时时间到时,会执行回调函数(相当于硬件定时器的中断服务程序);

定时器的和回调函数中,不能调用会阻塞任务的函数,比如vTaskDelay()、vTaskDelayUntil()以及等待信号量、消息队列之类的函数,否则会引起定时器不正常。

使用软件定时器,需要在FreeRTOSConfig.h文件中,将configUSE_TIMERS宏定义为1。

freeRTOS的软件定时器,是通过一个系统内部使用的任务来实现的,就是prvTimerTask函数,这个任务在timers.c文件中定义,是系统自己生成的,用户可以不用管它。

此外,在FreeRTOSConfig.h文件中,还有一些需要注意的宏定义,见下图:

configTIMER_TASK_PRIORITY定义的是定时器任务的优先级,值可以是0~(configMAX_PRIORITIES-1),这个值定义的就是定时器任务prvTimerTask的优先级;

configTIMER_QUEUE_LENGTH定义的是定时器队列的长度,也就是能定义几个软件定时器;

configTIMER_TASK_STACK_DEPTH定义的是定时器任务的堆栈大小,图中定义的是256字,这个堆栈也是定时器回调函数会使用的堆栈,所以不能定义得太小。

2)常用的定时器操作函数

freeRTOS的定时器由TimerHandle_t类型定义。

创建定时器:

TimerHandle_t xTimerCreate(

const char * const pcTimerName, /* 定时器名,字符串 */

const TickType_t xTimerPeriod, /* 定时器周期,单位为系统时钟节拍 */

const UBaseType_t uxAutoReload, /* 单次执行或者周期性执行,pdTRUE周期,pdFALSE单次 */

void * const pvTimerID, /* 定时器ID,这个参数主要用于多个定时器共用一个回调函数时,在回调函数中获取ID来识别是哪个定时器调用的它 */

TimerCallbackFunction_t pxCallbackFunction /* 定时器回调函数 */ );

这个函数实际上是动态创建定时器,还可以使用xTimerCreateStatic来静态创建。

另外需要注意的一点是,定时器的回调函数,只能定义成如下形式:(*TimerCallbackFunction_t)( TimerHandle_t xTimer ); 即传入的参数有且只有一个,就是定时器的句柄;

启动定时器:

BaseType_t xTimerStart( TimerHandle_t xTimer,    /* 定时器句柄 */

TickType_t xBlockTime ); /* 成功启动定时器前的最大等待时间设置,单位是系统时钟节拍*/

这个函数只能在任务中调用,如果想在中断中启动定时器,需要使用xTimerStartFromISR()。

停止定时器:

BaseType_t xTimerStop( TimerHandle_t xTimer,  /*定时器句柄*/

TickType_t xTicksToWait );/*成功停止定时器前的最大等待时间,单位是系统时钟节拍*/

这个函数只能在任务中调用,如果想在中断中停止定时器,需要使用xTimerStopFromISR()。

获取定时器的ID值:

void *pvTimerGetTimerID( TimerHandle_t xTimer ); /*输入参数为定时器句柄,返回ID */

3)编程试验

通过cubemx生成工程文件后,在keil中,生成了三个任务:

注意一下这里的任务优先级,defaultTask的优先级osPriorityNormal会经过HAL库函数的变换,对应freeRTOS中的优先级3

我们先定义三个定时器的句柄:

在启动任务之前,创建三个定时器,并启动它们:

定时器01和02都设置为周期性工作,定时器01周期为1s,定时器02周期为2s;定时器03只运行1次;这里我们为了试验定时器的ID获取功能,让它们共用了一个回调函数TimerCallback

定时器回到函数TimerCallback实现如下,获取定时器的ID,并打印出来:

在defaultTask中,延时10s后停止三个定时器:

编译,下载到开发板运行,这个程序的输出结果如下:

可以看到,定时器01每1s运行一次,定时器02每2s运行一次,定时器03只在第3s运行了1次。试验结果与定时器设置的一致。

定时器一共运行了9s,这是因为defaultTask的优先级是3,而FreeRTOSConfig.h中定时器任务的优先级configTIMER_TASK_PRIORITY定义成了2,比defaultTask优先级低,所以在第10s时,先执行了定时器停止,定时器回调函数不会再被调用。

如果把configTIMER_TASK_PRIORITY宏定义改为4,比defaultTask的优先级高,那么第10s时定时器任务会先执行,defaultTask中停止定时器的操作会后执行;输出就会多出第10s的两次回调函数打印,测试结果如下:

可以看到一共打印了10s的信息。

好了,本节的内容就到这里了。

如果觉得有用可以关注作者微信号“小白白学电子”,在公众号可以找到代码和资料下载地址:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值