软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器(systick)模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些,常见做一些简单的定时控制,如可以定时的喂狗、控灯。
在Linux、μC/OS、FreeRTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间,程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器。
使能软件定时器,必须配置软件定时器的优先级、队列长度、任务堆栈大小,详细文件在FreeRTOS.h。
1、文件路径:FreeRTOS.h
/***********************************************************************
FreeRTOS与软件定时器有关的配置选项
**********************************************************************/
//启用软件定时器
#define configUSE_TIMERS 1
//软件定时器优先级
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1)
//软件定时器队列长度
#define configTIMER_QUEUE_LENGTH 10
//软件定时器任务堆栈大小
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2)
2、静态内存
(1)使能静态内存
#define configSUPPORT_STATIC_ALLOCATION 0
(2)增加vApplicationGetTimerTaskMemory函数原型
static StackType_t TimerTaskStack[configMINIMAL_STACK_SIZE];
static StaticTask_t TimerTaskTCB;
//定时器任务所需内存
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
{
*ppxTimerTaskTCBBuffer=&TimerTaskTCB;
*ppxTimerTaskStackBuffer=TimerTaskStack;
*pulTimerTaskStackSize=configMINIMAL_STACK_SIZE;
}
3、动态内存
若使能动态内存,则不需要上述vApplicationGetTimerTaskMemory函数原型的编写。
TimerHandle_t xTimerCreate(const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction )
参数说明:
-pcTimerName-软件定时器名字,文本形式,纯粹是为了调试,
FreeRTOS 使用定时器是通过其句柄,而不是使用其名字。
-xTimerPeriodInTicks-软件定时器的周期,单位为系统节拍周期(即 tick 1ms)。
如果软件定时器的周期为100 个 tick,那么只需要简单的设置xTimerPeriod的值为100即可。
-uxAutoReload-如果uxAutoReload设置为pdTRUE,那么软件定时器的工作模式就是周期模式,
一直会以用户指定的xTimerPeriod周期去执行回调函数。
如果uxAutoReload设置为pdFALSE,那么软件定时器就在用户指定的xTimerPeriod周期下运行一次后就进入休眠态(单次定时器)。
-pvTimerID-软件定时器ID,数字形式。该ID典型的用法是当一个回调函数分配给一个或者多个软件定时器时,
在回调函数里面根据ID号来处理不同的软件定时器。
-pxCallbackFunction-软件定时器的回调函数,当定时时间到达的时候就会调用这个函数,
该函数需要用户自己实现。
返回值:
成功,返回软件定时器句柄;
失败,返回NULL。
//eg:时间:1000*系统节拍(1ms)= 1s,参数的2可随机数
my_Time = xTimerCreate("Time", 1000, pdTRUE, "2", TimerCallbackFunction);
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait )
参数说明:
-xTimer-软件定时器句柄。
-xTicksToWait-用户指定超时阻塞时间,单位为系统节拍周期(即tick)。
调用xTimerStart()的任务将被锁定在阻塞态,在软件定时器把启动的命令成功发送到定时器命令队列之前。
如果在FreeRTOS调度器开启之前调用xTimerStart(),形参将不起作用。
返回值:
成功-pdPASS。
失败-pdFAIL。
eg:
//启动定时器 0:马上启动
xTimerStart( my_Time, 0 );
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait);
参数说明:
-xTimer-软件定时器句柄。
-xTicksToWait-用户指定超时阻塞时间,单位为系统节拍周期(即tick)。
调用xTimerStart()的任务将被锁定在阻塞态,在软件定时器把启动的命令成功发送到定时器命令队列之前。
如果在FreeRTOS调度器开启之前调用xTimerStart(),形参将不起作用。
返回值:
成功-pdPASS。
失败-pdFAIL。
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );
参数说明:
-xTimer-软件定时器句柄。
-xTicksToWait-用户指定超时阻塞时间,单位为系统节拍周期(即tick)。
调用xTimerStart()的任务将被锁定在阻塞态,在软件定时器把启动的命令成功发送到定时器命令队列之前。
如果在FreeRTOS调度器开启之前调用xTimerStart(),形参将不起作用。
返回值:
成功-pdPASS。
失败-pdFAIL。
代码例子:
https://download.csdn.net/download/m0_63622771/90897118