第8章 外部中断实验

第八章 外部中断实验

1. 导入

前面我们在做按键控制实验时, 虽然能实现 IO 口输入功能, 但代码是一直在检测 IO 输入口的变化, 因此效率不高, 特别是在一些特定的场合, 比如某个按键, 可能 1 天才按下一次去执行相关功能, 这样我们就浪费大量时间来实时检测按键的情况。

为了解决这样的问题, 我们引入外部中断概念, 顾名思义, 就是当按键被按下(产生中断)时, 才去执行相关功能。 这大大节省了 CPU 的资源, 因此中断在实际项目中应用非常普遍。

ESP32 的外部中断有上升沿、 下降沿、 低电平、 高电平触发模式。 上升沿和下降沿触发如下:

屏幕截图 2024 08 06 101430

2. 硬件设计

本实验使用到硬件资源如下:

  • 按键模块

  • ESP32 GPIO

  • LED模块

按键模块电路如下所示:
屏幕截图 2024 08 06 101738

由图可知, J3 端子的 KEY1-KEY4 脚为按键控制端, 要检测按键是否被按下,只需读取 J3 端子的 KEY1-KEY4 脚是否为低电平, 因此可使用导线将 ESP32 的 IO口与 J2 端子的 KEY1-KEY4 脚连接。

本章实验使用 ESP32 的 IO14、 27、 26、 25 引脚, 接线如下所示:

屏幕截图 2024 08 06 101849

3. 软件设计

3.1 MicroPython函数使用

外部中断也是通过 machine 模块的 Pin 子模块来配置, 先来看构造函数和使用方法:

屏幕截图 2024 08 06 102017

3.2 代码分析

from machine import Pin
import time

# a定义按键控制对象
key1 = Pin(14, Pin.IN, Pin.PULL_UP) # 使用引脚14,输入模式,上拉电阻
key2 = Pin(27, Pin.IN, Pin.PULL_UP)
key3 = Pin(26, Pin.IN, Pin.PULL_UP)
key4 = Pin(25, Pin.IN, Pin.PULL_UP)

# 定义led控制对象
led1 = Pin(15, Pin.OUT)
led2 = Pin(2, Pin.OUT)
led3 = Pin(0, Pin.OUT)
led4 = Pin(4, Pin.OUT)

# 定义led初始状态
led1_state,led2_state,led3_state,led4_state = 1,1,1,1

# key1外部中断函数
def key1_irq(key1):
    global led1_state # 声明全局变量
    time.sleep_ms(10) # 延时10ms,防止抖动
    if key1.value() == 0: # 按键按下
        led1_state =not led1_state # 翻转led状态
        led1.value(led1_state) # 控制led

# key2外部中断函数
def key2_irq(key2):
    global led2_state
    time.sleep_ms(10)
    if key2.value() == 0:
        led2_state = not led2_state
        led2.value(led2_state)

# key3外部中断函数
def key3_irq(key3):
    global led3_state
    time.sleep_ms(10)
    if key3.value() == 0:
        led3_state = not led3_state
        led3.value(led3_state)

# key4外部中断函数
def key4_irq(key4):
    global led4_state
    time.sleep_ms(10)
    if key4.value() == 0:
        led4_state = not led4_state
        led4.value(led4_state)

# 主函数
if __name__ == '__main__':
    led1.value(led1_state) # 初始状态
    led2.value(led2_state)
    led3.value(led3_state)
    led4.value(led4_state)

    key1_irq(key1_irq, Pin.IRQ_FALLING) # 配置key1外部中断,下降沿触发
    key2_irq(key2_irq, Pin.IRQ_FALLING)
    key3_irq(key3_irq, Pin.IRQ_FALLING)
    key4_irq(key4_irq, Pin.IRQ_FALLING)

    while True:
        pass # 程序阻塞,等待外部中断

以上代码中需要注意的地方:

  1. ledx_state 是全局变量, 因此在 fun 函数里面用该变量必须添加global ledx_state 代码, 否则会在函数里面新建一个样的变量造成冲突。

  2. 在定义回调函数 keyx_irq 的时候, 需要将 Pin 对象 KEY 传递进去。


2024.8.21 第一次修订,后期不再维护

posted @ 2024-08-21 13:09  hazy1k  阅读(7)  评论(0编辑  收藏  举报