中断概念
参考:
https://docs.micropython.org/en/latest/pyboard/library/pyb.ExtInt.html
什么是中断呢?
想象一下,如果你想当按键按下的时候,就做一件事(比如点亮一个LED灯)。
那么最容易想到的就是轮询:
while True:
if 按键被按下:
亮灯
else:
灭灯
但是这种代码只适用于简单的逻辑,假如你有很多很多事情要做。这种方式就很浪费时间,并且,响应时间也会变长。
如果硬件可以自动的完成”当按键按下的时候,自动做xxxx”,就节省了很多的CPU的操作。
板子上的按键
举个例子:
pyboard 有2个小型按键,标有USR和RST。 RST开关是一个硬复位按键,按下的时候,它将从头重新启动pyboard,相当于关闭电源,然后重新打开。
USR按键可以通过Switch对象进行控制,首先新建一个对象:
sw = pyb.Switch()
然后可以用value()方法获得对象的值(按下就是True, 没按下就是False)。
>>> sw.value()
False
回调函数
pyboard通过回调函数来实现中断这一效果:
举个例子:如果不用回调函数,那么用轮询应该是这样的代码:
#轮询
from pyb import Switch
from pyb import LED
sw = Switch()
led = LED(1)
while True:
if sw.value() == True:
led.toggle()
如果用回调函数,程序应该是下面的:
#中断
from pyb import Switch
from pyb import LED
sw = Switch()
led = LED(1)
def led_process(): #定义一个回掉函数,用于调用
led.toggle()
sw.callback(led_process) #将led_process函数与按键绑定
while True:
pass#做一些其它的事
这个回调函数,也叫中断服务程序
, 这个程序应该尽可能的短,并且耗时短。
注意,这个回调函数,不能有任何的内存申请。比如:
def bug1():#错误
a=1+1
def bug2():#错误
return 1+1
def bug3():#错误
print(1+1)
def bug4():#错误
i+1
如果要使用全局的变量,除了定义一个全局变量以外,在函数内部要用global修饰。程序在最下面。
IO中断
当然,pyboard的引脚可以使用用中断的,使用ExtInt类。
class pyb.ExtInt(pin, mode, pull, callback)
– pin参数是引脚,可以是一个Pin对象,或者是一个引脚的名字
– mode:
– ExtInt.IRQ_RISING – 上升沿触发
– ExtInt.IRQ_FALLING – 下降沿出发
– ExtInt.IRQ_RISING_FALLING – 上升沿和下降沿都触发
– pull:
– pyb.Pin.PULL_NONE – 不开启上拉电阻,不开启下拉电阻
– pyb.Pin.PULL_UP – 开启上拉电阻
– pyb.Pin.PULL_DOWN – 开启下拉电阻
– callback:回调函数,当时间触发的时候执行的这个函数
举个例子
from pyb import Pin, ExtInt
def print_X1(line):
print("X1 is pressed")
ext = ExtInt(Pin('X1'), ExtInt.IRQ_FALLING, Pin.PULL_UP, print_X1)
while True:
pass
这里的line参数,是一定要有的,stm32有16条中断线,会自动分配,可以print(line)看一下是哪条。
当按键按下的时候,就会打印
X1 is pressed
又一个例子
from pyb import Pin, ExtInt
counter=0
def count(line):
global counter
counter += 1
print("counter is", counter)
ext = ExtInt(Pin('X1'), ExtInt.IRQ_FALLING, Pin.PULL_UP, count)
while True:
pass
当按键按下的时候,终端陆续会打印:
counter is 1
counter is 2
counter is 3
counter is 4
……