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));

定时器配置步骤

  1. 选择定时器(两组四个)
  2. 配置合适分频系数
  3. 绑定中断函数
  4. 配置报警计数器保护值
  5. 开启报警

定时器定时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 看门狗定时器

Arduino框架下 ESP32看门狗使用示例

使用Arduino开发ESP32(07):系统时间和定时任务调度器Ticker

我在使用esp32在arduino中执行简单任务时遇到此看门狗定时器错误

玩转 ESP32 + Arduino (六) 硬件定时器, IIC, SPI

Arduino ESP32:使用 ledcWrite 函数淡入淡出LED