当前位置: 首页 > news >正文

FreeRTOS(三)

一.软件定时器的介绍

定时器的定义从指定的时刻开始,经过一段时间,然后触发一个超时事件,用户可以自定义定时器的周期(类似于闹钟,响一次还是周期响)

定时器的分类:硬件定时器,软件定时器。

硬件定时器:芯片自带的定时器模块,硬件定时器一般精度很高(可达微秒/纳秒级),每次在定时时间到达之后就会自动触发一个中断,用户在中断服务函数 中处理信息。不受系统负载影响,依赖芯片内置定时器硬件。
软件定时器:基于软件实现的定时机制,不依赖专用硬件电路,而是通过软件模拟定时器功能,用于实现延时、周期性执行任务或超时检测等相关操作。其核心原理是以系统时钟为基准,通过计数或时间戳比较的方式,在预设时间到达时触发 指定的回调函数或事件。精度较低(通常毫秒级),资源需CPU和内存 ,受CPU负载和调度影响。
软定的特点:精度受系统限制:定时精度取决于系统时钟粒度,通常为毫秒级;灵活性高:可通过软件灵活配置定时周期、触发方式(单次/周期);资源占用低:无需额外硬件资源;. 受系统调度影响:在系统负载较高时,定时精度可能下降。
软件定时器支持设置成单次定时器或周期定时器
在实际中,需要用到定时器任务,但硬件定时器受硬件资源数量的限制,无法提供更多的定时器,那么这时候可以用软件定时器任务来替代硬件定时器的任务。但需要注意的是软件定时器的精度是无法和硬件定时器的精度相比的,因为软件定时器的任务可能被中断以及优先级更高的任务所打断,因为软件定时器本质也是任务,既然是任务就会存在被中断打断的可能。 所以软件定时器是用于对时间精度要求不高或辅助性的任务 。典型应用场景有周期性任务调度(如定期日志打印、状态检测),超时控制(如网络连接超时、用户操作超时),延时执行(如延迟启动某个功能)。

二.软件定时器服务任务

在调用函数vTaskStartScheduler()开启任务调度的时候,会创建两个任务,一个是空闲任务,一个是用于管理软件定时器 的任务,这个任务就叫软件定时器任务 。软件定时器服务任务作用如下:<1>负责软件定时器超时的逻辑判断;<2>调用超时软件定时器的超时回调函数;<3>处理软件定时器命令队列。
FreeRTOS的配置项configUSE_TIMERS设置为1,在启动任务调度器时,会自动创建软件定时器的服务/守护任务(prvTimerTask);
软件定时器服务任务的优先级为:configTIMER_TASK_PRIORITY=2(可配置)
软件定时器的超时回调函数是在软件定时器服务任务中被调用的,服务任务不是专为某个定时器服务的,它还要处理其他定时器。所以:定时器的回调函数不要影响"他人";回调函数要尽快完成,不能进入阻塞状态,即不能调用那些会阻塞任务的API函数,如:vTaskDelay()
eg.
//超时回调函数
void timerCallBackFun( TimerHandle_t xTimer )
{if(xTimer == timerHandle) {void * timeId = pvTimerGetTimerID(xTimer);printf("timerID:%d\r\n", *(uint32_t *)(timeId));}
}

三.软件定时器的命令队列

FreeRTOS提供了许多软件定时器相关的API函数,这些API函数大多都是往定时器的队列中写入消息 (发送命令) 这个队列叫软件定时器命令队列,是提供给FreeRTOS中的软件定时器使用的,用户是不能直接访问的。软件定时器服务函数从软件定时器命令队列中读取消息接受命令。
定时器的命令队列长度为:configTIMER_QUEUE_LENGTH = 10(可配置)

四.软件定时器的状态

软件定时器有俩个状态:休眠态和运行态。向软件定时器命令队列发送命令,比如说发送开启软件定时器命令,这个时候软件定时器就开始工作了,从休眠态转变为运行态
休眠态 :软件定时器可以通过其句柄被引用,但因为没有运行,所以其超时回调函数不会被执行新创建的软件定时器处于休眠状态,也就是未运行的
运行态 :运行态的定时器,当指定时间到达之后,它的超时回调函数会被调用

五.单次定时器和周期定时器

