ESP32 MicroPython教程:定时器中断-Arduino中文社区 - Powered by Discuz! Archiver

dfrobot 发表于 2019-5-28 11:40

ESP32 MicroPython教程:定时器中断


简 介本文主要介绍如何对运行在ESP32之上的MicroPython进行定时器中断的配置。有关ESP32定时器硬件的更多详情,请看这篇帖子: ESP32 Arduino:定时器中断 的第二部分。
测试是使用集成在FireBeetle ESP32开发板中的DFRobot的ESP-WROOM-32模块上进行的。使用软件是MicroPython IDE uPyCraft。
代 码首先需要导入machine模块,以使用与定时器中断配置和处理相关的函数。
import machine
接下来,声明一个计数器,定时器中断函数将使用这个计数器告知主代码中断已发生。之所以采取这种方式,主要是因为中断运行速度非常快,不应在中断内进行函数调用(比如print)。当中断发生时,中断处理函数只是简单地让计数器递增,我们在中断函数外边使用循环对计数器的数值进行检查,并做出相应的操作。

interruptCounter = 0
我们还会再定义一个计数器(http://docs.micropython.org/en/latest/library/machine.Timer.html),用于保存自程序开始运行以来所发生的所有中断,以便将每一个新发生的中断计数值打印出来。
totalInterruptsCounter = 0
接着,新建一个Timer类的对象,这个类位于machine模块中。我们将使用这个对象对定时器中断进行配置。该类的构造函数可接收一个数值参数(0到3),表示所要使用的定时器硬件(ESP32共有4种定时器硬件)。本例将使用定时器0。
timer = machine.Timer(0)
然后,声明一个叫做handleInterrupt的中断处理函数。该函数的输入参数是当中断被触发时的一个Timer类对象,但是在我们的代码中不会用到它。函数内部逻辑非常简单,只是不断地递增interruptCounter变量。鉴于我们将对这个全局变量进行操作和修改,因此需要使用global关键字对其进行声明,然后才能使用。
def handleInterrupt(timer):
global interruptCounter
interruptCounter = interruptCounter+1
声明完中断处理函数之后,调用先前所创建Timer对象的init方法,以对定时器进行初始化。该函数的输入参数包括中断周期(单位为毫秒)、定时器模式(一次性还是周期性)以及负责处理中断的回调函数。本例将定时器设置为周期性运行(每秒一次)。所以周期参数就是1000,定时器模式参数是Timer类的PERIODIC常量。对于一次性定时器,只需将模式参数改成Timer类的ONE_SHOT常量即可。最后,在回调参数中,把先前声明的中断处理函数传给它即可。
timer.init(period=1000, mode=machine.Timer.PERIODIC, callback=handleInterrupt)
现在定时器已经启动,我们再来看其他代码。如前所述,根据ISR发出的中断信号,我们将在主代码中对中断进行处理。由于例程非常简单,我们只是在一个无限循环中对interruptCounter变量进行轮询,以确定其值是否大于0。如果大于0,那就表示我们有中断需要处理。当然,在实际的应用程序中,通常会需要进行其他计算,而不会仅仅对这个变量进行轮询。如果检测到了中断,我们就需要使interruptCounter变量递减,表示我们将要对其进行处理。因为这个变量是与ISR共享的变量,为了避免冲突,递减操作需要在一个禁用中断的关键代码段内执行。当然,这个关键代码段应该越短越好,然后就要重新使能中断。只有变量递减操作在关键代码段内执行,其余处理都在重新使能中断后的关键代码段之外进行。所以,先通过调用machine模块的disable_irq函数将中断禁用。该函数会返回先前的IRQ状态,我们把它保存在一个变量中。要重新使能中断,只需调用machine模块的enable_irq函数(将之前保存的IRQ状态传给它作为输入参数)即可。在这两次函数调用之间,对共享变量进行访问和递减操作。

state = machine.disable_irq()
    interruptCounter = interruptCounter-1
    machine.enable_irq(state)

然后,将总中断计数器递增并打印出来,中断处理过程就完成了。最终代码如下所示,其中已经包含了打印代码以及检查中断是否发生的循环。

import machine
interruptCounter = 0
totalInterruptsCounter = 0
timer = machine.Timer(0)
def handleInterrupt(timer):
global interruptCounter
interruptCounter = interruptCounter+1
timer.init(period=1000, mode=machine.Timer.PERIODIC, callback=handleInterrupt)
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))

测试代码将代码上传到您的ESP32开发板并运行,即可对代码进行测试。输出结果如图1所示,控制台会每秒打印一条消息。

http://mc.dfrobot.com.cn/data/attachment/forum/201903/28/151004xp4w58owi1vn1553.png
图1-ESP32上运行的MicroPython定时器中断例程输出结果。

注:本文作者是Nuno Santos,他是一位和蔼可亲的电子和计算机工程师,住在葡萄牙里斯本 (Lisbon)。他写了很多有关ESP32、ESP8266的有用的教程和项目。
查看更多ESP32/ESP8266教程和项目,请点击 : ESP32教程汇总贴英文版教程 : ESP32 tutorial


页: [1]
查看完整版本: ESP32 MicroPython教程:定时器中断