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

版权声明:本文为CSDN博主「perseverance52」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42880082/article/details/120882798

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

版权声明:本文为CSDN博主「perseverance52」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42880082/article/details/120882798

生成海报
点赞 0

perseverance52

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

Arduino ESP32定时器功能使用

Arduino ESP32定时器功能使用ESP32硬件定时器介绍 ESP32 芯片包含两个硬件定时器组。每组有两个通用硬件定时器。它们都是基于 16 位预分频器和 64 位自动重载功能的向上/向下计数器的 64 位通用定时器。 初始化&#xff

74HC138译码器的原理和使用

前言 译码器就是将每个输入的二进制代码译成对应的输出高低电平信号,和编码器互为逆过程。 百度百科 74HC138是一款高速CMOS器件,74HC138引脚兼容低功耗肖特基TTL(LSTTL&#xf

ESP32-GY_30光照强度传感器

GY_30光照强度传感器介绍 GY-30光强传感器特点及使用介绍 一、连接引脚 GY_30光照强度传感器使用I2C传输数据 。 5根引脚,名称与功能如下; vcc 为外接供电电源输入端 GND 地线 SCL I2C通信模式时钟