单次定时器:定时器启动后仅在预设时间到达时触发一次回调函数,之后自动进入休眠状态,不再继续计时。
计时到期后执行回调函数,随后自动停止并进入休眠状态。通过 xTimerCreate() uxAutoReload 参数设置为 pdFALSE 来定义为单次定时器。休眠状态下可通过 xTimerStart() xTimerReset() 重新启动,再次触发定时逻辑。
首先创建一个定时器,创建完之后是休眠态的,通过发送命令(开启、复位、更改超时时间),都可以让其转换成运行态,调用停止命令就可以从运行态转换为休眠态,或者单次一旦超时【调用超时回调函数】,就会转换为休眠态。
周期定时器:定时器启动后会按照预设的固定周期重复触发回调函数,直到被主动停止。适用于需要周期性执行的任务,例如定期采集传感器数据、周期性发送心跳包、定时刷新显示屏等场景。
计时到期后执行回调函数,随后自动重置并开始下一个周期的计时,循环往复。通过 xTimerCreate() uxAutoReload 参数设置为 pdTRUE 来定义为周期定时器。运行中可通过xTimerChangePeriod() 修改周期,立即生效或等待当前周期结束后生效。

六.软件定时器API函数接口

<1>创建软件定时器

//动态分配内存
TimerHandle_t xTimerCreate(const char * const pcTimerName, // 定时器名称(仅用于调试)const TickType_t xTimerPeriodInTicks, // 定时周期(单位:系统节拍)const UBaseType_t uxAutoReload, // 模式:pdTRUE=周期,pdFALSE=单次void * const pvTimerID, // 定时器ID(区分多个定时器)TimerCallbackFunction_t pxCallbackFunction // 定时到期后的回调函数
);
//静态分配内存
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,TickType_t xTimerPeriodInTicks,UBaseType_t uxAutoReload,void * pvTimerID,TimerCallbackFunction_t pxCallbackFunction,StaticTimer_t *pxTimerBuffer // 指向用户预分配的StaticTimer_t结构体
);
功能: 创建单次或周期模式的定时器
定时器名称,最大长度由configMAX_TIMER_NAME_LEN定义(默认 24);
定时周期,与configTICK_RATE_HZ相关(例如1000节拍=1秒configTICK_RATE_HZ=1000)。
用户自定义ID,可通过pvTimerGetTimerID()在回调函数中获取,用于区分多个定时器。
定时到期时执行的回调函数,原型为void (*TimerCallbackFunction_t) (TimerHandle_t xTimer)。
返回值: TimerHandle_t类型,成功创建的定时器的句柄。

<2>删除软件定时器

BaseType_t xTimerDelete(TimerHandle_t xTimer, // 要删除的定时器句柄TickType_t xBlockTime // 等待命令队列的最大时间(节拍数)
);
功能:
删除软件定时器的API函数,用于释放定时器所占用的资源
参数说明:
xTimer:要删除的定时器句柄。
xBlockTime:当定时器命令队列已满时,调用者等待队列空闲的最大时间(单位:系统节拍)。若设为
0,则立即返回而不等待。
返回值
pdPASS:定时器成功删除。
pdFAIL:删除失败(通常因命令队列已满且xBlockTime内未获得空闲位置)

<3>启动软件定时器

BaseType_t xTimerStart(TimerHandle_t xTimer, // 要启动的定时器句柄TickType_t xBlockTime // 等待命令队列的最大时间(节拍数)
);
功能:
启动软件定时器,它能将处于休眠状态或挂起状态的定时器切换到运行状态
参数说明:
xTimer:需要启动的定时器句柄
xBlockTime:当定时器命令队列已满时,调用者等待队列空闲的最大时间(单位:系统节拍)。若设为
0,则立即返回而不等待;若设为 portMAX_DELAY,则会一直等待直到队列有空闲位置。
返回值
pdPASS:启动命令成功发送到定时器命令队列,定时器将开始运行。
pdFAIL:启动失败
BaseType_t xTimerStartFromISR(TimerHandle_t xTimer,BaseType_t
*pxHigherPriorityTaskWoken);
功能:
用于在中断服务程序(ISR)中启动软件定时器的专用API函数
参数说明
xTimer:需要启动的定时器句柄
pxHigherPriorityTaskWoken:输出参数,指向一个BaseType_t变量。若启动定时器的操作导致更高优
先级的任务(如定时器服务任务)就绪,该变量会被设为pdTRUE,提示中断退出后需要进行任务切换。
返回值
pdPASS:启动命令成功发送到定时器命令队列。
pdFAIL:启动失败

<3>停止软件定时器

