5. 外部中断
5.1 什么是中断
在微处理器或微控制器的世界中,中断是一种特殊的事件,它会打断和暂时挂起当前正在执行的程序,以便处理一个特定的状况或者事件。例如按下按钮、到达定时器时间或收到序列口数据。中断是一个非常重要的计算机系统概念,它通过异步的方式对这些特定情况做出响应。这里举一个例子,比如我们正在敲代码,突然有一个电话打过来,这时我 们停止敲代码转而去接电话,然后在电话聊完事情之后继续敲代码。这里面的电话就相当于一个中断,打断我们当前做的事情,接电话聊事情就相当于中断需要去执行的事情,也就是中断服务程序。
中断可以分为硬件中断和软件中断两种类型。
硬件中断通常由外部设备的物理事件引发,如按下按钮、达到定时器的时间、或数据到达串行端口。当这些事件发生时,微处理器会立即暂停其当前的任务,并跳转到一个预先定义的中断服务程序(ISR)来响应该事件。
软件中断则是由软件指令引发,通常用于更复杂的处理任务。像操作系统的系统调用就使用了软件中断。
5.2 外部中断
在上一章节,我们在做按键实验时,虽然能实现读取 GPIO口输入功能,但代码是一直在检测IO输入口的变化,如果我们后续加入了大量的代码,就需要花费很长的时间才能轮询到按键检测部分,因此效率不高。特别是在一些特定的场合,比如某个按键,可能 1 天才按下一次去执行相关功能,这样我们就浪费大量时间来实时检测按键的情况。为了解决这样的问题,我们引入外部中断概念,顾名思义,就是当按键被按下(产生中断)时,才去执行相关功能。这大大节省了 CPU 的资源,因此中断在实际项目中应用非常普遍。
外部中断是硬件中断的一种,它由微控制器外部的事件引发。微控制器的某些引脚被设计为对特定事件的发生做出响应,例如按钮的按压、传感器的信号改变等。这些指定的引脚通常被称为“外部中断引脚”。
在发生外部中断事件时,当前的程序执行会被立即停止,并跳转到对应的中断服务程序(ISR)进行处理。处理完毕后,程序会返回到被中断的地方继续执行。
对于嵌入式系统、实时系统来说,外部中断的使用是非常重要的,能帮助系统对外部事件进行即时响应,大大提高了系统的效率和实时性。ESP32S3开发板提供了许多引脚作为可用的外部中断引脚,可以通过配置这些引脚来进行外部中断实验。
ESP32 的外部中断有上升沿、下降沿、低电平、高电平触发模式。上升沿和下降沿触发如下:
当引脚设置为外部中断引脚后,当检测到引脚出现设置的触发模式时,就会进入中断回调函数中执行相应程序;
5.3 外部中断的作用和优势
ESP32S3的外部中断功能在Arduino开发中具有以下作用和优势:
实时响应外部事件:ESP32S3的外部中断功能可以让你的Arduino在检测到外部事件触发时立即作出响应。这些外部事件可以是来自传感器、按钮、开关、接收到的信号等等。通过外部中断,就可以实时地捕捉到这些事件并执行相应的操作,而无需频繁地轮询或等待。
节省计算资源:外部中断允许你将处理外部事件的任务转移给芯片的硬件,从而节省了处理器的计算资源。相比于软件轮询方式,外部中断可以降低对处理器的负担,使其可以更有效地利用其它资源进行更复杂的任务。
精确的事件捕捉:ESP32S3的外部中断功能能够以非常精确的方式捕捉外部事件的触发。你可以通过配置中断触发方式(如上升沿、下降沿、任意电平、低电平保持、高电平保持等)来适应不同的外部事件,并在事件发生时立即中断当前程序的执行,转而执行中断服务函数(ISR)。
高优先级处理:外部中断可以设置为高优先级处理,优先于当前正在执行的程序。这对于需要立即响应的重要事件非常有用,如紧急通知、传感器检测等。当外部事件触发时,处理器将立即转移到中断服务函数执行,确保及时、准确地处理相关操作,避免对处理程序的延迟。
多路中断处理:ESP32S3支持多路外部中断,你可以将多个外部事件与不同的中断引脚相连,从而实现对多个事件的并行处理。这使得你可以在一个Arduino上处理多个传感器、开关等外部事件,提高系统的灵活性和扩展性。
总之,ESP32S3的外部中断功能给的Arduino项目提供了实时响应、节省计算资源、精确事件捕捉、高优先级处理和多路中断处理等优势。它为我们提供了更加灵活、高效的方式来处理外部事件,并帮助构建更强大、可靠的应用。
5.4 使用外部中断流程
使用外部中断流程一般是如下步骤:
- 导入相应的模块和库
from machine import Pin
- 配置引脚为输入或启用上拉电阻输入模式
使用 Pin 方法将引脚配置为输入引脚。
# 初始化 GPIO0 引脚为输入模式,使能上拉电阻
KEY = Pin(0, Pin.IN, Pin.PULL_UP)
2
- 将引脚绑定中断服务程序并设置触发中断方式
- 使用 .irq() 方法将中断服务程序绑定到引脚上。可以选择触发中断的方式,例如上升沿、下降沿或状态变化:
#绑定中断服务函数, 下降沿触发,中断服务函数为key_handler
KEY.irq(key_handler, Pin.IRQ_FALLING)
2
其中, .irq()方法是 machine Pin 类中的一部分,用于将一个函数(中断服务程序ISR)与外部中断引脚绑定起来。当外部中断引脚满足指定的条件(例如引脚电平变化)时,相应的中断服务程序将自动被调用。这个函数最常用在处理实时操作和中断事件。
函数原型如下:
Pin.irq(handler=None, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, *, priority=1, wake=None, hard=False)
以下是各个参数的说明:
- handler: 这个参数接受一个回调函数,该函数在中断触发时会被调用。如果设置为 None,则会禁用之前配置的中断。
- trigger: 此参数定义了中断触发的条件。可以是以下几种类型中的一个或多个通过逻辑或操作组合起来的:
- Pin.IRQ_FALLING: 配置为在信号下降沿时触发中断。
- Pin.IRQ_RISING: 配置为在信号上升沿时触发中断。
- Pin.IRQ_LOW_LEVEL: 配置为在低电平时触发中断。
- Pin.IRQ_HIGH_LEVEL: 配置为在高电平时触发中断。
- priority: 设置中断优先级,此参数在某些设备中可能并不总是有效,因为它受硬件平台和 MicroPython 移植的支持情况影响。优先级的设置取决于特定平台和移植的具体实现。
- wake: 在某些设备上,此参数可以被设置为从睡眠模式中唤醒设备的方式。例如,ESP32 支持将其设置为模式如 machine.SLEEP 和 machine.IDLE,以从轻睡眠或休眠模式中唤醒设备。
- hard: 一个布尔参数,用于指定是否使用硬件中断。再次说明,这个功能取决于特定平台的 MicroPython 移植是否支持。 在使用 Pin.irq 时,提供一个中断触发条件 (trigger) 和一个回调函数 (handler) 是常规做法。例如:
from machine import Pin
def callback(p):
print("Interrupt detected on pin: ",p)
pin=Pin(15,Pin.IN,Pin.PULL_UP)
interrupt=pin.irq(trigger=Pin.IRQ_RISING|Pin.IRQ_FALLING,handler=callback)
2
3
4
5
6
7
8
这段代码片段设置了一个回调函数,这个回调函数会在连接到 GPIO 15 的引脚上检测到任何边缘变化(上升或下降)时被调用。
- 处理中断事件 根据上面的示例中使用的中断回调函数 callback 进行说明。
在中断处理函数中执行的代码将在引发中断时被调用。在里面可以实现具体的中断响应逻辑。
可选步骤:在必要时,你可以在中断处理函数中禁用中断或重新分配中断处理函数。
例如:
def callback(pin):
# 在引发中断时执行的代码
...
# 禁用中断
pin.irq(handler=None)
# 重新分配中断处理函数
pin.irq(handler=callback, trigger=machine.Pin.IRQ_FALLING)
2
3
4
5
6
7
8
9
注意事项:
- 在 MicroPython 中,外部中断引脚的可用范围取决于 ESP32 开发板的具体硬件引脚。
- 需要根据具体需求和引脚配置,选择适当的中断触发条件,如 machine.Pin.IRQ_FALLING(下降沿触发)或 machine.Pin.IRQ_RISING(上升沿触发)。
5.5 外部中断验证
案例同上一章节,但是触发方式以及触发后要执行的内容,是通过中断执行。
from machine import Pin
import time
# 初始化 GPIO48 引脚为输出模式
LED=Pin(48,Pin.OUT)
# 初始化 GPIO0 引脚为输入模式,使能上拉电阻
KEY=Pin(0,Pin.IN,Pin.PULL_UP)
#定义外部中断服务函数
def key_handler(key):
#消抖
time.sleep_ms(10)
#如果按钮按下
if KEY.value()==0:
#LED状态取反
LED.value(not LED.value())
#绑定中断服务函数, 下降沿触发,中断服务函数为key_handler
KEY.irq(key_handler, Pin.IRQ_FALLING)
while True:
time.sleep_ms(10)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
5.6 外部中断效果
按下按键灯亮,再按下按键灯灭,如此反复。