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;
volatile unsigned int tim1_IRQ_count = 0;
 
void Tim1Interrupt()
{//中断服务函数

  tim1_IRQ_count++;
  //Serial.println(timerAlarmEnabled(tim1));//不推荐放打印信息,容易造成看门狗溢出,引发esp32产生强制复位
}
 
void setup()
{
  Serial.begin(115200);
  tim1 = timerBegin(0, 80, true);
  timerAttachInterrupt(tim1, Tim1Interrupt, true);
  timerAlarmWrite(tim1, 100000ul, true);//100ms进一次中断
  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定时器功能涉及初始化硬件定时器并设置回调函数来处理定时事件。下面介绍一种基于`hw_timer`库的方法,该库允许开发者创建精确的时间间隔触发特定的任务执行。 为了简化操作流程,在程序启动阶段完成必要的设定工作是重要的[^1]: ```cpp #include "esp_timer.h" #define INTERVAL_US 500000 // 设置时间间隔为500,000微秒即每半秒钟一次 // 声明全局变量用于存储一次性或周期性定时器句柄 static esp_timer_handle_t periodic_timer; void timer_callback(void* arg){ Serial.println("Timer triggered!"); } void setup(){ // 初始化串口通信以便打印调试信息 Serial.begin(115200); const esp_timer_create_args_t periodic_timer_args = { .callback = &timer_callback, /* 此处可以传递参数给回调函数 */ .arg = NULL, .name = "periodic", .dispatch_method=ESP_TIMER_TASK }; // 创建一个周期性的计时器实例 ESP_ERROR_CHECK( esp_timer_create(&periodic_timer_args, &periodic_timer) ); } ``` 上述代码展示了如何定义一个名为`timer_callback`的简单回调函数以及通过调用`esp_timer_create()`函数创建了一个新的定时器对象,并将其指派给了静态变量`periodic_timer`。这里还设置了每次触发时所要运行的具体逻辑——向控制台输出一条消息表示定时器被激活了[^1]。 接下来的部分负责实际开启这个定时机制,这通常是在`setup()`之后由另一个独立的功能模块实现,比如按下按钮或者接收到某些网络指令等场景下才会去启动它;不过在这里直接放在`loop()`里作为演示用途也是完全可以接受的做法[^1]: ```cpp void loop() { static bool started = false; if (!started){ ESP_ERROR_CHECK( esp_timer_start_periodic(periodic_timer,INTERVAL_US)); started=true; } } ``` 这段脚本确保了一旦进入主循环体内部就会立即尝试启动之前建立好的周期型定时装置,并且只做这一次而已因为状态标志位会在成功后立刻翻转过来阻止后续重复动作的发生[^1]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值