FreeRTOS学习笔记(十)软件定时器


前言

  FreeRTOS 软件定时器是一种方便的工具,适用于对时间精度要求不高的延时任务或周期性任务。通过软件定时器,任务可以在不占用大量资源的情况下实现定时功能,而不需要手动管理硬件定时器或复杂的中断逻辑。


一、软件定时器

1.1 软件定时器的引入

  提到MCU的开发,我们就绕不过一个老朋友——定时器,有的 MCU 其定时器功能异常强大,通过定时器我们可以完成需要周期性处理的事务。但是硬件资源终究还是有限的,对此我们也可以使用FreeRTOS提供的定时器功能,不过是软件定时器,软件定时器的精度肯定没有硬件定时器那么高,但是对于普通的精度要求不高的周期性处理的任务来说够了。
  FreeRTOS 的软件定时器(Software Timers)是一种灵活的机制,允许任务以延时的方式执行特定功能,且无需占用大量系统资源。软件定时器不像硬件定时器那样直接依赖于物理计时硬件,而是通过 FreeRTOS 的时钟滴答(tick count)来驱动,从而为任务提供定时回调功能。

1.2 定时器服务

  定时器是一个可选的、不属于 FreeRTOS 内核的功能,它是由定时器服务(也叫Daemon)任务来提供的。FreeRTOS 提供了很多定时器有关的 API 函数,这些 API 函数大多都使用 FreeRTOS的队列发送命令给定时器服务任务。这个队列叫做定时器命令队列,它是提供给FreeRTOS 的软件定时器使用的,用户不能直接访问。
在这里插入图片描述
  左侧部分属于用户应用程序的一部分,并且会在某个用户创建的用户任务中调用。图中右侧部分是定时器服务任务的任务函数,定时器命令队列将用户应用任务和定时器服务任务连接在一起。在这个例子中,应用程序调用了函数 xTimerReset(),结果就是复位命令会被发送到定时器命令队列中,定时器服务任务会处理这个命令。应用程序是通过函数 xTimerReset()间接的向定时器命令队列发送了复位命令,并不是直接调用类似 xQueueSend()这样的队列操作函数发送的。

1.3 运行机制

  由于所有定时器事件都是通过定时器服务任务来调度和处理的,所以当我们使用 FreeRTOS 的软件定时器 API(如 xTimerCreate()、xTimerStart() 等)时,你无需自行管理定时器中断或滴答定时器。简单机制如下:

  1. 创建定时器:使用 API 创建定时器后,定时器不会立即运行,而是注册到定时器服务任务中。
  2. 定时器服务任务调度:FreeRTOS 中有一个特殊的定时器服务任务,负责监控所有注册的定时器。
  3. 触发时执行回调函数:当定时器达到指定的超时时间后,定时器服务任务就会调用你为定时器定义的回调函数。
    注:超时回调函数是在Daemon中作用的,要尽快处理不要使用延时操作,以便于不影响其他的软件定时器。

二、软件定时器的实现

2.1 相关配置

  configUSE_TIMERS
  如果要使用软件定时器的话宏 configUSE_TIMERS 一定要设置为 1,当设置为 1 的话定时器服务任务就会在启动 FreeRTOS 调度器的时候自动创建。
  configTIMER_TASK_PRIORITY
  设置软件定时器服务任务的任务优先级(0 ~ configMAX_PRIORITIES-1)。优先级一定要根据实际的应用要求来设置。如果定时器服务任务的优先级设置的高的话,定时器命令队列中的命令和定时器回调函数就会及时的得到处理。
configTIMER_QUEUE_LENGTH
  此宏用来设置定时器命令队列的队列长度。
configTIMER_TASK_STACK_DEPTH
  此宏用来设置定时器服务任务的任务堆栈大小,单位为字(16 bit)。对于 STM32 来说一个字是 4 字节。由于定时器服务任务中会执行定时器的回调函数,因此任务堆栈的大小一定要根据定时器的回调函数来设置。

2.2 相关API

2.2.1 创建软件定时器

  这里我们常用xTiemrCreate(),此函数用于创建一个软件定时器,所需要的内存通过动态内存管理方法分配。新创建的软件定时器处于休眠状态 ,可以利用其他函数使其进入活动状态,此函数的原型如下:

