1.开发背景
基于以上的章节,这个篇章主题是软件定时器使用,能使用 FreeRTOS 的基本都是从裸机 MCU 过来的,基本都知道 MCU 最基本的功能之一就是定时器,确切的说是硬件定时器,外围电路已经构建好的,精度很高,基本都是微秒级别定时,稳定性也不错,唯一的缺点就是资源太少,定时器的数目有限。
于是 FreeRTOS 从线程中衍生出了软件定时器的概念,用于一般精度的定时操作,即毫秒级定时。由于 FreeRTOS 内核自身的就是依靠一个定时器打节拍而运行的,本身是没有锁相环的,软件定时器的实现依托的是线程(prvTimerTask),实现机制如下。
既然实现的方式是线程,那就必须配置线程的参数,例如线程优先级考核堆栈大小,定时器的回调函数实际是运行在定时器线程中的,注意堆栈大小,如果想要定时器回调快速响应就需要提高优先级。也正由于定时器处理实在线程中,所以定时器回调不能阻塞,否则影响其他定时器。
事实上,FreeRTOS 创建多个定时器也是使用同一个定时器线程,这就意味着需要引入队列,这个就需要配置队列的最大长度。
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY 5
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)
2.开发需求
设计实验:
1)创建 1 个单次定时器,1 个自动重载定时器
2)2 个定时器同时启动,在定时器回调中输出对应日志
3)观察现象
3.开发环境
window10 + MDK + STM32F429 + FreeRTOS10.3.1
4.实现步骤
4.1 实现编码
#include "appTest.h"#include <stdio.h>
#include <string.h>
#include <stdlib.h>#include "mspDwt.h"
#include "mspGpio.h"
#include "mspExti.h"#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stream_buffer.h"#include "appLog.h"/*#define configUSE_TIMERS 1#define configTIMER_TASK_PRIORITY 1#define configTIMER_QUEUE_LENGTH 10#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)
*/typedef struct
{/* 定时器句柄 */TimerHandle_t timerSingle; // 单次TimerHandle_t timerAutoLoad; // 自动加载}Ctrl_t;/* 文件指针 */
static Ctrl_t s_ctrl = {0};
static Ctrl_t *p = &s_ctrl;/* 定时器回调 */
void vTimerCallback_Single(TimerHandle_t pxTimer)
{Log_Debug("%s\r\n", __func__);
}void vTimerCallback_AutoLoad(TimerHandle_t pxTimer)
{Log_Debug("%s\r\n", __func__);
}/* 测试初始化 */
void aTest_Init(void)
{/* 创建定时器任务 */TickType_t xTimerPeriodInTicks = 1000; // 定时时长UBaseType_t uxAutoReload = pdFALSE;p->timerSingle = xTimerCreate("vTimerCallback_Single", xTimerPeriodInTicks,uxAutoReload, NULL, vTimerCallback_Single);uxAutoReload = pdTRUE;p->timerAutoLoad = xTimerCreate("vTimerCallback_AutoLoad", xTimerPeriodInTicks,uxAutoReload, NULL, vTimerCallback_AutoLoad);/* 启动定时器 */xTimerStart(p->timerSingle, 1000);xTimerStart(p->timerAutoLoad, 1000);
}/* Key2 PC13 Key0 PH3 Key1 PH2 */
void Exti13_TriggerInterrupt(void)
{mspExti_Close(13);if (mspGpio_GetInput("PC13") == 0){}
}
4.2 结果显示
注意查看的是,打圈的就是软件定时器控制线程
4.3 常用接口
xTimerStart() // 启动定时器
xTimerStop() // 停止定时器
xTimerChangePeriod() // 修改定时周期
xTimerReset() // 定时器复位