除了ESP-IDF中的软硬件定时器,我们还可以使用FreeRTOS中的软件定时器,它是基于Tick的定时器。不过我一般不用,因为有ESP-IDF的定时器了嘛,但还是介绍一下。
首先包含头文件。
#include "freertos/timers.h"
接着我们创建一个定时器。
TimerHandle_t xTimerCreate(const char *const pcTimerName, const TickType_t xTimerPeriodInTicks, const BaseType_t xAutoReload, void *const pvTimerID, TimerCallbackFunction_t pxCallbackFunction)
第一个参数我们传入字符串表示这个定时器的名称,名称没什么用随便叫就行。
第二个参数传入Tick时钟周期数来表示定时器的周期。
第三个参数设置是否为循环定时器,给pdTRUE为循环的,给pdFALSE为一次性的定时器。
第四个参数我们传入一个void*的指针,但是这个不是传出参数,而是传入参数,我们来给定时器分配ID,不需要的话可以给个NULL。官方是说定时器的ID可以在定时器的回调函数里区分具体是哪个定时器,因为多个定时器可以共用同一个回调函数。
最后一个给定时器设置回调函数。
回调函数要无返回值,有一个定时器句柄类型的参数。
创建成功之后返回定时器句柄,此时这个定时器处于休眠状态,我们还需要将它开启。
使用下面这个宏。
xTimerStart(xTimer, xTicksToWait)
传入定时器句柄和一个等待时间,单位为时钟周期TickType_t。因为有个定时器命令队列,我们不一定可以马上打开指定的定时器,因此有个等待时间。
除了上面这个,还有个中断版本的,函数名后加个FromISR,这边就不介绍了。
开启之后我们还可以暂停。
xTimerStop(xTimer, xTicksToWait)
参数一样是定时器句柄和等待时间。
还有个重启定时器。
xTimerReset(xTimer, xTicksToWait)
如果重启之前定时器已经暂停,那么开启定时器。
如果重启之前定时器已经开启,那么重置计数时间。
另外如果开启定时器的时候定时器已经开启,那么等同于重启。
我们可以使用下面这个函数来判断定时器处于什么状态。
BaseType_t xTimerIsTimerActive(TimerHandle_t xTimer)
如果处于休眠状态,那么返回pdFALSE,否则返回非pdFALSE之外的值。
还有个删除定时器的宏。
xTimerDelete(xTimer, xTicksToWait)
有上面几个函数基本上就够用了,不过我再贴一些函数出来吧。
void *pvTimerGetTimerID(const TimerHandle_t xTimer)
返回分配给定时器的ID。
const char *pcTimerGetName(TimerHandle_t xTimer)
返回创建定时器时设置的名字。
上面俩可以用来调试,也可以用于区分使用同一个回调函数的不同的定时器,因为定时器的回调函数的参数只有一个定时器句柄,通过定时器句柄可以使用上面俩函数获取到定时器的信息。
下面这个宏可以修改定时器的周期。
xTimerChangePeriod(xTimer、xNewPeriod、xTicksToWait)
关于定时器的函数还蛮多的,在使用的时候可以去官方文档里查,接下来来个小例子简单演示一下定时器。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
TimerHandle_t timer1Handle, timer2Handle;
void timer1Callback(TimerHandle_t xTimer) {
printf("this is timer1\r\n");
}
void timer2Callback(TimerHandle_t xTimer) {
xTimerStop(timer1Handle, pdMS_TO_TICKS(100));
xTimerDelete(timer1Handle, pdMS_TO_TICKS(100));
}
void app_main(void) {
int32_t timer1Id = 0, timer2Id = 1;
timer1Handle = xTimerCreate("timer1", pdMS_TO_TICKS(300), pdTRUE,(void*)&timer1Id, timer1Callback);
timer2Handle = xTimerCreate("timer2", pdMS_TO_TICKS(3000), pdFALSE,(void*)&timer2Id, timer2Callback);
xTimerStart(timer1Handle, pdMS_TO_TICKS(100));
xTimerStart(timer2Handle, pdMS_TO_TICKS(100));
TickType_t curTime = xTaskGetTickCount();
while (1) {
printf("this is main\r\n");
xTaskDelayUntil(&curTime, pdMS_TO_TICKS(1000));
}
}
示例很简单,就是开俩定时器,一个周期的,一个一次性的,周期定时器打印一段话,一次性定时器关闭周期定时器。