数码之家

 找回密码
 立即注册
搜索
查看: 93|回复: 2

[Arduino] 《ESP32S3 Arduino开发指南》第九章 EXTI实验

[复制链接]
发表于 前天 09:22 | 显示全部楼层 |阅读模式
第九章 EXTI实验

在前面两章的学习中,我们掌握了ESP32-S3IO口最基本的操作。本章我们将介绍如何把ESP32-S3IO口作为外部中断输入来使用,在本章中,我们将以中断的方式,实现boot按键控制板载的LED灯状态翻转。
本章分为如下几个小节:
9.1 外部中断介绍
9.2 硬件设计
9.3 软件设计
9.4 下载验证


9.1 外部中断介绍
很多时候,我们程序采集一个传感器的数据,采集后就要进行分析判断,若符合某个条件就会做出处理。为了随时根据传感器的变化做出反应,所以程序需要一直重复这个过程。这种方式称为轮询,这种方式是最简单的。
但轮询有时候并不能很好完成一些实际场景的应用,比如我某个时刻按下按键,但这时候程序执行的是采集传感器数据的过程,这就意味着没有检测到按键按下的动作,此时该系统就成了无法正常响应的系统了。通过对该按键配置外部中断功能,这时候就能很好解决上述问题。
9.1.1 中断程序
外部中断是由外部设备发起请求的中断。每个中断对应一个中断程序,中断可以看作一段独立于主程序之外的程序,也称为中断回调函数。当中断被触发时,控制器会暂停当前正在运行的主程序,而跳转去运行中断程序。当中断程序运行完毕,则返回到先前主程序暂停的位置,继续运行主程序,如此便可达到实时响应处理事件的效果。中断程序运行示意图如下图所示。
图9.1.1.1 中断程序执行示意图
9.1.2 ESP32-S3的中断介绍
便于大家了解ESP32-S3芯片的中断知识,这里简单介绍一下。
ESP32-S399个外部中断源,但是CPU0或CPU1只能够处理32个中断。ESP32-S3将外部中断映射到CPU0CPU1中断就需要用到中断矩阵。中断映射的过程如下图所示。
9.1.2.1 ESP32-S3芯片中断源到CPU中断过程图
ESP32-S3中断矩阵会将任一外部中断源单独分配到双核CPU的任一外部中断上,以便在外设中断信号产生后,及时通知CPU0CPU1进行处理。
每个CPU都有32个中断号(0 ~ 31),其中包括26个外部中断,6个内部中断。
外部中断为外部中断源引发的中断,包括下面三种类型:
1) 电平触发类型中断:高电平触发,要求保持中断的电平状态直到CPU响应
2) 边沿触发类型中断:上升沿触发,此中断一旦产生,CPU即可响应
3) NMI中断:不可屏蔽中断,产生该中断时,表示系统发生了致命错误
内部中断为CPU内部自己产生的中断,包括以下三种类型:
1) 定时器中断:由内部定时器触发,可用于产生周期性的中断
2) 软件中断:软件写特殊寄存器时将触发此中断
3) 解析中断:用于性能监测和分析
ESP32-S3的外部中断是很强大的,每个引脚都可设置成外部中断触发引脚。但在大部分的Arduino控制器上,并非所有引脚都有中断功能。只有少数带外部中断功能的引脚上,Arduino控制器才能捕获到该中断信号并做出反应。在这过程中,难免需要通过中断引脚找中断的编号。
9.1.3 中断触发模式
ESP32-S3的中断触发模式有5种,即前面所提及的电平触发以及边沿触发,如下表所示。
中断触发模式
说明
示意图
RISING
上升沿触发,即由低电平变高电平时触发
FALLING
下降沿触发,即由高电平变低电平时触发
CHANGE
电平变化触发,即由高电平变低电平或由低电平变高电平时触发
ONLOW
低电平触发,即当前为低电平时触发
ONHIGH
高电平触发,即当前为高电平时触发
9.1.3.1 ESP32-S3中断模式说明表
9.1.4 中断触发函数介绍
本小节介绍到的函数可在以下文件中找到:
Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32\esp32-hal-gpio.c
Arduino-esp32库提供了两个中断函数,一个用于对中断引脚进行初始化设置,另一个是关闭外部中断。
attachInterrupt函数,该函数功能是指定中断引脚,并对中断引脚进行初始化设置。
void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode);
参数pin为要设置中断触发输入的引脚,ESP32-S3所有引脚均可以配置为外部中断引脚。
参数handler为中断回调函数,当引脚中断触发时,会终止当前运行的程序,转而执行该程序。
参数mode5种中断触发模式,如9.1.3.1表所示。
注意:中断回调函数不能有参数,且没有返回值。
假如不需要监测某个引脚的信号变化,可通过detachInterrupt函数关闭外部中断。
void detachInterrupt(uint8_t pin);
其中参数pin为已经设置中断触发输入的引脚。在本例程中没有用到该函数。
另外,很多时候,我们会见到attachInterrupt函数的第一参数会使用digitalPinToInterrupt(pin)函数,这里简单解释一下为什么?
其实前面也有所提及,在一些Arduino开发板中比如Arduino UnoLeonardo,只有23引脚有外部中断功能,而中断编号对应为01。在Arduino Uno开发板中,attachInterrupt函数第一个参数为中断编号,第二个参数为中断回调函数,第三个参数为触发模式,所以为了避免硬件引脚和中断编号,直接通过digitalPinToInterrupt函数解决。很多时候,attachInterrupt函数的使用也采用以下方式。
attachInterrupt(digitalPinToInterrupt(pin), handler, mode);
ESP32-S3的中断引脚跟中断编号一致,也可不必用digitalPinToInterrupt函数,但是你在程序中也没有问题。
9.2 硬件设计
1. 例程功能
通过外部中断的方式让开发板上的BOOT独立按键控制LED灯翻转。
2. 硬件资源
1LED
LED-IO1
2)独立按键
BOOT-IO0
3. 原理图
独立按键硬件部分的原理图,如下图所示。
图9.2.1 独立按键与ESP32-S3连接原理图
这里需要注意的是:BOOT设计为采样到按键另一端的低电平为有效电平。
9.3 软件设计
9.3.1 程序流程图
下面看看本实验的程序流程图:
图9.3.1.1 程序流程图
9.3.2 程序解析
1. exti驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。EXTI驱动源码包括两个文件:exti.cppexti.h
下面我们先解析exti.h的程序。 由硬件设计小节,我们知道KEY按键在硬件上连接到IO0,为了与按键实验进行区分,我们做了下面的引脚定义。
/* 引脚定义 */
#define KEY_INT_PIN       0   /* 外部中断引脚IO0 */
下面我们再解析exti.cpp的程序,这里有两个函数exti_initkey_isr,其定义如下:
uint8_t led_state = 0;        /* 决定灯亮灭状态变量 */
/**
* @brief    初始化外部中断相关IO
* @param  
* @retval  
*/
void exti_init(void)
{
    key_init();    /* KEY初始化 */
attachInterrupt(digitalPinToInterrupt(KEY_INT_PIN), key_isr, FALLING);  
/* 设置KEY引脚为中断引脚,下降沿触发 */
}
/**
* @brief    KEY外部中断回调函数
* @param   
* @retval  
*/
void key_isr(void)
{
    delay(10);
    if (KEY == 0)
    {
        led_state =! led_state;     /* 两种情况:从01,从1变为0 */
}
}
exti_init函数是初始化外部中断引脚,首先调用key_init设置KEY引脚为上拉输入模式,然后调用attachInterrupt函数设置中断回调函数和设置中断引脚为下降沿触发。
key_isr函数就是中断引脚的中断回调函数。当按键被按下时,出现了下降沿即高电平变为低电平时,这时候就会跳到该函数去执行。函数内部很简单,首先调用delay函数进行按键消抖,然后判断按键是否真的被按下。当按键是按下情况,就对全局变量led_state进行取反操作,即led_state就有两种情况01,最终在loop函数中作为LED(x)宏函数的参数x决定了LED灯的状态。
2. 03_exti.ino代码
在03_exti.ino里面编写如下代码:
#include "led.h"
#include "exti.h"
/**
* @brief   当程序开始执行时,将调用setup()函数,通常用来初始化变量、函数等
* @param   
* @retval  
*/
void setup()
{
    led_init();     /* LED初始化 */
    exti_init();    /* 外部中断引脚初始化 */
}
/**
* @brief    循环函数,通常放程序的主体或者需要不断刷新的语句
* @param   
* @retval   
*/
void loop()
{
    LED(led_state); /* 灯的亮灭由led_state值决定,led_state变化在key_isr函数中实现 */
}
在setup函数中,除了要调用led_init函数对LED灯进行初始化,还要调用exti_init函数对按键KEY进行初始化以及配置KEY所在引脚的下降沿触发中断功能。接下来,在loop函数中,LED的状态通过全局变量led_state决定,若led_state0,即运行LED(0)代码,这时候LED灯就会亮起;若led_state1,即运行LED(1)代码,这时候LED灯就会熄灭。
当按键被按下时,这时候出现了下降沿,就会触发中断,进入到中断回调函数中。在该函数中,会对全局变量led_state进行取反操作,执行完又回到loop函数暂停的地方继续往下执行。最终,实现的效果就是:通过按下按键,LED灯的状态会进行翻转。
9.4 下载验证
下载完之后,通过BOOT按键来控制LED灯的亮灭状态。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 前天 11:07 | 显示全部楼层
专此进来学习学习一下哈
回复 支持 反对

使用道具 举报

发表于 前天 11:38 | 显示全部楼层
谢谢分享~点进来学习一下
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-1 15:08 , Processed in 0.140400 second(s), 13 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表