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

FreeRTOS学习笔记之软件定时器

一、简介

FreeRTOS中的定时器是(基于滴答定时器)由软件实现的,与STM32的定时器不同,STM32的硬件定时器可以实现输入捕获,输出比较且定时器数量数量有限,当STM32的定时器计时时间到后,可以进入中断函数,而FreeRTOS中的定时器计时时间到后会执行一段代码,这段代码叫做回调函数
FreeRTOS中的定时器在内存足够的情况下可以有无限个,使用起来简单且成本低;缺点就是精度没有硬件高,而且滴答定时器可以被系统中断打断
对于软件定时器容易被系统中断打断,对于需要高精度要求的场合,不建议使用软件定时器。

1.1 什么是软件定时器服务任务?

在调用函数 vTaskStartScheduler()开启任务调度器的时候,系统会自主创建软件定时器服务任务和空闲任务。
软件定时器服务任务它是一个任务,主要负责软件定时器超时的逻辑判断调用超时软件定时器的回调函数以及处理软件定时器命令队列,我的理解是软件定时器服务任务它是一个任务,这个任务管理所有软件定时器。该任务服务于全部的软件定时器

注意:软件定时器超时回调函数是由软件定时器服务任务调用的,软件定时器超时回调函数不是任务,所以回调函数不会阻塞,也因此不可在回调函数中使用可能会导致任务阻塞的API函数,如果用了导致阻塞的API函数,那么会将软件定时器服务任务阻塞,阻塞后,软件定时器服务任务负责的其他软件定时器在软件定时器服务任务阻塞期间不可工作。

1.2 什么是软件定时器命令队列?

先看几个宏定义
#define configUSE_TIMERS 用于开启软件定时器功能,系统创建软件定时器服务任务和空闲任务
#define configTIMER_TASK_PRIORITY 用于配置软件定时器服务任务的任务优先级,建议配置最大优先级用于调用软件定时器超时回调函数
#define configTIMER_QUEUE_LENGTH 用于配置软件定时器命令队列的队列长度(须大于0)
#define configTIMER_TASK_STACK_DEPTH 用于配置软件定时器服务任务的栈大小
开启系统软件定时器功能使系统创建软件定时器服务任务、配置软件定时器命令队列的长度、设定软件定时器服务任务优先级、设定软件定时器服务任务的栈大小

对于软件定时器命令队列,其相当于介于应用程序和软件定时器服务任务的一个桥梁

从本篇的2.2 API函数章节可以看出,想要对软件按定时器进行操作,就需要往软件定时器命令队列中发送相应的指令(比如创建、开启定时器等),(如果队列项满了,还需要发送进行阻塞等待),软件定时器服务任务在从软件定时器命令队列中获取指令对定时器进行更改

 1.3 软件定时器状态

<1>休眠态:休眠态软件定时器可以通过其句柄被引用,但是因为没有运行,所以其定时超时回调函数不会被执行。
<2>运行态:处于运行态或在上次定时超时后再次定时超时的软件定时器,会执行其定时超时回调函数
<1>单次定时器:定时器的一旦定时超时,只会执行一次其软件定时器超时回调函数,超时后可以被手动重新开启,但单次定时器不会自动重新开启定时
<2>周期定时器:定时器的一旦被开启,会在每次超时时,自动地重新启动定时器,从而周期地执行其软件定时器回调函数。
注意:新创建的软件定时器处于休眠状态,也就是未运行状态。可以通过发送命令队列使定时器从休眠态转变为运行态

二、结构体/API函数

