外部中断
之前我们学习了 ESP32 的按键控制,当时通过查询 GPIO 输入电平来判断按键状态,这种方法占用 CPU 资源,效率不高。本节课我们学习外部中断,通过外部中断实现按键控制 LED。
实验原理
在单片机中,中断是指当 CPU 在正常处理主程序时,突然发生了另一件事件 A(中断发生)需要 CPU 去处理,这时 CPU 就会暂停处理主程序(中断响应),转而去处理事件 A(中断服务)。当事件 A 处理完以后,再回到主程序原来中断的地方继续执行主程序(中断返回)。这一整个过程称为中断。
例如,当你正在洗衣时,突然手机响了(中断发生),你暂时中断洗衣的工作,转去接电话(中断响应和中断服务),待你接完后,再回来继续洗衣(中断返回),这一过程就是中断。
当中断过程 A 中,发生了另一个中断级别更高的中断事件 B,则 CPU 又会中断当前的 A 转而去处理 B,完毕后再回到 A 的断点继续处理。这称为中断的嵌套。
中断的嵌套涉及到中断的优先级问题,优先级高的中断就可以在打断优先级低的中断执行。
注意
ESP32 无法使用 MicroPython 设置中断的优先级。
中断可以根据中断源分为 硬件中断
和 软件中断
:
硬件中断
:也被称为外部中断,硬件中断响应外部硬件事件而发生。例如,当检测到触摸时会发生触摸中断,而当 GPIO 引脚的状态发生变化时会发生 GPIO 中断。GPIO 中断和触摸中断属于这一类;软件中断
:当触发软件事件(例如定时器溢出)时,会发生这种类型的中断。定时器中断是软件中断的一个例子。
前面我们在做按键控制实验时,虽然能实现 IO 口输入功能,但代码是一直在检测 IO 输入口的变化,因此效率不高,特别是在一些特定的场合,比如某个按键,可能 1 天才按下一次去执行相关功能,这样我们就浪费大量时间来实时检测按键的情况。
为了解决这样的问题,我们引入外部中断概念,顾名思义,就是当按键被按下(产生中断)时,才去执行相关功能。这大大节省了 CPU 的资源,因此中断在实际项目中应用非常普遍。
ESP32 的外部中断有上升沿、下降沿、低电平、高电平触发模式。上升沿和下降沿触发如下:
若将按键对应 IO 配置为下降沿触发,当按键按下后即触发中断,然后在中断回调函数内执行对应的功能。
硬件电路设计
使用按键电路实现开关灯的效果。
物料清单(BOM 表):
材料名称 | 数量 |
---|---|
直插式 LED | 1 |
1kΩ 电阻 | 1 |
杜邦线(跳线) | 若干 |
面包板 | 1 |
将材料按照下图相连:
软件程序设计
外部中断也是通过 Pin 模块来配置的,使用方法如下:
from machine import Pin
button = Pin(14, Pin.IN, Pin.PULL_DOWN)
# 配置中断模式
button.irq(handler, trigger)
其中 button.irq(handler, trigger)
是配置中断模式,参数意义:
handler
: 中断执行的回调函数;trigger
: 触发中断的方式,共 4 种,分别是 Pin.IRQ_FALLING(下降沿触发)、Pin.IRQ_RISING(上升沿触发)、Pin.IRQ_LOW_LEVEL(低电平触发)、Pin.IRQ_HIGH_LEVEL(高电平触发)。
因此,我们的代码需要这么写:
import time
from machine import Pin
button = Pin(14, Pin.IN, Pin.PULL_DOWN)
led = Pin(2, Pin.OUT)
# 定义 button 的外部中断函数
def button_irq(button):
time.sleep_ms(80)
if button.value() == 1:
led.value(not led.value())
button.irq(button_irq, Pin.IRQ_RISING)