介绍 本文旨在介绍如何在运行MicroPython的ESP32上使用外部引脚中断功能。请注意,本文中涉及的一些代码在前面的定时器中断教程中有更详细的介绍。
代码 首先,我们将导入机器模块,使用它来配置外部中断。
[mw_shl_code=applescript,true]import machine[/mw_shl_code]
接下来,我们将声明一个全局变量,在发生中断事件时,中断处理函数将使用该变量与主程序通信。为了不丢失中断事件,这个变量被设置为一个计数器。关于中断和主代码之间的通信为何使用计数器而不是flag标志的原因,请查看早先的教程。 注意,我们不能在中断服务程序中较长时间地执行任务(例如,将内容打印到串口控制台),所以我们在设计中断任务时应使其尽快地完成。为此,中断服务程序将通知主代码(通过递增计数器的值)发生了中断事件,然后由主代码对任务进行处理。
[mw_shl_code=applescript,true]interruptCounter = 0[/mw_shl_code]
我们还将使用另一个变量来跟踪自程序开始执行以来发生了多少次中断事件。在每次发生中断事件时,我们都会递增这个变量的值并将其打印出来。
[mw_shl_code=applescript,true]totalInterruptsCounter = 0
[/mw_shl_code]
接下来,我们将定义发生中断时需要执行的回调函数。该函数有一个输入参数,当中断发生时,一个Pin类对象将会被传递给此参数。在这个esp32 micropython教程中,我们不会使用到这个函数。 在函数实际执行时,它将递增先前定义的interruptCounter变量的值。请注意,在函数内部更改此变量的值之前,我们首先要将此变量声明为全局变量。
[mw_shl_code=applescript,true]def callback(pin):
global interruptCounter
interruptCounter = interruptCounter+1[/mw_shl_code]
接下来我们需要创建一个Pin类对象,用于在MicroPython中控制GPIO引脚[1]。您可以在此处查看构造函数的所有可用参数。在这个程序中,我们需要将待使用的引脚编号、引脚模式以及是否存在相关拉电阻等信息作为输入参数。 在此示例中,我使用的是引脚25,但你也可以使用其它引脚。请注意,对于某些ESP32开发板,ESP32 GPIO编号可能与板上标记的编号不匹配。 此外,我们还将利用Pin类对象的IN常量属性将引脚模式设置为输入模式。 最后,我们将引脚设置为使用上拉电阻,从而保证在没有施加电信号时该引脚将处于已知状态(高电平,VCC)。 此设置可通过将Pin类的PULL_UP常量传递给函数参数来完成。
[mw_shl_code=applescript,true]
p25 = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP)
[/mw_shl_code]
接下来,我们将通过调用Pin对象的irq函数来指定如何触发中断以及需要执行的回调函数。 在此示例中,我们指定当检测到引脚输入信号下降沿时触发中断程序。为此,我们需要将Pin类对象的IRQ_FALLING常量作为irq函数的触发参数。您可以在此查看所有可用的触发类型。 我们还将把先前定义的中断函数以句柄参数的形式传递给处理函数。
[mw_shl_code=applescript,true]p25.irq(trigger=machine.Pin.IRQ_FALLING, handler=callback)[/mw_shl_code]
至此,所有配置工作都已完成,我们将进入轮询循环以查询interruptCounter变量。当然,我们的程序非常简单,不需要执行其它任务,只要执行轮询任务即可。在实际应用中,我们很可能需要执行一些计算任务,或者让开发板进入睡眠模式以节省能量,而非不断地查询变量的值。 当检测到它的值大于0时,我们将处理此中断事件。首先,我们将递减计数器的值,以此表示即将处理此中断事件。 请注意,由于此变量也用于中断服务程序代码,所以我们需要首先禁用中断功能,然后递减计数器,再重新启用中断功能,从而避免竞态条件。 中断的禁用和重新启用是通过机器模块的disable_irq和enable_irq函数完成的。关于如何使用这些函数的详细信息,请查看先前的教程。
最后,我们将递增中断计数器的总计数值并将其打印出来。在此示例中,由于此变量不与中断服务程序共享,所以我们在更改其值时不需要禁用中断功能。 MicroPython脚本的最终源代码如下所示,其中包含了中断检查循环。
[mw_shl_code=applescript,true]
import machine
interruptCounter = 0
totalInterruptsCounter = 0
def callback(pin):
global interruptCounter
interruptCounter = interruptCounter+1
p25 = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP)
p25.irq(trigger=machine.Pin.IRQ_FALLING, handler=callback)
while True:
if interruptCounter>0:
state = machine.disable_irq()
interruptCounter = interruptCounter-1
machine.enable_irq(state)
totalInterruptsCounter = totalInterruptsCounter+1
print("Interrupt has occurred: " + str(totalInterruptsCounter))[/mw_shl_code]
测试代码 为了测试此代码,我们只需将上述脚本上传到ESP32并运行即可。在运行状态下,不需外部硬件就能触发中断的最简单方法是接通和断开中断输入引脚与开发板GND引脚的接线。 在执行此操作时请特别小心,避免因为将GND引脚连接到错误的GPIO而损坏开发板。 中断事件的处理结果如图1所示。
图1 - ESP32 MicroPython外部引脚中断
注:本文作者是Nuno Santos,他是一位和蔼可亲的电子和计算机工程师,住在葡萄牙里斯本 (Lisbon)。 他写了200多篇有关ESP32、ESP8266的有用的教程和项目。
查看更多ESP32/ESP8266教程和项目,请点击 : ESP32教程汇总贴
|