2.1 结构体

    typedef struct tmrTimerControl                {const char * pcTimerName;                   //软件定时器名字ListItem_t xTimerListItem;                  //软件定时器列表项TickType_t xTimerPeriodInTicks;             //软件定时器周期void * pvTimerID;                           //软件定时器ID,当两个定时器对应同一个超时回调函数时,通过ID分辨TimerCallbackFunction_t pxCallbackFunction; //软件定时器的回调函数#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxTimerNumber;              //软件定时器编号,调试用#endifuint8_t ucStatus;                           //软件定时器状态,单次/周期} xTIMER;

2.2 API函数

函数描述
xTimerCreate()动态方式创建软件定时器
xTimerCreateStatic()静态方式创建软件定时器
xTimerStart()开启软件定时器定时
xTimerStartFromISR()在中断中开启软件定时器定时
xTimerStop()停止软件定时器定时
xTimerStopFromISR()在中断中停止软件定时器定时
xTimerReset()复位软件定时器定时
xTimerResetFromISR()在中断中复位软件定时器定时
xTimerChangePeriod()更改软件定时器的定时超时时间
xTimerChangePeriodFromISR()在中断中更改软件定时器的定时超时时间
xTimerDelete()删除软件定时器

2.2.1 创建软件定时器API

TimerHandle_t xTimerCreate
(const char * const pcTimerName             ,//@软件定时器名const TickType_t xTimerPeriodInTicks       ,//@软件定时器定时超时时间,单位为系统时钟节拍const UBaseType_t uxAutoReload             ,//@定时模式,pdTURE周期定时,pdFALSE单次定时void * const pvTimerID                     ,//@定时器ID,用于多个定时器公用一个回调函数TimerCallbackFunction_t pxCallbackFunction  //@软件定时器超时回调函数
);
返回值:
NULL:定时器创建失败
其他值:软件定时创建成功,返回其句柄

2.2.2 开启软件定时器API

为什么每一个对软件定时器进行操作的API都有可以设定的等待时间呢?因为操作定时器的是定时器服务任务,而定时器服务任务需要从定时器命令队列中获取消息指令,也就是用于对定时器操作的API相当于向软件定时器队列中发送消息指令,但队列项的值是一定的,如果多个API操作函数往队列中发送消息,那么当队列项满的时候,则可以选择阻塞等待一段时间,看看队列项没有没有空的。

BaseType_t xTimerStart
(TimerHandle_t xTimer        , //@待开启的软件定时器的句柄const TickType_t xTicksToWait //@发送命令到软件定时器命令队列的最大等待时间
);
返回值:
pdPASS:软件定时器开启成功
pdFAIL:软件定时器开启失败

2.2.3 关闭软件定时器API

BaseType_t xTimerStop
(TimerHandle_t xTimer        , //@待关闭的软件定时器的句柄const TickType_t xTicksToWait //@发送命令到软件定时器命令队列的最大等待时间
);
返回值:
pdPASS:软件定时器关闭成功
pdFAIL:软件定时器关闭失败

2.2.4 复位软件定时器

该功能将使软件定时器的重新开启定时,例如定时器设定超时时间为10ms,当定时器计时到5ms时复位该定时器,则定时器会重新计时10ms.

BaseType_t xTimerReset
(TimerHandle_t xTimer         ,//@待复位的软件定时器的句柄const TickType_t xTicksToWait //@发送命令到软件定时器命令队列的最大等待时间
);
返回值:
pdPASS:软件定时器复位成功
pdFAIL:软件定时器复位失败

2.2.5 更改软件定时器的定时超时时间

BaseType_t xTimerChangePeriod
(TimerHandle_t xTimer          ,//@待更改定时超时时间的软件定时器的句柄const TickType_t xNewPeriod   ,//@新的定时超时时间,单位:系统时钟节拍const TickType_t xTicksToWait  //@发送命令到软件定时器命令队列的最大等待时间
);
返回值:
pdPASS:软件定时器定时超时时间更改成功
pdFAIL: 软件定时器定时超时时间更改失败

http://www.xdnf.cn/news/15721.html

相关文章:

  • 【初识数据结构】CS61B中的基本图算法:DFS, BFS, Dijkstra, A* 算法及其来历用法
  • Java-77 深入浅出 RPC Dubbo 负载均衡全解析:策略、配置与自定义实现实战
  • CS231n-2017 Lecture3线性分类器笔记
  • 时序数据库选型实战:Apache IoTDB技术深度解析
  • 用逻辑回归(Logistic Regression)处理鸢尾花(iris)数据集
  • 移除debian升级后没用的垃圾
  • 电商商品综合排序:从需求分析到实时计算的全方位指南
  • 鸿蒙与web混合开发双向通信
  • The Missing Semester of Your CS Education 学习笔记以及一些拓展知识(三)
  • HTTP性能优化实战
  • Matplotlib和Plotly知识点(Dash+Plotly分页展示)
  • Android 开发实战:从零到一集成 espeak-ng 实现中文离线 TTS(无需账号开箱即用)
  • Qt笔记整理(1)
  • CCF编程能力等级认证GESP—C++5级—20250628
  • 使用nvm安装node、npm、pnpm以及编译项目教程
  • SpringBoot 3.0 挥别 spring.factories,拥抱云原生新纪元
  • 基于大模型打造故障预警服务器巡检机器人
  • Jetpack Compose中的Modifier:UI元素的装饰与行为扩展
  • 3-大语言模型—理论基础:生成式预训练语言模型GPT(代码“活起来”)
  • [论文阅读] 软件工程 | 用模糊逻辑“解锁”项目成功:告别非黑即白的评估时代
  • 网络基础DAY13-NAT技术
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 基于wordcloud库实现词云图
  • OSPF高级特性之Overflow
  • 浅谈Rust语言特性
  • 1 渗透基础
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - snowNLP库实现中文情感分析
  • 【unitrix】 6.7 基本结构体(types.rs)
  • Python 使用期物处理并发(使用concurrent.futures模块下载)
  • Leetcode刷题营第三十三题:对称二叉树
  • 五大开源OCR开源框架评估01-Tesseract:OCR 领域的远古巨神