freertos---软定时器

2023-11-06

一、软件定时器介绍

freeRTOS软件定时器的时基是基于系统时钟节拍实现的,可以创建很多个,在硬件定时器资源不充足的情况下非常有用。

软件定时器一般用作周期性地执行函数,在创建软件定时器时指定软件定时器的回调函数,在回调函数中实现相应的功能。

二、软件定时器的两种模式

FreeRTOS 提供的软件定时器支持单次模式和周期模式, 单次模式和周期模式的定时时间到之后都会调用软件定时器的回调函数。
单次模式(One-shot timers):当用户创建了定时器并启动了定时器后,定时时间到了,只执行一次回调函数之后就将该定时器进入休眠状态,不再重新执行。
周期模式(Auto-reload timers):这个定时器会按照设置的定时时间循环执行回调函数,直到用户将定时器删除

在这里插入图片描述

 三、软件定时器的两种状态

休眠态(Dormant):A Dormant software timer exists, and can be referenced by its handle, but is not running, so its callback functions will not execute.

运行态(Running):A Running software timer will execute its callback function after a time equal to its  period has elapsed since the software timer entered the Running state, or since the software timer was last reset

自动重载定时器执行回调函数后重新进入运行状态,一次性定时器执行回调函数后进入休眠状态。

四、守护任务和定时器命令队列

1、守护任务(daemon task)

daemon task又称作timer service task,这是因为早期这个任务是执行定时器回调函数的,现在freertos版本的该任务还有别的用途,因此,更多地叫做daemon task。

当rtos调度器开始调度的时候,daemon task自动被创建,daemon task的优先级(configTIMER_TASK_PRIORITY)和栈大小(configTIMER_TASK_STACK_DEPTH)在 FreeRTOSConfig.h设置。

守护任务为了更好的管理FreeRTOS的定时器组件而专门创建了一个定时器任务。

2、定时器命令队列(The Timer Command Queue)

The Timer Command Queue是一个标准的队列,在调度器开始调度的时候也会自动创建,队列的长度在FreeRTOSConfig.h文件中configTIMER_QUEUE_LENGTH指定。
软件定时器API 会通过 定时器命令队列 发送定时器命令(‘start a timer’, ‘stop a timer’ and ‘reset a timer’) 给守护任务,守护任务来执行相关命令和定时器回调函数。 (这是实现软件定时器的核心原理)

发送到定时器命令队列的命令包含一个时间戳。例如,如果发送“启动计时器”命令来启动一个周期为 10 的计时器,则时间戳用于确保10个周期是从发送出命令开始算起,而不是命令由守护任务处理后开始算起。

3、示例

  • t1:task1状态为Running state,daemon task 在 the Blocked state
  • t2:task1调用 xTimerStart().xTimerStart() 向定时器命令队列发送命令,导致守护进程任务离开阻塞状态。 task1的优先级高于守护程序任务,因此守护程序任务不会抢占task1task1仍处于 Running 状态,守护程序任务已离开 Blocked 状态并且进入就绪状态。
  • t3:task1执行完成xTimerStart函数,继续执行后面的内容
  • t4:task1调用某些API函数导致进行阻塞状态,daemon task 在进入运行态
  • t5:daemon task完成task1发送的命令,此时命令队列为空,daemon task又进入阻塞状态。idle task进入运行态

  • t1:task1状态为Running state,daemon task 在 the Blocked state
  • t2:task1调用 xTimerStart().xTimerStart() 向定时器命令队列发送命令,导致守护进程任务离开阻塞状态。 task1的优先级低于守护任务,因此守护任务抢占task1,task1变为就绪态,此时task1还没有执行完成xTimerStart函数守护程序进入 Running 状态。
  • t3:daemon task完成task1发送的命令,此时命令队列为空,daemon task又进入阻塞状态。task1从就绪态进入运行态
  • t4:task1执行完成xTimerStart函数,继续执行后面的内容
  • t5:task1调用某些API函数导致进行阻塞状态,idle task进入运行态

五、相关API函数

API原型 函数说明 参数说明 返回值
TimerHandle_t xTimerCreate( const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction );

用于创建一个软件定时器,创建成功后定时器处于休眠状态。

可以在任务调度器调度之前创建定时器。

  •  pcTimerName:软件定时器的名字,字符串类型
  • xTimerPeriodInTicks:定时时间,以ticks为单位
  • uxAutoReload:是否自动重新装载,pdTRUE和pdFALSE
  • pxCallbackFunction:回调函数指针
  • pvTimerID

    通常用于在当同一个回调函数被多个定时器使用的情况。void *类型

NULL 表示没有足够的堆空间分配给队列而导致创建失败。
非 NULL 值表示队列创建成功。此返回值应当保存下来,以作为
操作此定时器的句柄
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );

启动在休眠状态的定时器,或者复位(重新启动)在运行状态的定时器;