TimerHandle_t xTimerCreate( const char * const pcTimerName,
 			TickType_t xTimerPeriodInTicks, UBaseType_t uxAutoReload,
 			void * pvTimerID, TimerCallbackFunction_t pxCallbackFunction )
  • 参数:
    • pcTimerName: 软件定时器名字,名字是一串字符串,用于调试使用。
    • xTimerPeriodInTicks : 软件定时器的定时器周期, 单位是时钟节拍数。
      注:可以借助portTICK_PERIOD_MS 将 ms 单位转换为时钟节拍数。举个例子,定时器的周期为 100 个时钟节拍的话,那么 xTimerPeriodInTicks 就为100,当定时器周期为 500ms 的时候 xTimerPeriodInTicks 就可以设置为(500/ portTICK_PERIOD_MS)。
    • uxAutoReload: 设置定时器模式
      • pdTRUE:周期定时器;
      • pdFALSE: 单次定时器
    • pvTimerID: 定时器 ID 号,回调函数会根据ID 号来处理不同的定时器
    • pxCallbackFunction: 定时器回调函数,当定时器定时周期到了以后就会调用这个函数
  • 返回值:
    • 成功:创建成功的软件定时器句柄
    • 失败:NULL

2.2.2 复位软件定时器

  有时候我们可能会在定时器正在运行的时候需要复位软件定时器,复位软件定时器的话重新计算定时周期到达的时间点,这个新的时间点是相对于复位定时器的那个时刻计算的,并不是第一次启动软件定时器的那个时间点。
xTimerReset( )
  复位一个软件定时器,此函数只能用在任务中,调用函数xTimerReset( )恢复软件定时器其实就是向定时器命令队列发送一条 tmrCOMMAND_START 命令,既然是向队列发送消息,那肯定会涉及到入队阻塞时间的设置。,函数原型如下:

BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait )
  • 参数:
    • xTimer: 要复位的软件定时器的句柄。
    • xTicksToWait: 设置阻塞时间
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFAIL

xTimerResetFromISR( )
 * *此函数是 xTimerReset()的中断版本,此函数用于中断服务函数中!

BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, BaseType_t *
	 			pxHigherPriorityTaskWoken );
  • 参数:
    • xTimer: 要开启的软件定时器的句柄
    • pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFAIL

2.2.3 开启软件定时器

  如果软件定时器停止运行的话可以使用 FreeRTOS 提供的两个开启函数来重新启动软件定时器。
xTimerStart( )
 启动软件定时器,函数 xTimerStartFromISR()是这个函数的中断版本,可以用在中断服务函数中。如果软件定时器没有运行的话调用函数 xTimerStart()就会计算定时器到期时间,如果软件定时器正在运行的话调用函数 xTimerStart()的结果和 xTimerReset()一样。

BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait )
  • 参数:
    • xTimer: 要开启的软件定时器的句柄
    • xTicksToWait: 设置阻塞时间
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFAIL

xTimerStartFromISR( )
  此函数是函数 xTimerStart()的中断版本,用在中断服务函数中,此函数是一个宏,此函数原型如下:

BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,
	BaseType_t * pxHigherPriorityTaskWoken );
  • 参数:
    • xTimer: 要开启的软件定时器的句柄
    • pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFAIL

2.2.4停止软件定时器

  既然有开启软件定时器的 API 函数,那么肯定也有停止软件定时器的函数,FreeRTOS 也提供了两个用于停止软件定时器的 API 函数。
xTimerStop( )
  此函数用于停止一个软件定时器,此函数用于任务中,不能用在中断服务函数中,函数原型如下:

BaseType_t xTimerStop ( TimerHandle_t xTimer, TickType_t xTicksToWait )
  • 参数:
    • xTimer: 要停止的软件定时器的句柄
    • xTicksToWait: 设置阻塞时间
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFAIL

xTimerStopFromISR( )
  此函数是 xTimerStop()的中断版本,此函数用于中断服务函数中。

BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,BaseType_t * 
		pxHigherPriorityTaskWoken );
  • 参数:
    • xTimer: 要开启的软件定时器的句柄
    • pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换
  • 返回值:
    • 成功:pdPASS
    • 失败:pdFAIL

免责声明:本文参考了网上公开资料,仅用于学习交流,若有错误或侵权请联系笔者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值