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

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

相关推荐
云山工作室2 小时前
基于物联网的风机故障检测装置的设计与实现
单片机·物联网·毕业设计·毕设
小关1232 小时前
STM32补充——IAP
stm32·单片机·嵌入式硬件
呆呆珝2 小时前
RKNN_C++版本-YOLOV5
c++·人工智能·嵌入式硬件·yolo
十月旧城3 小时前
51单片机入门_01_单片机(MCU)概述(使用STC89C52芯片)
单片机·嵌入式硬件·51单片机
马浩同学6 小时前
【ESP32】ESP-IDF开发 | WiFi开发 | TCP传输控制协议 + TCP服务器和客户端例程
c语言·网络·单片机·mcu·tcp/ip
单片机社区6 小时前
随笔十六、音频采集、UDP发送
嵌入式硬件·udp·音视频·泰山派
promising-w8 小时前
单片机基础模块学习——按键
单片机·嵌入式硬件·学习
嵌联驰10 小时前
【S32K3 RTD LLD篇7】K344中心对齐PWM中心点触发ADC BCTU采样
单片机·嵌入式硬件
stm32发烧友16 小时前
基于 STM32 的智能农业温室控制系统设计
stm32·单片机·嵌入式硬件
嵌入式新人菜鸟17 小时前
单片机-STM32 WIFI模块--ESP8266 (十二)
c语言·stm32·单片机