可以在任务调度器调度之前启动定时器,但是定时器不会在调度器工作之前真正启动定时器;

在中断服务程序里应该使用xTimerStartFromISR()来启动定时器

  • xTimer:目标定时器的句柄
  • xTicksToWait:如果定时器命令队列已满,调用任务应保持在阻塞状态以等待命令队列上腾出可用空间

pdPASS:启动定时器的命令成功发送到定时器命令队列

pdFALSE:如 果 由 于 队 列 已 满 而 无 法 将 数 据 写 入(超时时间过了依旧不能写入)

void vTimerSetTimerID( const TimerHandle_t xTimer, void *pvNewID );

设置定时器ID

  • xTimer:目标定时器的句柄
  • pvNewID :定时器id,void *类型,所以可以保存任意类型。

void *pvTimerGetTimerID( TimerHandle_t xTimer );

获取定时器id,通常用在回调函数中。

当多个定时器的回调函数相同,在回调函数获取id从而辨识是哪一个定时器调用的回调函数。

  • xTimer:目标定时器的句柄
获取到的id
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
TickType_t xNewTimerPeriodInTicks,
TickType_t xTicksToWait );

修改定时器的定时时间。

在休眠状态下调用该API,会使得定时器开始运行,不需要执行start函数;在运行状态下调用该API,修改定时时间,定时器还处在运行状态。

中断模式下应使用xTimerChangePeriodFromISR()

  • xTimer:目标定时器的句柄
  • xNewTimerPeriodInTicks:定时时间,以ticks为单位
  • xTicksToWait:如果定时器命令队列已满,调用任务应保持在阻塞状态以等待命令队列上腾出可用空间

pdPASS:更改定时器时间命令成功发送到定时器命令队列

pdFALSE:如 果 由 于 队 列 已 满 而 无 法 将 数 据 写 入(超时时间过了依旧不能写入)

BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );

复位定时器,即重新启动定时器,定时器的超时时间从reset定时器开始算起,并不是从一开始启动的时间算起。

在休眠模式下调用该API,会自动启动定时器。

中断模式下应使用

xTimerResetFromISR()
  • xTimer:目标定时器的句柄
  • xTicksToWait:如果定时器命令队列已满,调用任务应保持在阻塞状态以等待命令队列上腾出可用空间

pdPASS:复位定时器的命令成功发送到定时器命令队列

pdFALSE:如 果 由 于 队 列 已 满 而 无 法 将 数 据 写 入(超时时间过了依旧不能写入)

六、定时器使用示例

1、one-shot和auto-reload定时器举例

#define mainONE_SHOT_TIMER_PERIOD pdMS_TO_TICKS( 3333 )
#define mainAUTO_RELOAD_TIMER_PERIOD pdMS_TO_TICKS( 500 )
int main( void )
{
	TimerHandle_t xAutoReloadTimer, xOneShotTimer;
	BaseType_t xTimer1Started, xTimer2Started;
	
	xOneShotTimer = xTimerCreate( "OneShot", mainONE_SHOT_TIMER_PERIOD,pdFALSE, 
	0, prvOneShotTimerCallback ); 
	xAutoReloadTimer = xTimerCreate( "AutoReload", mainAUTO_RELOAD_TIMER_PERIOD, pdTRUE, 
	0, prvAutoReloadTimerCallback ); 
	
	if( ( xOneShotTimer != NULL ) && ( xAutoReloadTimer != NULL ) )
	{
		xTimer1Started = xTimerStart( xOneShotTimer, 0 );
		xTimer2Started = xTimerStart( xAutoReloadTimer, 0 );
		/* The timer service task does not get created until the scheduler is started, 
		so all commands sent to the command queue will stay in the queue until after 
		the scheduler has been started.  */
		if( ( xTimer1Started == pdPASS ) && ( xTimer2Started == pdPASS ) )
		{
			vTaskStartScheduler();
		}
	}
	for( ;; );
}

static void prvOneShotTimerCallback( TimerHandle_t xTimer )
{
	TickType_t xTimeNow;
	xTimeNow = xTaskGetTickCount();
	vPrintStringAndNumber( "One-shot timer callback executing", xTimeNow );
	ulCallCount++;
}

static void prvAutoReloadTimerCallback( TimerHandle_t xTimer )
{
	TickType_t xTimeNow;
	xTimeNow = uxTaskGetTickCount();
	vPrintStringAndNumber( "Auto-reload timer callback executing", xTimeNow );
	ulCallCount++;
}

ref:

【FreeRTOS操作系统教程】第19章 FreeRTOS定时器组_硬汉Eric2013_新浪博客

FreeRTOS软件定时器_hqy450665101的博客-CSDN博客_freertos软件定时器

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

