ESP32开发——关于ESP32TimerInterrupt库的例程分析

最近在学习嵌入式开发的内容,正好有一个开发任务涉及到对于定时器中断的使用,今天正好找到了这个相关的库:ESP32TimerInterrupt

ESP32TimerInterrupt库的下载链接(适用于Arduino IDE)

进入到这个地址后直接下载该库的压缩包,不用解压,直接通过arduino IDE添加即可!
然后关于该库的使用,GitHub中也给出了example来告诉大家如何使用。
下面开始例程的分析
  • 使用的开发IDE:arduino IDE
  • 使用的板子:ESP32S3
  • 例程:TimerInterruptTest.ino
首先要使用这个定时器中断,要引入定时器中断的库,即包含这个库的头文件:
#include "ESP32TimerInterrupt.h"
然后定义中断调用时,输出电平的管脚:
#define PIN_D19       19        // Pin D19 mapped to pin GPIO9 of ESP32
#define PIN_D3        3        // Pin D3 mapped to pin GPIO3/RX0 of ESP32
然后编写中断处理函数:
bool IRAM_ATTR TimerHandler0(void * timerNo)
{static bool toggle0 = false;  // 定义状态值为false//timer interrupt toggles pin PIN_D19digitalWrite(PIN_D19, toggle0); // 调用该中断时,在ESP的GPIO9输出toggle0的状态值toggle0 = !toggle0; // 将状态反转return true;
}
关于该函数的解释及参数说明

bool IRAM_ATTR TimerHandler0(void * timerNo) 是一个中断服务例程(ISR)的声明,它用于ESP32的硬件定时器中断处理。下面是对该函数声明的详细解释:

  • bool:函数的返回类型为布尔值,这意味着函数将返回 true 或 false。在中断服务例程中返回 true 通常表示中断被成功处理,而返回 false 可能表示中断未被处理或处理中出现错误。
  • IRAM_ATTR:这是一个宏定义,用于指定该函数需要放置在指令RAM(Instruction RAM,IRAM)中。在ESP32中,将中断服务例程放在IRAM中可以确保它们被快速执行,因为IRAM的访问速度比普通RAM快。这是在处理高速中断时推荐的做法。
  • TimerHandler0:这是ISR函数的名称,它遵循了一定的命名约定,表明这是针对特定定时器(在这个例子中是 Timer 0)的中断处理函数。
  • (void * timerNo):这是传递给ISR的参数,timerNo 是一个指向 void 类型的指针,通常用于传递与定时器相关的信息或上下文。参数的具体使用取决于中断服务例程的设计和需求。
第二个中断处理函数
bool IRAM_ATTR TimerHandler1(void * timerNo)
{static bool toggle1 = false;//timer interrupt toggles outputPindigitalWrite(PIN_D3, toggle1);toggle1 = !toggle1;return true;
}

注:解释与参数说明同上,唯一的区别是,这里的中断用的Timer 1,上面的中断处理函数用的Timer 0。

