创客孙老师
创客孙老师
发布于 2024-05-19 / 28 阅读
0
0

使用MicroPython和pyboard开发板(6):Switch、回调和中断

使用MicroPython和pyboard开发板(6):Switch、回调和中断

pyb_v1.1.png

pyboard开发板有两个小开关,分别标为USRRSTRST开关是一个硬复位开关,如果按下,pyboard就会从头开始重启,相当于关机后再开机。
USR开关用于一般用途,通过Switch对象控制。要创建Switch对象,可以执行以下操作:

>>> sw = pyb.Switch()

直接敲入上面的代码可能会出现pyb不存在的错误,那是因为没有引入pyb包,可以键入 import pyb回车引入。

使用switch对象可以获取其状态:

>>> sw.value()
False

如果开关未拿下,则打印False;如果按住开关,则打印True,可以尝试在运行上述命令时按住USR开关。

还有一个简写符号调用开关对象来获取开关状态:

>>> sw()
False

Switch回调

switch是一个非常简单的对象,但它有一个高级功能:sw.callback()函数。回调函数设置按下开关时要运行的内容,并使用中断。在了解中断如何工作之前,可以先从一个示例开始。尝试在提示符下运行以下命令:

>>> sw.callback(lambda:print('开关按下!'))

每按下开关一次,开关就会打印一次 "开关按下!"。可以尝试:按下 USR开关并观察PC上的输出。请注意,这次打印会中断正在输入的任何内容,上面是中断例程异步运行的一个例子。

另一个例子是:

>>>sw.callback(lambda:pyb.LED(1).toggle())

每次按下开关时,红色LED都会切换。它甚至可以在其他代码运行时工作。
要禁用开关回调,可将None传递给回调函数:

>>> sw.callback(None)

可以将任何函数(无参数)传递给switch回调。上面使用Python的lambda特性来动态创建一个匿名函数,同样可以这样做:

>>> def f():
...     pyb.LED(1).toggle()
...
>>> sw.callback(f)

这里创建一个名为f的函数并将其分配给switch进行回调。当函数比 lambda允许的更复杂时,可以这样做。

请注意,回调函数不得分配任何内存(例如,它们不能创建元组或列表)。回调函数应该比较简单。如果需要创建一个列表,请预先创建并将其存储在全局变量中(或将其设置为本地变量并关闭它)。如果需要进行长时间、复杂的计算,请使用回调来设置一个标志,然后其他代码会响应该标志。

中断的技术细节

下面逐步详细了解switch回调所发生的情况。当使用sw.callback()注册函数时,开关会在开关连接的引脚上设置外部中断触发器(下降沿)。这意味着微控制器将侦听引脚上的任何变化,并且将发生以下情况:

  1. 当按下开关时,引脚上会发生变化(引脚从低电平变为高电平),微控制器会记录此变化。
  2. 微控制器完成当前机器指令的执行,停止执行,并保存其当前状态(将寄存器压入堆栈)。这具有暂停任何代码的效果,例如正在运行的 Python 脚本。
  3. 微控制器开始执行与开关外部触发器相关的特殊中断处理程序。该中断处理程序获取使用sw.callback()注册的函数并执行它。
  4. 回调函数将一直执行直至完成,将控制权返回给开关中断处理程序。
  5. 开关中断处理程序返回,并通知微控制器中断已被处理。
  6. 微控制器恢复在步骤 2 中保存的状态。
  7. 继续执行开始时运行的代码。除了暂停之外,这段代码没有注意到它被中断了。

当多个中断同时发生时,上述事件序列会变得更加复杂。在这种情况下,优先级最高的中断首先执行,然后按优先级顺序执行其他中断。这里switch中断设置为最低优先级。


评论