STM32 | 软件定时器
01
一、概述
软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些,常见做一些简单的定时控制,如可以定时的喂狗、控灯。
在Linux、μC/OS、FreeRTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间,程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器。
02
二、配置
使能软件定时器,必须配置软件定时器的优先级、队列长度、任务堆栈大小,详细文件在FreeRTOS.h。
1、文件路径:FreeRTOS.h
/***********************************************************************FreeRTOS与软件定时器有关的配置选项 **********************************************************************///启用软件定时器#define configUSE_TIMERS0 //软件定时器优先级#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //软件定时器队列长度#define configTIMER_QUEUE_LENGTH 10 //软件定时器任务堆栈大小#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2)
03
(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;}
04
3、动态内存
若使能动态内存,则不需要上述vApplicationGetTimerTaskMemory函数原型的编写。
05
三、函数接口
1.软件定时器创建
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)。使用pdMS_TO_TICKS()可以把时间单位从 ms 转换为系统节拍周期。如果软件定时器的周期为100 个 tick,那么只需要简单的设置xTimerPeriod的值为100即可。如果软件定时器的周期为 500ms,那么xTimerPeriod应设置为pdMS_TO_TICKS(500)。宏 pdMS_TO_TICKS()只有当 configTICK_RATE_HZ 配置成小于或者等于1000HZ时才可以使用。
uxAutoReload-如果uxAutoReload设置为pdTRUE,那么软件定时器的工作模式就是周期模式,一直会以用户指定的xTimerPeriod周期去执行回调函数。如果uxAutoReload设置为pdFALSE,那么软件定时器就在用户指定的xTimerPeriod周期下运行一次后就进入休眠态(单次定时器)。
pvTimerID-软件定时器ID,数字形式。该ID典型的用法是当一个回调函数分配给一个或者多个软件定时器时,在回调函数里面根据ID号来处理不同的软件定时器。
pxCallbackFunction-软件定时器的回调函数,当定时时间到达的时候就会调用这个函数,该函数需要用户自己实现。
返回值:
成功,返回软件定时器句柄;
失败,返回NULL。
06
2.软件定时器启动
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait )
参数说明:
返回值:
成功-pdPASS。
失败-pdFAIL。
07
3.软件定时器停止
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait);
参数说明:
返回值:
成功-pdPASS。
失败-pdFAIL。
08
4.软件定时器删除
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait )
参数说明:
返回值:
成功-pdPASS。
失败-pdFAIL。
09
四、示例代码
static StackType_t TimerTaskStack[configMINIMAL_STACK_SIZE];static StaticTask_t TimerTaskTCB;void MX_FREERTOS_Init(void) {//创建周期软件定时器soft_timer_Handle=xTimerCreate((const char*)"AutoReloadTimer",(TickType_t)1000,/* 定时器周期 1000(tick) */(UBaseType_t)pdTRUE,/* 周期模式 */(void*)1,/* 为每个计时器分配一个索引的唯一ID */(TimerCallbackFunction_t)soft_timer_callback); //开启周期软件定时器xTimerStart(soft_timer_Handle,0);}static void soft_timer_callback(void* parameter){TickType_t tick_cnt;tick_cnt = xTaskGetTickCount();/* 获取滴答定时器的计数值 */printf("soft_timer_callback is running .....\r\n");printf("滴答定时器数值=%d\n", tick_cnt);}
演示