FreeRTOS软件定时器(1-18)

软件定时器简介

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

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

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

软件定时器的优缺点

优点:

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     /*软件定时器的编号*/#endifuint8_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         软件定时器定时超时时间修改失败
*/

软件定时器项目实战

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/6928.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java常用命令总结 持续更新中!!!

蓝桥杯JAVA组 推荐输入输出示例 // 基础输入 import java.util.*;public class Main{public static void main(String[] args){} }// 非静态方法调用 new Main.Solution();//static函数里面调用非static函数 类.函数// 更快的输入方式 BufferedReader // 更快的输出方式 Print…

js监听页面的显示和隐藏

下方微信公众号 和微信小程序推荐 js监听页面的显示和隐藏 在JavaScript中,监听页面的显示和隐藏可以通过监听visibilitychange事件来实现。visibilitychange事件会在页面的可见性发生变化时触发。 以下是一个简单的示例,演示如何使用visibilitychan…

打招呼得不到回复,跟头像还有关系?

现在很多人有个想法,那就是觉得某些公司是不是为了某些目的才往出发的招聘信息啊,其实他们并不需要招聘新员工。 目录 已读不回? 头像很重要 选择自己的精修照片 已读不回? 很有这种可能,但你细心观察会发现,的确有很多大公司,

再学Java基础——垃圾回收

在Java中,垃圾回收(Garbage Collection,简称GC)是一个自动的内存管理机制,它用于自动释放那些不再被程序使用的对象所占用的内存空间。这种机制有助于防止内存泄漏和内存溢出等问题,使程序员能够更专注于业…

《面向对象程序设计及C++》实验报告

《面向对象程序设计及C》实验报告 一、实验目的与实验要求 (1)掌握类的定义、类中成员函数的定义和使用、构造函数和析构函数的定义、功能;掌握对象的使用方法。 (2)掌握静态数据成员、静态成员函数的功能和使用方法…

什么是新能源汽车热管理?

前言 新能源汽车热管理是指针对电动汽车等新型动力系统所涉及的热量控制和调节技术,其包括散热、冷却、加热、温度控制等方面。在新能源汽车中,电池、电动机、控制器等部件都会产生一定的热量,如果不进行有效的热管理,将会影响汽…

Java中多线程间的通信机制:初学者指南

Java中多线程间的通信机制:初学者指南 在Java中,多线程编程是构建高效、响应迅速的应用程序的关键。然而,当多个线程需要共享数据或协作完成任务时,就需要考虑线程间的通信问题。线程间的通信是指一个线程需要等待另一个线程完成…

Cocos Creator UICanvas详解与2D游戏配置详解

前言 Cocos Creator是一款强大的2D游戏开发引擎,提供了丰富的工具和组件来帮助开发者快速制作出优秀的游戏作品。其中,UICanvas是Cocos Creator中一个非常重要的组件,用于管理游戏中的UI界面。 在本文中,我们将深入探讨Cocos Cr…

python 学习: 矩阵运算

摘要: 本贴通过例子描述 python 的矩阵运算. 1. 一般乘法 (mm 与 matmul) 代码: input_mat1 torch.tensor([[1, 2, 3, 4],[1, 2, 2, 3]])input_mat2 torch.tensor([[1, 2, 3, 3],[2, 1, 2, 3],[3, 1, 2, 2],[2, 3, 2, 3]])print("input_mat1: ", input_mat1)prin…

Linux —— 信号初识

Linux —— 信号初识 什么是信号测试几个信号signal函数函数原型参数说明返回值注意事项示例 后台程序前台转后台检测输入中断向量表 我们今天来继续学习Linux的内容,今天我们要了解的是Linux操作系统中的信号: 什么是信号 信号是操作系统内核与进程之…

判断dll/lib是32/64位、查看lib是导入库/静态库的方法 、查看dll包含的符合、lib包含的函数

一、判断dll/lib是32/64位 原文链接:https://www.cnblogs.com/bandaoyu/p/16752602.html 1. 简便方法: 直接用记事本或者notepad(或txt文本)打开exe文件(dll文件),会有很多乱码,不要头疼,接下…

Vitis HLS 学习笔记--Schedule Viewer 调度查看器

目录 1. 简介 2. Schedule Viewer详解 2.1 视图说明 2.1.1 Operation\Control Step 2.1.2 周期关系图 2.1.3 Schedule Viewer 菜单栏 2.1.4 属性视图 2.2 内容说明 2.2.1 实参(b)解释 2.2.2 实参(a)解释 2.2.3 变量&am…

Microsoft 推出 Phi-3 系列紧凑型语言模型

本心、输入输出、结果 文章目录 Microsoft 推出 Phi-3 系列紧凑型语言模型前言Phi-3 基础参数模型对比突破性训练技术降低人工智能安全风险Microsoft 推出 Phi-3 系列紧凑型语言模型 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csdn.net/qq_15071263 如果觉得本文对你…

【PyTorch与深度学习】3、PyTorch张量的运算API(下)

课程地址 最近做实验发现自己还是基础框架上掌握得不好,于是开始重学一遍PyTorch框架,这个是课程笔记,这个课还是讲的简略,我半小时的课听了一个半小时。 1. PyTorch的数据类型 数据类型dtype参数遗留的构造函数32位浮点数torch…

WPS二次开发系列:如何使用WPS返回的FileUri

作者持续关注 WPS二次开发专题系列,持续为大家带来更多有价值的WPS开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397) 目录 什么是FileUri 在SDK中的使用场景 打开文档时…

Windows如何安装hadoop

Hadoop是一个开源的分布式计算平台,旨在处理大规模数据的存储和处理。它提供了分布式文件系统(HDFS)和分布式计算框架(MapReduce),使得用户能够在大规模集群上存储和处理数据。Hadoop最初由Apache软件基金会…

15、Python:循环控制语句

在编程中,循环控制语句是实现代码重复执行的基本结构。Python 提供了多种循环控制结构,以适应不同的编程场景。本文将详细介绍 Python 中的 for 循环和 while 循环,以及如何使用 break 和 continue 语句来控制循环流程。 for 循环 for 循环…

spring boot test 设置环境变量

在 Spring Boot 中,可以通过在测试类上添加 TestPropertySource 注解来设置测试环境变量。该注解可以指定一个或多个 properties 文件,或者一个或多个 key-value 形式的环境变量。 例如,如果您有一个名为 application-test.properties 的测试…

cmake进阶:定义函数的使用方法

一. 简介 前面已经将 cmake 中常用的命令 command、变量 variable 都给大家进行了详细介绍,通过前面的学习,相信大家已经掌握了 cmake 工具的基本使用方法; 接下来我们再进一步学习 cmake,本文开始学习 cmake中定义函数。 二. …

TypeScript学习日志-第十九天(namespace命名空间)

namespace命名空间 一、基本用法 namespace 所有的变量以及方法必须要导出才能访问,如图: 二、 嵌套 namespace 可以进行嵌套使用,如图: 它也必须需要导出才能访问 三、合并 当我们出现两个同名的 namespace 它就会合并这两…