单片机,FreeRtos操作系统软件定时器(Software Timer)原理及其应用!!!

前言:本文参考,韦东山开发文档,连接放在最后

基本概念理解

软件定时器 (Software Timer),类似于闹钟,当规定的时间到来时,提醒你,去完成某件事情,闹钟提醒我们的事情,可以是每天重复性的任务,也可以是只执行一次的任务。将功能带入到软件定时器,得到定义,软件定时器(Software Timer)是一个定时机制,允许任务或函数在特定时间间隔后被执行。软件定时器的核心功能是延时和周期性执行任务。

需要注意的是,软件定时器 (Software Timer)是依靠FreeRtos操作系统的,系统滴答中断(Tick Interrupt)来运行的,这里系统滴答中断提供的是软件定时器(Software Timer)判断时间的标准。

同样的软件定时器(Software Timer)因为功能不同也被分为 一次性定时器 和周期性定时器概念如下所示。

一次性定时器:当达到设定时间时触发一次并停止

周期性定时器:当达到设定时间周期间隔,就会重复触发,知道手动停止定时器

在概念中最重要的一点是,因为FreeRtos是操作系统(RTOS),要求任务的并发性,并发性也就是任务的同时执行是通过中断函数来切换的,这里也就是通过系统滴答中断(Tick Interrupt)的中断函数来切换的,这个函数中不能放入执行时间不确定的程序,回影响系统切换任务,也就是影响并发性,因此,软件定时器 (Software Timer)的执行函数会系统内核中调用函数,通过函数来读写 RTOS command queue 在系统内核中通过去读队列的数值,来在普通任务上下文调用不同的函数, RTOS守护 任务 (RTOS Damemon Task)在普通任务的上下文执行,从而避免在中断中执行时间不确定的操作。

RTOS守护 任务 (RTOS Damemon Task)的调度和普通任务的调度,没有什么区别,同样需要遵守任务的优先级规则。这里需要注意的是,软件定时器在创建过后,并不会启动,需要调用函数来启动软件定时器。

如果软件定时器在创建之后,没用使用函数调用,这个时候本身的状态是 **冬眠(Dormant)**状态,是不能够正常相应的。

函数原型

软件定时器(Software Timer)的创建也分为动态创建和静态创建,同时创建成功之后,返回控制句柄函数原型如下。

动态创建

cpp 复制代码
TimerHandle_t xTimerCreate( const char * const pcTimerName,const TickType_t xTimerPeriodInTicks,const UBaseType_t uxAutoReload,void * const pvTimerID,TimerCallbackFunction_t pxCallbackFunction );

静态创建

cpp 复制代码
TimerHandle_t xTimerCreate( const char * const pcTimerName,const TickType_t xTimerPeriodInTicks,const UBaseType_t uxAutoReload,void * const pvTimerID,TimerCallbackFunction_t pxCallbackFunction,StaticTimer_t *pxTimerBuffer );

|---------------------------------------------|--------------------------------|
| const char * const pcTimerName | 填定时器的名字 |
| TickType_t xTimerPeriodInTicks, | 填软件定时器执行周期,以Tick为单位 |
| UBaseType_t uxAutoReload, | pdTRUE代表为周期性定时器 pdFALSE 一次性定时器 |
| void * pvTimerID | 回调函数可以使用此参数, 比如分辨是哪个定时器 |
| TimerCallbackFunction_t pxCallbackFunction, | 填软件定时器执行函数 |
| StaticTimer_t *pxTimerBuffer | 回调函数可以使用此参数, 比如分辨是哪个定时器 |

创建软件定时器

cpp 复制代码
static TimerHandle_t g_TimerSound;
void GameSoundTimer_Func(void)
{
}
g_TimerSound = xTimerCreate("GameSound",200,pdFALSE,NULL,GameSoundTimer_Func);

首先需要声明一个句柄,然后声明或者找到,软件定时器的执行函数,选择软件定时器为周期性定时器或者一次性定时器,这里200个Tick可以看成200ms,来对待,还有给软件定时器七一给名字,基本上创建函数需要填写的参数就这么多。

启动/停止软件定时器

启动软件定时器 (Software Timer)就是将他的状态改变为 运行态 (Running、Active),而停止软件定时器 (Software Timer)就是对应的将状态改为 **冬眠(**Dormant) ,在这个状态软件定时器不能运行。

启动软件定时器

cpp 复制代码
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken );

这个参数分为在普通任务上下文使用,和在中断任务上下文使用,参数有一位不同,具体参数填写见下表格。

|---------------------------------------|----------------------------------------------------------------|
| TimerHandle_t xTimer | 填写作用定时器的句柄 |
| TickType_t xTicksToWait | 如果 command queue队列已满等待的时间 |
| BaseType_t*pxHigherPriorityTaskWoken | pdFALSE当前没有更高优先级的任务需要运行。 pdTrue 有更高优先级的任务在ISR结束时需要切换任务 |

当调用启动函数的时候,软件定时器状态会从冬眠( Dormant)转变为 运行态(Running、Active),从而去运行任务。

停止软件定时器

调用停止函数会使,软件定时器 (Software Timer)从 运行态 (Running、Active)停止转变为**冬眠(**Dormant)状态,从而停止定时器的功能。

cpp 复制代码
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );
BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, BaseType_t *pxHigherPriorityTaskWoken );

