Arduino ESP32定时器功能使用
Posted perseverance52
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Arduino ESP32定时器功能使用相关的知识,希望对你有一定的参考价值。
Arduino ESP32定时器功能使用
ESP32硬件定时器介绍
ESP32 芯片包含两个硬件定时器组。每组有两个通用硬件定时器。它们都是基于 16 位预分频器和 64 位自动重载功能的向上/向下计数器的 64 位通用定时器。
- 初始化(开启)定时器 timerBegin
hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){}
参数:timer(选择定时器):0-3 divider(分频系数):0-65536 countUp:是否为向上计数
num : 定时器编号
divider:分频数
countUp: 是否是累加模式
返回值:
返回一个计时器结构体指针 hw_timer_t * ,我们预定义一个指针接收它
hw_timer_t* tim1= NULL;
tim1 = timerBegin(0,80,true); //80MHZ, ESP32主频80MHz
- 详细配置定时器
void timerSetConfig(hw_timer_t *timer, uint32_t config);
uint32_t timerGetConfig(hw_timer_t *timer);
- 取消初始化定时器 timerEnd
void timerEnd(hw_timer_t *timer)
参数:*timer : 目标定时器 ( 计时器结构体指针 hw_timer_t * )
- 开启定时器中断 timerAttachInterrupt
void timerAttachInterrupt(hw_timer_t timer, void (fn)(void), bool edge){}
参数:*timer : 目标定时器 ( 计时器结构体指针 hw_timer_t * )
void (*fn)(void) : 中断函数入口地址
中断边沿触发 : 是否跳变沿触发中断 定时器中断触发方式有: 电平触发中断(level type) 边缘触发中断(edge type)
timerAttachInterrupt(tim1,tim1Interrupt,true);
- 取消定时器中断 timerDetachInterrupt
void timerDetachInterrupt(hw_timer_t *timer)
- 配置报警计数器保护值timerAlarmWrite
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload){}
timer:目标定时器 interruptAt:报警保护值 autoreload:是否开启自动重载
参数:*timer : 目标定时器 ( 计时器结构体指针 hw_timer_t * )
alarm_value : 计数上限值,单位:微秒
autoreload : 是否重装载.
timerAlarmWrite(tim1, 100000, true);
- 使能定时器报警timerAlarmEnable
void timerAlarmEnable(hw_timer_t *timer){}
参数:*timer : 目标定时器 ( 计时器结构体指针 hw_timer_t * )
timerAlarmEnable(tim1);
- 失能定时器 timerAlarmDisable
void timerAlarmDisable(hw_timer_t *timer)
- 判断定时器是否启动 timerAlarmEnabled
bool timerAlarmEnabled(hw_timer_t *timer)
Serial.println(timerAlarmEnabled(tim1));
定时器配置步骤
- 选择定时器(两组四个)
- 配置合适分频系数
- 绑定中断函数
- 配置报警计数器保护值
- 开启报警
定时器定时10秒触发一次
#include <Arduino.h>
hw_timer_t *tim1 = NULL;
int tim1_IRQ_count = 0;
void tim1Interrupt()
{//中断服务函数
Serial.println("haha");
tim1_IRQ_count++;
Serial.println(timerAlarmEnabled(tim1));
}
void setup()
{
Serial.begin(115200);
tim1 = timerBegin(0, 80, true);
timerAttachInterrupt(tim1, tim1Interrupt, true);
timerAlarmWrite(tim1, 100000ul, true);
timerAlarmEnable(tim1);
}
void loop()
{
if (tim1_IRQ_count > 10)
{//相当于一秒触发一次
Serial.println("定时器触发");
tim1_IRQ_count = 0;
}
}
定时器计数,通过按键取消定时器功能示例
当按键(D4–GPIO4),按下,电平拉低,即触发取消定时器功能。
/*
重复计时器(定时器可以通过连接到 D4 的按钮停止)
接线说明: 按键接4
注意:按键(D4————GPIO4)一定要设置为输入上拉,经测试,设置为普通的输入,和电平置高不行。
*/
//停止按钮连接到 PIN 0 (IO0)
#define BTN_STOP_ALARM (4)
hw_timer_t * timer = NULL;
volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
volatile uint32_t isrCounter = 0;
volatile uint32_t lastIsrAt = 0;
void IRAM_ATTR onTimer() {
// 增加计数器并设置 ISR 的时间
portENTER_CRITICAL_ISR(&timerMux);
isrCounter++;
lastIsrAt = millis();
portEXIT_CRITICAL_ISR(&timerMux);
// 给出一个我们可以在循环中检查的信号量
xSemaphoreGiveFromISR(timerSemaphore, NULL);
// 如果要切换输出,在此处使用数字读/写是安全的
}
void setup() {
Serial.begin(115200);
// 将 BTN_STOP_ALARM 设置为输入上拉模式
pinMode(BTN_STOP_ALARM, INPUT_PULLUP);//一定要设置为输入上拉,经测试,设置为普通的输入,和电平置高不行。
// 创建信号量以在计时器触发时通知我们
timerSemaphore = xSemaphoreCreateBinary();
// 使用 4 的第一个计时器(从零开始计数)。
// 为预分频器设置 80 分频器(更多信息请参见 ESP32 技术参考手册)信息)。
timer = timerBegin(0, 80, true);
// 将计时器功能附加到我们的计时器。
timerAttachInterrupt(timer, &onTimer, true);
// 定时器设置
//每秒调用一次 onTimer 函数(值以微秒为单位)。
// 是否重装载,重复闹钟(第三个参数)
timerAlarmWrite(timer, 1000000ul, true);
// 使能定时器
timerAlarmEnable(timer);
}
void loop() {
//如果计时器已触发
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE) {
uint32_t isrCount = 0, isrTime = 0;
// 读取中断计数和时间
portENTER_CRITICAL(&timerMux);
isrCount = isrCounter;
isrTime = lastIsrAt;
portEXIT_CRITICAL(&timerMux);
//打印出来
Serial.print("onTimer no. ");
Serial.print(isrCount);
Serial.print(" at ");
Serial.print(isrTime);
Serial.println(" ms");
}
// 如果按钮被按下
if (digitalRead(BTN_STOP_ALARM) == LOW) {
Serial.println("取消计数,Stoping");
// 如果计时器仍在运行
if (timer) {
// 停止并释放计时器
timerEnd(timer);
timer = NULL;
}
}
}
以上是关于Arduino ESP32定时器功能使用的主要内容,如果未能解决你的问题,请参考以下文章
使用Arduino开发ESP32(07):系统时间和定时任务调度器Ticker
我在使用esp32在arduino中执行简单任务时遇到此看门狗定时器错误