19_FreeRTOS软件定时器
目录
软件定时器介绍
FreeRTOS软件定时器特点
软件定时器的命令队列
软件定时器的相关配置
单次定时器和周期定时器
软件定时器结构体成员
FreeRTOS软件定时器相关API函数
实验源码
软件定时器介绍
定时器描述:从指定的时刻开始,经过一个指定时间,然后触发一个超时事件,用户可自定义定时器的周期。
硬件定时器描述:芯片本身自带的定时器模块,硬件定时器的精度一般很高,每次在定时时间到达之后就会自动触发一个中断,用户在中断服务函数中处理信息。
软件定时器:是指具有定时功能的软件,可设置定时周期,当指定时间到达后要调用回调函数(也称超时函数),用户在回调函数中处理信息。
软件定时器优点:
1.硬件定时器数量有限,而软件定时器理论上只需有足够内存,就可以创建多个。
2.使用简单、成本低
软件定时器缺点:
1.软件定时器相对硬件定时器来说,精度没有那么高(因为它以系统时钟为基准,系统时钟中断优先级又是最低,容易被打断)。对于需要高精度要求的场合,不建议使用软件定时器。
FreeRTOS软件定时器特点
可裁剪:软件定时器是可裁剪可配置的功能,如果要使能软件定时器,需将configUSE_TIMERS配置项配置成 1
单次和周期:软件定时器支持设置成:单次定时器或周期定时器
注意:软件定时器的超时回调函数是由软件定时器服务任务调用的,软件定时器的超时回调函数本身不是任务,因此不能在该回调函数中使用可能会导致任务阻塞的API函数。
软件定时器服务任务作用:
1.负责软件定时器超时的逻辑判断
2.调用超时软件定时器的超时回调函数
3.处理软件定时器命令队列
软件定时器的命令队列
FreeRTOS提供了许多软件定时器相关的API函数,这些API函数大多都是往定时器的队列中写入消息(发送命令) ,这个队列叫做软件定时器命令队列,是提供给FreeRTOS中的软件定时器使用的,用户是不能直接访问的。
软件定时器的相关配置
当FreeRTOS的配置项configUSE_TIMERS设置为1,在启动任务调度器时,会自动创建软件定时器的服务/守护任务prvTimerTask();
软件定时器服务任务的优先级为configTIMER_TASK_PRIORITY =31;
定时器的命令队列长度为 configTIMER_QUEUE_LENGTH =5 ;
注意:软件定时器的超时回调函数是在软件定时器服务任务中被调用的,服务任务不是专为某个定时器服务的,它还要处理其他定时器。所以,定时器的回调函数不要影响其他定时器。
1.回调函数要尽快实行,不能进入阻塞状态,即不能调用那些会阻塞任务的API 函数,如:vTaskDelay();
2.访问队列或者信号量的非零阻塞时间的API函数也不能调用。
软件定时器的状态
软件定时器共有两种状态
休眠态:软件定时器可以通过其句柄被引用,但因为没有运行,所以其定时超时回调函数不会被执行。
运行态:运行态的定时器,当指定时间到达之后,它的超时回调函数会被调用。
注意:新创建的软件定时器处于休眠状态,也就是未运行的!发送命令队列软件定时器从休眠态转变为运行态
单次定时器和周期定时器
单次定时器:单次定时器的一旦定时超时,只会执行一次其软件定时器超时回调函数,不会自动重新开启定时,不过可以被手动重新开启。
周期定时器:周期定时器的一旦启动以后就会在执行完回调函数以后自动的重新启动,从而周期地执行其软件定时器回调函数。
Timer1:周期定时器,定时超时时间为2个单位时间,开启后,一直以2个时间单位间隔重复执行;
Timer2:单次定时器,定时超时时间为1个单位时间,开启后,则在第一个超时后就不在执行了。
单次定时器状态转换图
周期定时器状态转换图
软件定时器结构体成员
typedef struc
{
tconst char* pcTimerName /* 软件定时器名字*/
Listltem_t xTimerListltem /* 软件定时器列表项*/
TickType_t xTimerPeriodInTicks;/*软件定时器的周期*/
void * pvTimerID /*软件定时器的ID*/
TimerCallbackFunction_t pxCallbackFunction;/*软件定时器的回调函数*/
#if (configUSE_TRACE_FACILITY ==1)
UBaseType_t uxTimerNumber /*软件定时器的编号,调试用*/
#endif
uint8_t ucStatus; /*软件定时器的状态*/
}xTIMER;
FreeRTOS软件定时器相关API函数
创建软件定时器API函数
TimerHandle_t xTimerCreate( const char* constpcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t constuxAutoReload,
void* pvTimerlD,
TimerCallbackFunction_t pxCallbackFunction );
开启软件定时器API函数
BaseType_t xTimerStart(TimerHandle_txTimer,const TickType_t xTicksToWait);
停止软件定时器API函数
BaseType_t xTimerStop( TimerHandle_txTimer,const TickType_txTicksToWait);
复位软件定时器API函数
该功能将使软件定时器的重新开启定时,复位后的软件定时器以复位时的时刻作为开启时刻重新定时
BaseType_t xTimerReset( TimerHandle_txTimer,const TickType_txTicksToWait);
更改软件定时器超时时间API函数
BaseType_t xTimerChangePeriod(TimerHandle_txTimer,
const TickType_txNewPeriod,
const TickType_txTicksToWait);
实验源码
设计两个任务:start_task、task1
start_task:用来创建task1任务,并创建两个定时器(单次和周期)
task1:用于按键扫描,并对软件定时器进行开启、停止操作
/********************************************************************************* @file : user_mian.h* @brief : V1.00******************************************************************************* @attention********************************************************************************//* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "user_key.h"
#include "queue.h"
#include "event_groups.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define 定义----------------------------------------------------------------*/
/* Macro 宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/
/* Constants 常量--------------------------------------------------------------*/
/* Function 函数--------------------------------------------------------------*/
void Timer1_Callback(TimerHandle_t pxTimer);
void Timer2_Callback(TimerHandle_t pxTimer);TimerHandle_t Timer1 = 0;/*单次定时器*/
TimerHandle_t Timer2 = 0;/*周期定时器*/uint32_t Timer1_;
uint32_t Timer2_;//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define TASK1_PRIO 4
//任务堆栈大小
#define TASK1_STK_SIZE 100
//任务句柄
TaskHandle_t TASK1_Handler;
//任务函数
void task1(void *pvParameters);int main(void){ /*配置系统中断分组为4位抢占*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/*延时函数初始化*/delay_init();/*RCC配置*/Rcc_config();/*GPIO初始化*/ Gpio_Init();/*USART1初始化*/Uart1_Init(9600);/*创建开始任务*/xTaskCreate((TaskFunction_t )start_task, //任务函数(const char* )"start_task", //任务名称(uint16_t )START_STK_SIZE, //任务堆栈大小(void* )NULL, //传递给任务函数的参数(UBaseType_t )START_TASK_PRIO, //任务优先级(TaskHandle_t* )&StartTask_Handler); //任务句柄 vTaskStartScheduler(); //开启任务调度}/*!\brief 开始任务函数\param[in] 传递形参,创建任务时用户自己传入\param[out] none\retval none
*/
void start_task(void *pvParameters)
{taskENTER_CRITICAL(); //进入临界区/*创建单次软件定时器*//*名字,延时时间,pdFALSE单次,编号1,回调函数*/Timer1 = xTimerCreate("Tiner1",1000,pdFALSE,(void *)1,Timer1_Callback);/*创建周期软件定时器*//*名字,延时时间,pdTRUE周期,编号2,回调函数*/Timer2 = xTimerCreate("Tiner2",1000,pdTRUE,(void *)2,Timer2_Callback);//创建任务xTaskCreate((TaskFunction_t )task1, (const char* )"task1", (uint16_t )TASK1_STK_SIZE, (void* )NULL, (UBaseType_t )TASK1_PRIO, (TaskHandle_t* )&TASK1_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL(); //退出临界区
}/*!\brief 任务1扫描控制软件定时器\param[in] 传递形参,创建任务时用户自己传入\param[out] none\retval none
*/
void task1(void *pvParameters)
{uint8_t key = 0;while(1){ key = Key_Scan(0);if(key == KEY0_PRES){/*开启定时器*/xTimerStart(Timer1,portMAX_DELAY);xTimerStart(Timer2,portMAX_DELAY);taskENTER_CRITICAL(); //进入临界区 printf("开启2个定时器\r\n\r\n");taskEXIT_CRITICAL(); //退出临界区}else if(key == KEY1_PRES){/*关闭定时器*/xTimerStop(Timer1,portMAX_DELAY);xTimerStop(Timer2,portMAX_DELAY);Timer1_ = 0;Timer2_ = 0;taskENTER_CRITICAL(); //进入临界区 printf("停止2个定时器\r\n\r\n");taskEXIT_CRITICAL(); //退出临界区}vTaskDelay(10);}
} /*!\brief 单次定时器回调函数\param[in] none\param[out] none\retval none
*/
void Timer1_Callback(TimerHandle_t pxTimer)
{taskENTER_CRITICAL(); //进入临界区 printf("单次定时器运行次数:%d次数\r\n\r\n",++Timer1_);taskEXIT_CRITICAL(); //退出临界区}/*!\brief 周期定时器回调函数\param[in] none\param[out] none\retval none
*/
void Timer2_Callback(TimerHandle_t pxTimer)
{taskENTER_CRITICAL(); //进入临界区 printf("周期定时器运行次数:%d次数\r\n\r\n",++Timer2_);taskEXIT_CRITICAL(); //退出临界区
}/************************************************************** END OF FILE ****/
相关文章:

19_FreeRTOS软件定时器
目录 软件定时器介绍 FreeRTOS软件定时器特点 软件定时器的命令队列 软件定时器的相关配置 单次定时器和周期定时器 软件定时器结构体成员 FreeRTOS软件定时器相关API函数 实验源码 软件定时器介绍 定时器描述:从指定的时刻开始,经过一个指定时间,然后触发一个超时事件…...

值得推荐!安利5款良心又好用的小众软件
电脑上的各类软件有很多,除了那些常见的大众化软件,还有很多不为人知的小众软件,专注于实用功能,简洁干净、功能强悍。今天分享5个实用的软件,简单实用,效果拉满,堪称工作生活必备! …...

Enhanced ShockBurst (ESB)原文翻译
自我学习为主,同时也为所需要的提供一份资料 官方地址 增强型ShockBurst(ESB)是一种支持双向数据包通信的基本协议,包括数据包缓冲、数据包确认和丢失数据包的自动重传。ESB以低功耗提供无线通信,并且实现的代码量小且…...
软件测试之兼容性测试
对于基于计算机平台的软件,在测试过程中必须考虑软、硬件的兼容性,在设计测试用例的过程中必须考虑数据转换或转移的问题,应该尽力发现其可能带来的错误。不仅是基于计算机平台的软件,对于嵌入式软件也一样,在软件升级…...
笔记(一)——容器
容器分类:序列式容器:每个元素都有固定位置,取决于插入的时机和地点,和元素无关,如vector、deque、list、stack、queue。关联式容器:元素位置取决于特定的排序准则,和插入顺序无关,如…...
C++入门:命名空间
假设这样一种情况,当一个班上有两个名叫 Zara 的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字等等。同样的情况也出现在 C 应用程序中。例…...

操作系统(复试准备)
操作系统(复试准备) 第一章知识点 操作系统概述 操作系统的概念 负责协调软硬件等计算机资源的工作 为上层用户,应用程序提供简单易用的接口 是一种系统软件 操作系统的功能与目标 资源的管理者 处理机管理,存储器管理&#x…...
2023年CDGA考试模拟题库(501-600)
2023年CDGA考试模拟题库(501-600) 501.希望从数据中获取价值的组织认识到,高质量数据比低质量数据更有价值。使用劣质数据充满风险,会损害组织的声誉,导致罚款、收入损失、客户流失和负面的媒体曝光等组织基于各种业务驱动因素而着手进行数据质量管理活动,下列哪项不属于上述驱…...
NCNN+Int8+yolov5部署和量化
【GiantPandaCV引言】 还记得我在两个月前写的文章吗,关于yolov4-tiny+ncnn+int8量化的详细教程:NCNN+INT8+YOLOV4量化模型和实时推理 后来准备写yolov5+ncnn+int8量化的教程,却在yolov5的量化上遇到了麻烦,一方面是量化后速度更慢了,另一方面是精度下降严重,出现满屏都…...

springboot+vue.js协同过滤算法之智能旅游推荐系统java
目 录 第一章 绪论 3 1.1课题背景 3 1.2课题研究的目的和意义 3 1.3 研究现状 4 1.4论文所做的主要工作 4 第二章 技术介绍 5 2.1B/S结构 5 2.2MySQL 介绍 5 2.3MySQL环境配置 6 第三章 系统分析与设计 8 3.1系统说明 8 3.2系统可行性分析…...

Google Brain新提出的优化器“Lion”,效果要比Adam(W)更好
Google Brain新提出的优化器“Lion”,效果要比Adam(W)更好 论文地址:https://arxiv.org/abs/2302.06675代码地址:https://github.com/google/automl/blob/master/lion/lion_pytorch.py 1 简单、内存高效、运行速度更快 与 AdamW 和各种自适…...

慢雾:Discord 私信钓鱼手法分析
事件背景 5 月 16 日凌晨,当我在寻找家人的时候,从项目官网的邀请链接加入了官方的 Discord 服务器。在我加入服务器后立刻就有一个"机器人"(Captcha.bot)发来私信要我进行人机验证。这一切看起来相当的合理。我也点击了这个验证链接进行查看…...
2023-2-25 刷题情况
交换字符使得字符串相同 题目描述 有两个长度相同的字符串 s1 和 s2,且它们其中 只含有 字符 “x” 和 “y”,你需要通过「交换字符」的方式使这两个字符串相同。 每次「交换字符」的时候,你都可以在两个字符串中各选一个字符进行交换。 …...

【数据结构】双向链表的接口实现(附图解和源码)
双向链表的接口实现(附图解和源码) 文章目录双向链表的接口实现(附图解和源码)前言一、定义结构体二、接口实现(附图解源码)1.初始化双向链表2.开辟新空间3.尾插数据4.尾删数据5.打印双向链表中数据6.头插数…...

数据结构与算法之[把数字翻译成字符串]动态规划
前言:最近在刷动态规划的算法题目,感觉这一类题目还是有一点难度的,但是不放弃也还是能学好的,今天给大家分享的是牛客网中的编程题目[把数字翻译成字符串],这是一道经典的面试题目,快手,字节跳…...

java 面向对象三大特性之多态 万字详解(超详细)
目录 前言 : 一、为什么需要多态 : 1.白璧微瑕 : 2.举栗(请甘雨,刻晴,钟离吃饭): 3.代码 : 4.问题 : 二、什么是多态 : 1.定义 : 2.多态的实现步骤(重要) : 三、多态的使用 : 1.多态中成员方法的使用(重要…...

git push origin master 情况
📢📢📢📣📣📣哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝一位上进心十足的【Java ToB端大厂领…...
ElasticSearch查询优化routing
如果一个索引分片多达一百,再加上每个分片数据量大的情况下ES查询速度会慢,这种情况可以根据业务情况考虑使用_routing优化。 _routing 路由 当索引一个文档的时候,文档会被存储在一个主分片上。在存储时一般都会有多个主分片。Elasticsearch 如何知道一个文档应该放置在哪…...
【HashMap 1.7和1.8】
Java中的HashMap是一种常用的数据结构,用于存储键值对。在Java 1.7和1.8中,HashMap的实现有一些不同。 Java 1.7中的HashMap实现是基于“拉链法”的哈希表。每个哈希桶(bucket)是一个链表,存储了散列值相同的键值对。当键值对数量过多时&…...
【Zabbix实战之故障处理篇】Zabbix监控中文乱码问题解决方法
【Zabbix实战之故障处理篇】Zabbix监控中文乱码问题解决方法 一、问题展现1.查看Zabbix仪表盘2.问题分析二、检查Zabbix环境1.检查Zabbix监控主机2.检查Zabbix各组件状态三、在宿主机安装中文字体库1.安装中文字体2.查看字体文件四、安装中文字库1.查看Zabbix所有组件容器2.拷贝…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...