freertos---软定时器 的相关文章

  • FreeRTOS例程4-串口DMA收发不定长数据

    FreeRTOS例程4 串口DMA收发不定长数据 知乎 zhihu com
  • FreeRTOS config开始的宏

    FreeRTOSConfig h系统配置文件中可以自定义 FreeRTOS h中定义默认值 configAPPLICATION ALLOCATED HEAP 默认情况下FreeRTOS的堆内存是由编译器来分配的 将宏configAPPLIC
  • 【FreeRTOS 信号量】互斥信号量

    互斥信号量与二值信号量类似 但是互斥信号量可以解决二值信号量出现的优先级翻转问题 解决办法就是优先级继承 普通互斥信号量创建及运行 参阅安富莱电子demo 互斥信号量句柄 static SemaphoreHandle t xMutex NU
  • FreeRTOS软件定时器创建、复位、开始和停止(备忘)

    目录 一 简介 1 1 开发环境 1 2 摘要 二 STM32CubeIDE配置 三 创建定时器 3 1 头文件声明 3 2 工程文件定义 3 3 创建定时器 3 4 开启 复位 和关闭定时器 四 定时器回调函数 一 简介 1 1 开发环境
  • FreeRTOS学习笔记(3、信号量、互斥量的使用)

    FreeRTOS学习笔记 3 信号量 互斥量的使用 前言 往期学习笔记链接 学习工程 信号量 semaphore 两种信号量的对比 信号量的使用 1 创建信号量 2 give 3 take 4 删除信号量 使用计数型信号量实现同步功能 使用
  • FreeRTOS系列

    本文主要介绍如何在任务或中断中向队列发送消息或者从队列中接收消息 使用STM32CubeMX将FreeRTOS移植到工程中 创建两个任务以及两个消息队列 并开启两个中断 两个任务 Keyscan Task 读取按键的键值 并将键值发送到队列
  • 【FreeRTOS开发问题】FreeRTOS内存溢出

    FreeRTOS内存溢出 如下图所示 FreeRTOS编译完成后可以看到 系统提示无法分配内存到堆 Objects Template axf Error L6406E No space in execution regions with A
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory (referred from tasks.o).

    我用的是F103ZET6的板子 移植成功后 编译出现两个错误是关于stm32f10x it c 里 void SVC Handler void void PendSV Handler void 两个函数的占用问题 随后编译出现以下两个问题
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • 13-FreeRTOS任务创建与删除

    任务创建和删除API函数位于文件task c中 需要包含task h头文件 task h里面包函数任务的类型函数 例如 对xTaskCreate的调用 通过指针方式 返回一个TaskHandle t 变量 然后可将该变量用vTaskDele
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • FreeRTOS 配置TICK_RATE_HZ

    我使用的是带有 5 4 版 FreeRTOS 的 MSP430f5438 我有一个有趣的问题 我无法弄清楚 基本上 当我将 configTICK RATE HZ 设置为不同的值时 LED 闪烁得更快或更慢 它应该保持相同的速率 我将 con
  • 使用 GCC 编译器的 ARM 内核的堆栈回溯(当存在 MSP 到 PSP 切换时)

    核心 ARM Cortex M4 编译器 GCC 5 3 0 ARM EABI 操作系统 免费 RTOS 我正在使用 gcc 库函数 Unwind Reason Code Unwind Backtrace Unwind Trace Fn v
  • 如何将 void* 转换为函数指针?

    我在 FreeRTOS 中使用 xTaskCreate 其第四个参数 void const 是传递给新线程调用的函数的参数 void connect to foo void const task params void on connect
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d

