<p>从根本上说,GPIO包支持事件的方式是等待所选通道的上升沿和下降沿。这是在后台线程中完成的,而不管在主线程中发生了什么。您的<code>if</code>语句在配置按钮后立即运行一次,然后主线程结束。在</p>
<p>您可以实现两种类型的解决方案。一种是强制主线程等待状态的改变。另一个是响应回调中状态的变化。在</p>
<p>要强制<code>main</code>等待:</p>
<pre><code>import RPi.GPIO as GPIO
channels = [19, 20, 21]
def main():
GPIO.setmode(GPIO.BCM)
for chan in channels:
GPIO.setup(chan, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
for chan in channels:
GPIO.wait_for_edge(chan, GPIO.RISING)
# Now all your buttons have been pressed
</code></pre>
<p>这可能是更有效的方法。最小的设置和没有显式的多线程。在</p>
<p>另一种方法是在单独的线程中侦听输入。您可以像使用<code>add_event_callback</code>那样配置回调以响应上升沿,但请记住,该函数主要用于设置多个回调。更简洁的方法是将对<code>add_event_detect</code>的调用移动到<code>main</code>中,并将它们与<code>add_event_callback</code>结合起来:</p>
^{pr2}$
<p>从编程的角度来看,我将使用这样一个事实:所有通道都被处理得几乎相同,并且只定义一个回调。事实上,设置中最重要的是频道编号和频道名称:</p>
<pre><code>import RPi.GPIO as GPIO
channels = {19: 1, 20: 2, 21: 3}
class callback:
def __init__(self):
self.pressed = dict.fromkeys(channels, False)
def __call__(self, channel):
print(f'Button {channels[channel]} pressed')
self.pressed[channel] = True
if sum(self.pressed.values()) == len(self.pressed):
# All buttons have been pressed
def main():
GPIO.setmode(GPIO.BCM)
cb = callback()
for chan in channels:
GPIO.setup(chan, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(chan, GPIO.RISING, callback=cb)
</code></pre>
<p>注意,在这两个例子中,除了通道配置之外,我都避免了全局状态。第二种方法是将回调设置为可调用类的实例。另一种方法是将回调定义为<code>main</code>中的嵌套函数。在</p>