3.10. GPIO 輸入¶
從 GPIO 接腳讀取開關(或任何數位訊號)同樣會經由 machine.Pin,這次設定為輸入。其介面與輸出對稱:設定模式,然後可在主迴圈中輪詢接腳的值,或註冊一個在值變化時觸發的中斷處理常式。
3.10.1. 設定輸入¶
將 Pin.IN 傳給建構式,並可選擇性地傳入上下拉電阻:
from machine import Pin
button = Pin("P0", Pin.IN, Pin.PULL_UP)
這會將 P0 設定為輸入,並啟用 MCU 的內部上拉電阻。在接腳上沒有接任何東西時,上拉會將其維持在高電位;將開關從接腳接到接地閉合則會將其拉低。
3.10.2. 讀取值¶
value() 不帶引數時會回傳目前的狀態──``0`` 代表低電位,1 代表高電位:
if button.value() == 0:
print("button pressed")
else:
print("button released")
在主迴圈的模式中,輪詢看起來像這樣:
while True:
if button.value() == 0:
do_action()
time.sleep_ms(50)
這 50 ms 的睡眠避免迴圈以滿載 CPU 運行。
3.10.3. 中斷驅動的輸入¶
Polling works, but every iteration of the main loop costs CPU
time. For inputs that change rarely -- a button press once a
minute, an alarm signal -- irq() registers
a handler that runs only when the pin changes.
該處理常式在中斷環境中執行,這限制了它能做的事:
不可配置記憶體。建立新物件──串列、字串、例外、格式化字串──在 ISR 內可能會失敗,因為堆積(heap)被鎖定。請在模組層級預先配置處理常式所需的任何緩衝區。
不可進行長時間運行的工作。處理常式應該交派出去並回傳。在 ISR 內耗費實際時間會延誤其他所有事情(其他中斷、主迴圈、USB 流量)。
不可在緊湊的 ISR 中列印。
print()會配置記憶體、在 UART 上阻塞,是處理常式所能做的最昂貴的事情之一。
標準的模式是讓 ISR 透過 micropython.schedule() 排程真正的工作,它會將一個函式排入佇列,在下一個安全的時間點回到主要環境執行:
import micropython
def handle_press(pin):
print("button pressed")
def on_press(pin):
micropython.schedule(handle_press, pin)
button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)
ISR 只有一行:將回呼函式排入佇列並回傳。handle_press 接著在正常環境中執行,在那裡進行記憶體配置、print() 與緩慢的 I/O 又都是安全的了。
trigger 引數選擇由哪個邊緣觸發:
Pin.IRQ_FALLING── 1 變 0。Pin.IRQ_RISING── 0 變 1。Pin.IRQ_FALLING|Pin.IRQ_RISING── 兩個邊緣皆觸發。