|---------------------------------------|----------------------------------------------------------------|
| TimerHandle_t xTimer | 填写作用定时器的句柄 |
| TickType_t xTicksToWait | 如果 command queue队列已满等待的时间 |
| BaseType_t*pxHigherPriorityTaskWoken | pdFALSE当前没有更高优先级的任务需要运行。 pdTrue 有更高优先级的任务在ISR结束时需要切换任务 |

cpp 复制代码
static TimerHandle_t g_TimerSound;

void GameSoundTimer_Func(void)
{
}

g_TimerSound = xTimerCreate("GameSound",200,pdFALSE,NULL,GameSoundTimer_Func);

xTimerStart( g_TimerSound, 0);//开启软件定时器,如果阻塞就不等待

xTimerStop( g_TimerSound, 0);//关闭软件定时器,如果 command queue 队列阻塞不等待

改变软件定时器周期

这里软件定时器在创建的时候,需要声明定时器周期,如果在后续-程序中,需要改变软件定时器的周期可以通过这个函数来改变周期,也就是执行时间,同时这里需要注意的是,这个函数也可以让软件定时器从冬眠( Dormant)转变为 运行态(Running、Active)。

当在软件定时器工作时调用,假设此时时间为tX,调用修改新的周期时间为y,那么软件定时器调用函数去响应的时间就是,tX+y,调用函数之前的时间不会计入新的软件定时器周期内。

函数原型

cpp 复制代码
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,TickType_t xNewPeriod,TickType_t xTicksToWait );

|-------------------------|----------------------|
| TimerHandle_t xTimer | 填写改变定时器周期的句柄 |
| TickType_t xNewPeriod | 填写新的定时器周期 |
| TickType_t xTicksToWait | 等待 command queue超时时间 |

cpp 复制代码
static TimerHandle_t g_TimerSound;

void GameSoundTimer_Func(void)
{
}

g_TimerSound = xTimerCreate("GameSound",200,pdFALSE,NULL,GameSoundTimer_Func);

xTimerChangePeriod(g_TimerSound,400,0);//更改定时器周期为400

xTimerStart( g_TimerSound, 0);//开启软件定时器,如果阻塞就不等待

xTimerStop( g_TimerSound, 0);//关闭软件定时器,如果 command queue 队列阻塞不等待

软件定时器复位函数

当在软件定时器工作时调用,假设此时时间为tX,周期时间为n,那么软件定时器调用函数去响应的时间就是 tX+n, 这个函数也可以让软件定时器从冬眠( Dormant)转变为 运行态(Running、Active)。

函数原型

cpp 复制代码
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );

|-------------------------|----------------------|
| TimerHandle_t xTimer | 填写改变定时器周期的句柄 |
| TickType_t xTicksToWait | 等待 command queue超时时间 |

cpp 复制代码
static TimerHandle_t g_TimerSound;

void GameSoundTimer_Func(void)
{
}

g_TimerSound = xTimerCreate("GameSound",200,pdFALSE,NULL,GameSoundTimer_Func);

xTimerChangePeriod(g_TimerSound,400,0);//更改定时器周期为400
xTimerReset( g_TimerSound,0 );//复位软件定时器,等待时间为0

xTimerStart( g_TimerSound, 0);//开启软件定时器,如果阻塞就不等待

xTimerStop( g_TimerSound, 0);//关闭软件定时器,如果 command queue 队列阻塞不等待

程序实现调用

cpp 复制代码
static TimerHandle_t g_TimerSound;

void GameSoundTimer_Func(TimerHandle_t xTimer)
{
	PassiveBuzzer_Control(0);

}

int Buzzer_Init(void)
{
	//初始化蜂鸣器
  PassiveBuzzer_Init();
	//创建软件定时器
	g_TimerSound = xTimerCreate("GameSound",200,pdFALSE,NULL,GameSoundTimer_Func);	
}
void Buzzer_buzz(int freq ,int time_ms)
{
	PassiveBuzzer_Set_Freq_Duty(freq, 50);
	//启动软件定时器停止声音
	xTimerChangePeriod(g_TimerSound,time_ms,0);	
}

欢迎指正,希望对你,有所帮助!!!

相关推荐
Jumbuck_101 小时前
基于OpenMV+STM32+OLED与YOLOv11+PaddleOCR的嵌入式车牌识别系统开发笔记
笔记·stm32·嵌入式硬件
小智学长 | 嵌入式5 小时前
单片机-89C51部分:4、固件烧录
c语言·单片机·嵌入式硬件
时之彼岸Φ5 小时前
Adruino:传感器及步进电机
单片机·嵌入式硬件
少年、潜行6 小时前
【开源】基于51单片机的简易智能楼道照明设计
单片机·嵌入式硬件·51单片机
子朔不言6 小时前
MH2103 MH22D3系列的JTAG/SWD复用功能和引脚映射,IO初始化的关键点
单片机·mcu·mh2103·mh22d3·新龙微·兆讯
国科安芯6 小时前
基于先进MCU的机器人运动控制系统设计:理论、实践与前沿技术
人工智能·单片机·机器人
honey ball6 小时前
为啥低速MCU单板辐射测试会有200M-1Ghz的辐射信号
单片机·嵌入式硬件
憧憬一下7 小时前
stm32之EXIT外部中断详解
stm32·单片机·嵌入式·中断
小猪写代码7 小时前
嵌入式硬件开发工具---万用表---示波器---仿真器
单片机·嵌入式硬件
精彩漂亮ing8 小时前
基于外部中中断机制,实现以下功能: 1.按键1,按下和释放后,点亮LED 2.按键2,按下和释放后,熄灭LED 3.按键3,按下和释放后,使得LED闪烁
单片机·嵌入式硬件