6. [Micropython]TPYBoard v102 按键开关,回调函数和中断

原创版权归山东萝卜科技有限公司所有,转载必须以链接形式注明作者和原始出处。

TPYBoard v10x开发板上有两个小按键,分别标示为 USR 和 RTS。RTS 按键属于复位按键,如果按下的话将重新擦写重启开发板,相当于将开发板断电再重启。

USR按键供用户使用,且其可以通过声明一个按键对象(Switch object)进行控制。

创建开关对象的方法如下:

>>> sw = pyb.Switch()

当提示 pyb 不存在的错误出现时 ,其大意为你忘记键入 import pyb 语句。

利用按键对象可以得到按键的状态:

>>> sw()
False

如果按键被按下将打印 True ,松开则打印 False 。可以尝试运行上述指令时按下 USR 按键。

6.1. 按键回调函数

尽管按键算是一种简单的构造,但它具有明显的优势特征:sw.callback()函数。该回调函数将在按键按下时创建一些东西,且使用了一个中断。在理解中断工作机制前最好用一个例子进行描述。尝试在解释器里边运行如下的代码:

>>> sw.callback(lambda:print('press!'))

这个例程要求每次按下按键时都能打印 press! 字符。先进行尝试:按下USR按键并观测你 PC 上的输出。注意该打印将打断目前你在 pyborad 板上的任何程序,且其属于一种异步中断例程。

可以尝试如下另一个例子:

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

这将在每次按键按下时翻转 LED 的亮灭状态,且其能打断目前其他代码的运行。

关闭按键回调,只需将回调函数的参数设置为 None 即可。

>>> sw.callback(None)

你可以传递不带参数的函数作为参数给按键回调函数使用。所以我们可以充分利用 Python 中的 lamba 声明特性。但我们可以用下面的形式替代:

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

这将创建一个名为 f 的函数并将其传递给按键回调函数。当 lamba 比较复杂时你可以尝试使用这种方法。

注意回调函数一定不能含有任何分配内存的定义(比如不能声明创建列表和元组)。回调函数越简单越好。如果确切需要定义列表,请在使用回调函数前定义并用一个全局变量存储(或者定义为局部变量并对其进行封装)。如果需要多次复杂的计算,那么可以用按键回调设置一个标志供其他代码响应使用。

6.2. 中断的原理细节

现在谈谈按键回调函数发生时的细节。当你调用了含有 sw.callback( )的函数时,按键将在其连接引脚产生一个边沿触发(下降沿)外部中断。这意味着芯片将监听该引脚的任何状态变换,且如下事情会发生:

1.当按键被按下时引脚将发生改变(电平由低到高),芯片处理器将记录这种变化;

2.处理器完成当前机器指令,退出执行状态并保存当前的状态(将寄存器的内容推入栈中)。这将停止当前运行的任何代码,例如正在执行着的 python 脚本;

3.芯片开始执行与按键相关的特定外部中断触发处理。该处理指向你在 sw.callback()函数中指定的函数功能并执行之;

4.直到回调函数执行完毕,控制主权将回到中断处理手上;

5.按键中断处理将返回,芯片处理器确认记录该中断被执行过;

6.芯片调回步骤 2 的状态;

7.继续执行开始时的代码,除了短暂的暂停,这部分代码看起来似乎没有被打断过。

当同一时间多个中断同时发生上述的过程将复杂得多。这种情况下拥有最高优先级别的中断将被首先执行,其他的中断按各自的优先级数序执行。按键中断的优先级最低。

6.3. 进一步参考

进一步使用硬件中断的信息可参考文档 writing interrupt handlers 。