随机推荐

  • HierarchicalDataTemplate

    针对具有分层数据结构的控件设计的 比如说TreeView 相当于可以每一个层级上做DataTemplate XmlDataProvider 数据源 写在Resources下
  • Redis——缓存击穿、穿透、雪崩

    Redis的缓存击穿 穿透 雪崩 这几个概念是设计大流量接口时所需要考虑的问题 也是面试常问的Redis相关的基础知识 本篇捋一下这几个概念 做一个小结 大家都知道 计算机的瓶颈之一就是IO 为了解决内存与磁盘速度不匹配的问题 产生了缓存
  • 操作系统作业 - 内存管理 - 请求分页分配方式模拟

    内存管理 请求分页分配方式 设计方案报告 文末有源码 文章目录 内存管理 请求分页分配方式 设计方案报告 1 项目需求 1 1 基本任务 1 2 功能描述 1 3 项目目的 2 开发环境 3 项目结构 4 操作说明 5 系统分析 5 1 置
  • 洛谷题单 算法1-7 搜索

    USACO08FEB Meteor Shower S 题目描述 Bessie hears that an extraordinary meteor shower is coming reports say that these meteor
  • 【千律】C++基础:宽窄字节字符串的相互转换与控制台输出

    方案1 include
  • 怎么调节手机的刷新率_二分钟科普:手机上的“高刷新率”

    上回粗略带过屏幕刷新率 这篇将会以更简单的叙述 介绍手机屏幕刷新率和插帧 本期关键词 屏幕刷新率 FPS 插帧 正文 不纠结这是谁带节奏 进步是必然的 屏幕刷新率 通常单位为Hz 是一个硬件固定数值 例如一部手机的屏幕刷新率为120Hz 那
  • Conditional DETR spatial attention & content attention可视化(二)

    就是将attention图通过加权叠加 叠加到原图上 要通过cv2 applyColorMap 将attention的单通道图转为三通道图 将attention中一些小的值置0 不然叠加之后会干扰原图 产生色差 至于蓝色 是通过cv2 ap
  • tcp retransmission 出现的原因_TCP 协议快被淘汰了,UDP 协议才是新世代的未来?

    公众号关注 运维之美 设为 星标 每天带你玩转 Linux TCP 协议可以说是今天互联网的基石 作为可靠的传输协议 在今天几乎所有的数据都会通过 TCP 协议传输 然而 TCP 在设计之初没有考虑到现今复杂的网络环境 当你在地铁上或者火车
  • 多线程:什么是同步与异步?二者的区别

    今天看到一道面试题 同步与异步有什么区别 同步 异步 这个在我们学习多线程的时候 会接触到这个概念 后面所学的一系列多线程知识运用也是以这两个点开展的 由于学习的时候囫囵吞枣 导致我对这两个概念没法准确说出定义及其区别 现在记录一下 如果光
  • 修改主机名(/etc/hostname和/etc/hosts区别)

    ubuntu永久修改主机名 1 查看主机名 在Ubuntu系统中 快速查看主机名有多种方法 其一 打开一个GNOME终端窗口 在命令提示符中可以看到主机名 主机名通常位于 符号后 其二 在终端窗口中输入命令 hostname或uname n
  • Visual Stdio 2017 Community 中文版哪里下载方便

    嫌官网不好用的话 推荐先下一个腾讯电脑管家 腾讯电脑管家自带了软件下载中心 可以去那里获取Visual Stdio 2017 Community 具体步骤如下 1 安装腾讯电脑管家 2 打开腾讯电脑管家 点击软件管理 如图 3 搜索Visu
  • 寻找环——指针法

    一 在一条链中找环 bool judge int a 存在返回ture 否则返回false int slow 0 fast 0 do slow a slow fast a a fast while slow fast a fast 1 if
  • 嵌入式数据库-SQLite3的基本指令及用C语言操作数据库

    SQLite简介 轻量化 易用的嵌入式数据库 用于设备端的数据管理 可以理解成单点的数据库 传统服务器型数据 库用于管理多端设备 更加复杂 SQLite是一个无服务器的数据库 是自包含的 这也称为嵌入式数据库 这意味着数据库引擎作为应用程序
  • DEMO:修改外向交货单BAPI_OUTB_DELIVERY_CHANGE_SAP刘梦_新浪博客

    简单demo 交货单数量 1 然后维护上序列号 有的公司没有启用序列号就不需要了 REPORT zdemo vl02n TABLES likp lips PARAMETERS p vbeln TYPE vbeln vl PARAMETER
  • 若依源码DataScopeAspect数据权限

    目录 源代码 使用场景 代码解析 源代码 从这里可以看出 表sys role dept 的用途 之前一起不清楚 role dept关联表的含义 自定义数据权限时 DATA SCOPE CUSTOM 通过角色 可以管理哪几个部门 来实现的 A
  • qt中的setStyleSheet的基本用法(按钮的几种状态)

    参考博客 https blog csdn net qq 42250189 article details 105199339 https blog csdn net weixin 38169769 article details 99894
  • 在打印ASCII值是26的字符的时候,输出的结果不认识

    现象 解决办法 32其实是一种转义字符 后面的32是8进制的 8进制的32代表的就是2 8 0 3 8 1 结果为十进制的26 在ASCII表里边0 31个字符 开头的32个字符 以及第127个字符 最后一个字符 都是不可见的 无法显示 但
  • 封装 x-spreadsheet 带样式导入导出

    接上两篇 vue 下使用 exceljs x spreadsheet 带样式导入Excel vue 下使用 exceljs x spreadsheet 带样式导出Excel 下面封装好一个组件
  • gan与dcgan训练自己的数据集

    gan https blog csdn net weixin 50113231 article details 122959899 dcgan 源码地址 https github com carpedm20 DCGAN tensorflow
  • freertos---软定时器

    一 软件定时器介绍 freeRTOS软件定时器的时基是基于系统时钟节拍实现的 可以创建很多个 在硬件定时器资源不充足的情况下非常有用 软件定时器一般用作周期性地执行函数 在创建软件定时器时指定软件定时器的回调函数 在回调函数中实现相应的功能