有关定时器外设的详细介绍在ESP-IDF的对应文章中,跳转栏目目录可以找到。
1. API
1.1 启动定时器
hw_timer_t * timerBegin(uint8_t timer, uint16_t divider, bool countUp);
- timer:定时器序号(ESP32有4个硬件定时器,所以可填序号0-3);
- divider:预分频器,定时器频率 = APB频率 / 预分频器值,APB时钟频率默认为80MHz;
- countUp:选择向上计数还是向下计数。
函数会返回一个硬件定时器句柄。
1.2 关闭定时器
void timerEnd(hw_timer_t *timer);
- timer:定时器句柄。
1.3 设置定时器中断回调
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
- timer:定时器句柄;
- fn:回调函数指针;
- edge:边沿触发(ESP32不支持,默认失能即可)。
1.4 设置定时器闹钟
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload);
- timer:定时器句柄;
- alarm_value:闹钟超时值,触发时间 = (1 / 定时器频率) * 闹钟超时值;
- autoreload:是否重装载,为真时闹钟可以连续触发。
1.5 使能定时器闹钟
void timerAlarmEnable(hw_timer_t *timer);
- timer:定时器句柄。
1.6 关闭定时器闹钟
void timerAlarmDisable(hw_timer_t *timer);
- timer:定时器句柄。
2. 例程
这个例程实现一个间隔为1秒的定时器闹钟。
#include <Arduino.h>
hw_timer_t *timer = NULL;
SemaphoreHandle_t sem;
void ARDUINO_ISR_ATTR timeoutCb()
{
BaseType_t higherTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(sem, &higherTaskWoken);
if (higherTaskWoken) {
portYIELD_FROM_ISR();
}
}
void setup()
{
Serial.begin(115200);
/* 初始化定时器 */
sem = xSemaphoreCreateBinary();
timer = timerBegin(0, 80, true); // 时钟频率 = 80MHz / 80 = 1MHz
timerAttachInterrupt(timer, timeoutCb, false);
timerAlarmWrite(timer, 1000000, true); // 闹钟频率 = (1 / 1MHz) * 1000000 = 1s
timerAlarmEnable(timer);
}
void loop()
{
if (pdTRUE == xSemaphoreTake(sem, portMAX_DELAY)) {
Serial.println("Timer timeout");
}
}
因为中断回调里面是不能调用打印函数的,所以例程中使用一个二值信号量来实现,回调函数内释放信号量,然后主循环中获取信号量,成功获取后打印信息。