BaseType_t xTimerStop(TimerHandle_t xTimer, // 要停止的定时器句柄TickType_t xBlockTime // 等待命令队列的最大时间(节拍数)
);
功能:
用于停止软件定时器
参数说明
xTimer:需要停止的定时器句柄
xBlockTime:当定时器命令队列已满时,调用者等待队列空闲的最大时间(单位:系统节拍)。设为0表
示立即返回;设为portMAX_DELAY表示无限等待。
返回值
pdPASS:停止命令成功发送到定时器命令队列,定时器将进入休眠状态。
pdFAIL:停止失败
BaseType_t xTimerStopFromISR(TimerHandle_t xTimer, // 要停止的定时器句柄BaseType_t *pxHigherPriorityTaskWoken // 标记是否触发高优先级任务切换
);
功能:
用于在中断服务程序(ISR)中停止软件定时器
参数说明
xTimer:需要启动的定时器句柄
pxHigherPriorityTaskWoken:输出参数,指向一个 BaseType_t 变量。若停止定时器的操作导致更高
优先级任务(如定时器服务任务)从阻塞变为就绪,该变量会被设为 pdTRUE,提示中断退出后需执行任
务切换。
返回值
pdPASS:停止命令成功发送到定时器命令队列,定时器将进入休眠状态。
pdFAIL:停止失败

<4>定时器ID

获得定时器ID
void *pvTimerGetTimerID(TimerHandle_t xTimer);
更新定时器ID
void vTimerSetTimerID(TimerHandle_t xTimer, void *pvNewID);

六.使用案例

首先判断STM32Cubmx中的配置是否正确:

在配置中的USE_TIMERS确保是Enabled,优先级要高一些,确保定时器服务任务的优先级(configTIMER_TASK_PRIORITY)不低于其他任务,否则会被阻塞。

#include "FreeRTOS.h"
#include "timers.h"
#include "task.h"
#include <stdio.h>
#include "cmsis_os.h"TimerHandle_t timerHandle;//超时回调函数
void timerCallBackFun( TimerHandle_t xTimer )
{if(xTimer == timerHandle) {void * timeId = pvTimerGetTimerID(xTimer);printf("timerID:%d\r\n", *(uint32_t *)(timeId));}
}void timer_init()
{//创建软件定时器
//	TimerHandle_t xTimerCreate(	const char * const pcTimerName,			/*lint !e971 Unqualified char types are allowed for strings and single characters only. */
//								const TickType_t xTimerPeriodInTicks,
//								const UBaseType_t uxAutoReload,
//								void * const pvTimerID,
//								TimerCallbackFunction_t pxCallbackFunction )timerHandle = xTimerCreate("mySoftTimer1", pdMS_TO_TICKS(2000), pdPASS, 0, timerCallBackFun);if(timerHandle == NULL) {printf("xTimerCreate failure!\r\n");return;}//启动定时器BaseType_t ret = xTimerStart(timerHandle, portMAX_DELAY);if(ret == pdFAIL) {printf("xTimerStart failure!\r\n");return;}
}

运行结果:

http://www.dtcms.com/a/570305.html

相关文章:

  • 网站建设 要维护么宁波网站建设费用
  • 基于 veRL 多模态混训的视频上下文并行,百度百舸提升具身智能强化学习效能
  • 微网站介绍html做网站头部
  • 如何上传文件到自己的网站wordpress+边框插件
  • 专业的消防风机机电一体化创新厂家
  • 网站建设中模随手app怎么转版
  • 网站建设都需要什么wordpress附件修复
  • 嵌入式网络编程深度优化 --网络协议栈配置实战指南
  • 如何再工商局网站做设备抵押怎样查看网站是否被百度收录
  • static constexpr 有什么作用,适用场景是?
  • 现代C++核心特性——内存篇
  • 教师资格资源合集
  • tp5.1做的网站学校如何重视校园网站建设
  • 江西网站开发软件公司网页设计实训报告结束语
  • 生成模型实战 | β-VAE详解与实现
  • 司马阅与众创集团达成生态战略合作,构建 “综合企业服务资源 + AI智能技术”的创新赋能体系
  • 一张白纸,无限画布:SkyReels刚刚重新定义了AI视频创作
  • Java_ArrayList底层结构和源码分析
  • 局域网创建网站怎么自建一个网站
  • 网站建设问题及解决办法北京网站建设方案品牌公司
  • 网站建设电销话术开场白搜索网排名
  • 中国建设银行官网站汽车卡一级做ae视频直播可以吗多少钱
  • 电子学会青少年机器人技术(三级)等级考试试卷-理论综合(2025年9月)
  • 长沙公司核名网站wordpress的图片存在哪里
  • 【IC】NoC设计入门 -- router模块
  • 网站做项目网络营销方案策划书
  • 外贸功能网站建设电脑课程培训零基础
  • 网站建设策划公司凡科建站怎样建站中站
  • 侯捷STL标准库和泛型编程
  • BigDecimal是怎么比较大小的