接下来定义中断的持续时间(毫秒)和间隔时间(微秒)
#define TIMER0_INTERVAL_MS        1000  // 间隔时间单位是微秒
#define TIMER0_DURATION_MS        5000  // 持续时间单位是毫秒#define TIMER1_INTERVAL_MS        3000
#define TIMER1_DURATION_MS        15000
对两个定时器进行初始化
// Init ESP32 timer 0 and 1
ESP32Timer ITimer0(0);
ESP32Timer ITimer1(1);
编写配置函数
void setup()
{pinMode(PIN_D19, OUTPUT);pinMode(PIN_D3, OUTPUT);// 开启串口Serial.begin(115200);// 如果串口连接建立或者板子运行超过5秒则退出循环while (!Serial && millis() < 5000);// 延迟500毫秒delay(500);// 利用串口打印信息Serial.print(F("\nStarting TimerInterruptTest on "));Serial.println(ARDUINO_BOARD);Serial.println(ESP32_TIMER_INTERRUPT_VERSION);Serial.print(F("CPU Frequency = "));Serial.print(F_CPU / 1000000);Serial.println(F(" MHz"));// Using ESP32  => 80 / 160 / 240MHz CPU clock ,// For 64-bit timer counter// For 16-bit timer prescaler up to 1024// Interval in microsecs// 下面定时器间隔设置为1000000微秒,即1秒if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)){// 如果定时器中断设置成功,则串口打印定时器设置成功的信息,并打印板子运行时间Serial.print(F("Starting  ITimer0 OK, millis() = "));Serial.println(millis());}else// 否则打印定时器无法设置Serial.println(F("Can't set ITimer0. Select another freq. or timer"));// Interval in microsecsif (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)){Serial.print(F("Starting  ITimer1 OK, millis() = "));Serial.println(millis());}elseSerial.println(F("Can't set ITimer1. Select another freq. or timer"));Serial.flush();
}
编写循环函数
void loop()
{static unsigned long lastTimer0 = 0;static unsigned long lastTimer1 = 0;static bool timer0Stopped = false;static bool timer1Stopped = false;if (millis() - lastTimer0 > TIMER0_DURATION_MS){// 如果板子距离上一次中断触发的时间大于定时器持续时间,则更新lastTimer0的值lastTimer0 = millis(); // 检查定时器是否开启,如果开启就关掉,如果关掉就开启if (timer0Stopped){Serial.print(F("Start ITimer0, millis() = "));Serial.println(millis());ITimer0.restartTimer(); // 重启定时器Timer 0}else{Serial.print(F("Stop ITimer0, millis() = "));Serial.println(millis());ITimer0.stopTimer();  // 关闭定时器Timer 0}// 进行状态转换timer0Stopped = !timer0Stopped;}// 如果板子距离上一次中断触发的时间大于定时器持续时间,则更新lastTimer1的值if (millis() - lastTimer1 > TIMER1_DURATION_MS){lastTimer1 = millis();// 检查定时器是否开启,如果开启就关掉,如果关掉就开启if (timer1Stopped){Serial.print(F("Start ITimer1, millis() = "));Serial.println(millis());ITimer1.restartTimer(); // 重启定时器Timer 1}else{Serial.print(F("Stop ITimer1, millis() = "));Serial.println(millis());ITimer1.stopTimer();  // 关闭定时器Timer 1}timer1Stopped = !timer1Stopped;}
}
完整代码
#include "ESP32TimerInterrupt.h"// Don't use PIN_D1 in core v2.0.0 and v2.0.1. Check https://github.com/espressif/arduino-esp32/issues/5868
// Don't use PIN_D2 with ESP32_C3 (crash)
#define PIN_D19             19        // Pin D19 mapped to pin GPIO9 of ESP32
#define PIN_D3               3        // Pin D3 mapped to pin GPIO3/RX0 of ESP32// With core v2.0.0+, you can't use Serial.print/println in ISR or crash.
// and you can't use float calculation inside ISR
// Only OK in core v1.0.6-
bool IRAM_ATTR TimerHandler0(void * timerNo)
{static bool toggle0 = false;//timer interrupt toggles pin PIN_D19digitalWrite(PIN_D19, toggle0);toggle0 = !toggle0;return true;
}bool IRAM_ATTR TimerHandler1(void * timerNo)
{static bool toggle1 = false;//timer interrupt toggles outputPindigitalWrite(PIN_D3, toggle1);toggle1 = !toggle1;return true;
}#define TIMER0_INTERVAL_MS        1000
#define TIMER0_DURATION_MS        5000#define TIMER1_INTERVAL_MS        3000
#define TIMER1_DURATION_MS        15000// Init ESP32 timer 0 and 1
ESP32Timer ITimer0(0);
ESP32Timer ITimer1(1);void setup()
{pinMode(PIN_D19, OUTPUT);pinMode(PIN_D3, OUTPUT);Serial.begin(115200);while (!Serial && millis() < 5000);delay(500);Serial.print(F("\nStarting TimerInterruptTest on "));Serial.println(ARDUINO_BOARD);Serial.println(ESP32_TIMER_INTERRUPT_VERSION);Serial.print(F("CPU Frequency = "));Serial.print(F_CPU / 1000000);Serial.println(F(" MHz"));// Using ESP32  => 80 / 160 / 240MHz CPU clock ,// For 64-bit timer counter// For 16-bit timer prescaler up to 1024// Interval in microsecsif (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)){Serial.print(F("Starting  ITimer0 OK, millis() = "));Serial.println(millis());}elseSerial.println(F("Can't set ITimer0. Select another freq. or timer"));// Interval in microsecsif (ITimer1.attachInterruptInterval(TIMER1_INTERVAL_MS * 1000, TimerHandler1)){Serial.print(F("Starting  ITimer1 OK, millis() = "));Serial.println(millis());}elseSerial.println(F("Can't set ITimer1. Select another freq. or timer"));Serial.flush();
}void loop()
{static unsigned long lastTimer0 = 0;static unsigned long lastTimer1 = 0;static bool timer0Stopped         = false;static bool timer1Stopped         = false;if (millis() - lastTimer0 > TIMER0_DURATION_MS){lastTimer0 = millis();if (timer0Stopped){Serial.print(F("Start ITimer0, millis() = "));Serial.println(millis());ITimer0.restartTimer();}else{Serial.print(F("Stop ITimer0, millis() = "));Serial.println(millis());ITimer0.stopTimer();}timer0Stopped = !timer0Stopped;}if (millis() - lastTimer1 > TIMER1_DURATION_MS){lastTimer1 = millis();if (timer1Stopped){Serial.print(F("Start ITimer1, millis() = "));Serial.println(millis());ITimer1.restartTimer();}else{Serial.print(F("Stop ITimer1, millis() = "));Serial.println(millis());ITimer1.stopTimer();}timer1Stopped = !timer1Stopped;}
}
上面的完整代码在arduino IDE中安装好定时器中断的库后,即可编译,烧录进ESP32中即可运行!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/13419.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu使用记录——如何使用wireshark网络抓包工具进行检测速腾激光雷达的ip和端口号

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言wireshark网络抓包工具1.wireshark的安装2.wireshark的使用3.更改雷达ip 总结 前言 Wireshark是一款备受赞誉的开源网络协议分析软件&#xff0c;其功能之强大…

简述MyBatis中#{}引用和${}引用的区别

各位大佬光临寒舍&#xff0c;希望各位能赏脸给个三连&#xff0c;谢谢各位大佬了&#xff01;&#xff01;&#xff01; 目录 1.有无预编译 优点 缺点 2.SQL执行的快慢 3.能否被SQL注入 4.参数输入方式 5.总结 1.有无预编译 #{}是有预编译的而${}是没有预编译的&…

LiveGBS流媒体平台GB/T28181用户手册-服务器概览:通道信息、负载信息、CPU使用、存储使用、带宽使用(Mbps)、内存使用

LiveGBS用户手册-服务器概览&#xff1a;通道信息、负载信息、CPU使用、存储使用、带宽使用&#xff08;Mbps&#xff09;、内存使用 1、服务器概览1.1、通道信息1.2、负载信息1.2.1、信息说明1.2.2、会话列表 1.3、CPU使用1.4、存储使用1.5、带宽使用&#xff08;Mbps&#xf…

15:00面试,15:08出来,面试问的有点变态。。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天…

C语言查漏补缺学习【精简版】

1.scanf函数 scanf&#xff08;"%d %d"&#xff09;//1 2 scanf("price%d %d") //price1 2 // 意思就是scanf函数中&#xff0c;格式是什么&#xff0c;就要对应的输入什么&#xff0c;不然读取不到输入的变量2.常量&#xff1a;const int AMOUNT 100; …

github下载代码

clone代码 git clone https://<your_token>github.com//.git 设置URL git remote set-url origin https://<your_token>github.com//.git 设置github本地ip https://juejin.cn/post/7350880189836918820?searchId202405191828091DB64DD476DF0AEC7442

掌握Edge浏览器的使用技巧

导言&#xff1a; Edge浏览器是微软推出的一款现代化、高效的网络浏览器。它不仅提供了基本的浏览功能&#xff0c;还具备了许多强大的特性和技巧&#xff0c;可以帮助用户更好地利用浏览器进行工作和娱乐。本文将介绍一些Edge浏览器的使用技巧&#xff0c;帮助读者更好地掌握这…

阿里云数据库 SelectDB 版全面商业化,开启现代化实时数据仓库的全新篇章

2024 年 5 月 21 日&#xff0c;由阿里云联合飞轮科技共同举办的「阿里云数据库 SelectDB 版商业化产品发布会」于线上召开。阿里巴巴集团副总裁、阿里云数据库产品事业部负责人李飞飞宣布&#xff0c;阿里云数据库 SelectDB 版在中国站及国际站全面发布&#xff0c;正式开启商…

集合-1 数组ArrayListLinkedList

一.数组 1.什么是数组&#xff1f; 数组是一种用连续的内存空间存储相同类型数据的线性数据结构。 2.为什么数组下标是从0开始&#xff1f; &#xff08;1&#xff09;数组根据下标查找元素是基于寻址公式&#xff1a;元素地址数组首地址索引i*数组存储数据类型的大小 &am…

ROS | 用C++和python实现运动控制功能

基础知识&#xff1a; 用C实现&#xff1a; C代码&#xff1a; 用python实现&#xff1a; Python代码&#xff1a;

数据库理论基本概念

数据库理论基本概念 三级模式和两级映像 外模式 > 用户和数据库系统的接口 -------- 外模式-概念模式映射 概念模式 > 数据的逻辑结构和特征的描述 -------- 概念模式-内模式映射 内模式 > 数据物理结构和存储方式的描述三级…

避雷:搭建ai知识库的6大注意事项

随着人工智能技术的发展&#xff0c;ai知识库成为众多企业追求的一个重要部分&#xff0c;帮助企业提高运营次效率&#xff0c;越来越受到人们的关注。但是&#xff0c;在搭建ai知识库的过程中&#xff0c;稍不留意&#xff0c;就会漏掉一些小细节&#xff0c;导致做出来的ai知…

【LeetCode】438.找到字符串中所有字母异位词

找到字符串中所有字母异位词 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示…

Scala学习笔记4: 数组

目录 第四章1- 定长数组2- 变长数组3- 遍历数组和数组缓存4- 数组转换5- 常用算法6- 多维数组end 第四章 1- 定长数组 在Scala中, 定长数组可以使用 Array 类来创建; 定长数组在创建时需要指定数组的长度, 并且长度在整个数组生命周期中保持不变; 示例: // 定义一个定长数组…

GPT-4o 引领人机交互新风向的向量数据库Milvus Cloud 成本

成本 AIGC 时代对于冷热储存的呼唤 成本一直是向量数据库获得更广泛使用的最大阻碍之一,这个成本来自两点: 储存,绝大多数向量数据库为了保证低延迟,需要把数据全量缓存到内存或者本地磁盘。在这个动辄百亿量级的AI 时代,意味着几十上百 TB 的资源消耗。 计算,数据需…

OpenFeign高级用法:缓存、QueryMap、MatrixVariable、CollectionFormat优雅地远程调用

码到三十五 &#xff1a; 个人主页 微服务架构中&#xff0c;服务之间的通信变得尤为关键。OpenFeign&#xff0c;一个声明式的Web服务客户端&#xff0c;使得REST API的调用变得更加简单和优雅。OpenFeign集成了Ribbon和Hystrix&#xff0c;具有负载均衡和容错的能力&#xff…

线性回归模型之套索回归

概述 本案例是基于之前的岭回归的案例的。之前案例的完整代码如下&#xff1a; import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import Ridge, LinearRegression from sklearn.datasets import make_regression from sklearn.model_selectio…

NegativePrompt:利用心理学通过负面情绪刺激增强大型语言模型

【摘要】大型语言模型 (LLM) 已成为各种应用不可或缺的一部分&#xff0c;从传统的计算任务到高级人工智能 (AI) 应用。这种广泛的应用促使社会科学等各个学科对 LLM 进行了广泛的研究。值得注意的是&#xff0c;研究表明 LLM 具有情商&#xff0c;可以通过积极的情绪刺激进一步…

C++:深入理解多态

一、多态的概念 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 那究竟多态的实际价值体现在哪里呢&#xff1f;&#xff1f; 1、举个例子比如说购买高铁票这个行为&…