单片机,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);	
}

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

相关推荐
基极向上的三极管41 分钟前
【AD】3-4 在原理图中放置元件
嵌入式硬件
徐嵌1 小时前
STM32项目---水质水位检测
stm32·单片机·嵌入式硬件
徐嵌1 小时前
STM32项目---畜牧定位器
c语言·stm32·单片机·物联网·iot
lantiandianzi1 小时前
基于单片机的老人生活安全监测系统
单片机·嵌入式硬件·生活
东胜物联1 小时前
探寻5G工业网关市场,5G工业网关品牌解析
人工智能·嵌入式硬件·5g
stm32发烧友2 小时前
基于STM32的智能家居环境监测系统设计
stm32·嵌入式硬件·智能家居
hairenjing11239 小时前
使用 Mac 数据恢复从 iPhoto 图库中恢复照片
windows·stm32·嵌入式硬件·macos·word
模拟IC攻城狮11 小时前
华为海思招聘-芯片与器件设计工程师-模拟芯片方向- 机试题-真题套题题目——共8套(每套四十题)
嵌入式硬件·华为·硬件架构·芯片
IT B业生11 小时前
51单片机教程(六)- LED流水灯
单片机·嵌入式硬件·51单片机
一枝小雨11 小时前
51单片机学习心得2(基于STC89C52):串口通信(UART)
单片机·嵌入式硬件·51单片机