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

文章目录

  • 前言
  • 一、软件定时器
    • [1.1 软件定时器的引入](#1.1 软件定时器的引入)
    • [1.2 定时器服务](#1.2 定时器服务)
    • [1.3 运行机制](#1.3 运行机制)
  • 二、软件定时器的实现
    • [2.1 相关配置](#2.1 相关配置)
    • [2.2 相关API](#2.2 相关API)
      • [2.2.1 创建软件定时器](#2.2.1 创建软件定时器)
      • [2.2.2 复位软件定时器](#2.2.2 复位软件定时器)
      • [2.2.3 开启软件定时器](#2.2.3 开启软件定时器)
      • 2.2.4停止软件定时器

前言

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(),此函数用于创建一个软件定时器,所需要的内存通过动态内存管理方法分配。新创建的软件定时器处于休眠状态 ,可以利用其他函数使其进入活动状态,此函数的原型如下:

c 复制代码
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 命令,既然是向队列发送消息,那肯定会涉及到入队阻塞时间的设置。,函数原型如下:

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

xTimerResetFromISR( )

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

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

2.2.3 开启软件定时器

如果软件定时器停止运行的话可以使用 FreeRTOS 提供的两个开启函数来重新启动软件定时器。

xTimerStart( )

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

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

xTimerStartFromISR( )

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

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

2.2.4停止软件定时器

既然有开启软件定时器的 API 函数,那么肯定也有停止软件定时器的函数,FreeRTOS 也提供了两个用于停止软件定时器的 API 函数。

xTimerStop( )

此函数用于停止一个软件定时器,此函数用于任务中,不能用在中断服务函数中,函数原型如下:

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

xTimerStopFromISR( )

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

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

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

相关推荐
不会编程的懒洋洋1 小时前
Spring Cloud Eureka 服务注册与发现
java·笔记·后端·学习·spring·spring cloud·eureka
scc21401 小时前
spark的学习-06
javascript·学习·spark
luoganttcc1 小时前
能否推荐开源GPU供学习GPU架构
学习·开源
垂杨有暮鸦⊙_⊙2 小时前
阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_技术趋势
笔记·学习·无人机
Mephisto.java2 小时前
【大数据学习 | HBASE高级】region split机制和策略
数据库·学习·hbase
Xiao Fei Xiangζั͡ޓއއ2 小时前
一觉睡醒,全世界计算机水平下降100倍,而我却精通C语言——scanf函数
c语言·开发语言·笔记·程序人生·面试·蓝桥杯·学习方法
Bio Coder3 小时前
学习用 Javascript、HTML、CSS 以及 Node.js 开发一个 uTools 插件,学习计划及其周期
javascript·学习·html·开发·utools
baijin_cha3 小时前
机器学习基础04_朴素贝叶斯分类&决策树分类
笔记·决策树·机器学习·分类
Allen zhu3 小时前
【PowerHarmony】电鸿蒙学习记录-准备工作
学习·华为·harmonyos
华清远见成都中心3 小时前
物联网学习路线来啦!
物联网·学习