post / 2024.02.15
MicroPython函式庫
本文整理 MicroPython 的 machine 模組在 Raspberry Pi Pico(RP2040)上的常用介面。內容已對照 MicroPython 官方文件 核對。
machine:與硬體相關的功能
腳位編號有以下兩種:
- GPIO 編號(GP0–GP29):程式碼裡最常用,
Pin(25)就是 GP25。 - 實體腳位號:開發板上的 40 個針腳位置,與 GPIO 編號不是一回事,接線時要注意區分。
Pin 類別
建構子 machine.Pin(id, mode=-1, pull=-1, value=None)
| 參數 | 說明 |
|---|---|
id | 腳位編號。Pico 上可用 0–29(GP0–GP29) |
mode | None / Pin.IN(0) / Pin.OUT(1) / Pin.OPEN_DRAIN(2) |
pull | 內部上下拉電阻,僅在輸入模式有效:None / Pin.PULL_UP(1) / Pin.PULL_DOWN(2) |
value | 僅輸出/開汲極模式有效,初始電位:0 低電位,1 高電位 |
注意是
Pin.PULL_DOWN,不是Pin.DOWN。
Pin.init(mode=-1, pull=-1, value=None)
重新初始化腳位。只修改傳入的參數,其餘狀態保持不變。
Pin.value([x])
- 不傳參數:回傳目前腳位電位(0 或 1)。
- 傳參數:寫入腳位電位,參數會被轉成布林值(
True置 1,False置 0)。
Pin.on() / Pin.off()、Pin.high() / Pin.low()
on()、high():輸出高電位(置 1)。off()、low():輸出低電位(置 0)。
這四個方法僅對輸出/開汲極模式有意義。low() / high() 屬於非核心 API,在 Pico(rp2)上可用。
Pin.toggle()
翻轉輸出電位,0 變 1、1 變 0。toggle() 在 rp2、esp32 等埠可用;如果某個埠不支援,用 Pin.value(not Pin.value()) 代替。
from machine import Pin
import time
led = Pin(25, Pin.OUT) # Pico 板載 LED 在 GP25
while True:
led.toggle()
time.sleep(1) # 每 1 秒翻轉一次
Pin.irq(handler=None, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING)
設定外部中斷。電位變化時自動呼叫回呼函式。
handler:中斷回呼函式,必須接收一個Pin參數。trigger:觸發條件,可用|組合:
| 常數 | 含義 |
|---|---|
Pin.IRQ_FALLING | 下降緣 |
Pin.IRQ_RISING | 上升緣 |
Pin.IRQ_LOW_LEVEL | 低電位 |
Pin.IRQ_HIGH_LEVEL | 高電位 |
def on_press(pin):
print("按鍵被按下")
button = Pin(15, Pin.IN, Pin.PULL_UP)
button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)
PWM 類別
PWM(脈衝寬度調變)透過快速開關來模擬中間的電壓值,常用於調光、調速、伺服馬達控制。
machine.PWM(pin, freq=..., duty_u16=...)
在指定腳位上建立 PWM 輸出,pin 是 Pin 物件。
常用方法
| 方法 | 作用 |
|---|---|
PWM.freq([value]) | 讀取/設定頻率,單位 Hz,範圍約 8 Hz – 62.5 MHz(CPU 125 MHz 時) |
PWM.duty_u16([value]) | 讀取/設定工作週期,取值 0–65535,代表 value / 65535 的比例 |
PWM.duty_ns([value]) | 讀取/設定一個週期內的高電位時長,單位 ns |
PWM.deinit() | 關閉 PWM 輸出 |
注意
duty_u16的上限是 65535,不是 65536。寫 65536 會溢位。
RP2040 有 8 組獨立的 PWM 切片,每組 2 個通道,共 16 路。同一組的兩個通道必須共用頻率,但可以有不同工作週期。
例:呼吸燈
from machine import Pin, PWM
import time
led = PWM(Pin(25))
led.freq(1000) # 1 kHz
duty = 0 # 工作週期百分比
step = 1
while True:
duty += step
if duty >= 100:
duty = 100
step = -1
elif duty <= 0:
duty = 0
step = 1
# 百分比換算成 0-65535,注意別越界
led.duty_u16(int(duty / 100 * 65535))
if duty % 5 == 0:
print(duty) # 方便繪圖觀察
time.sleep(0.01) # 約 2 秒一個來回
例:按鍵點燈(含軟體防彈跳)
from machine import Pin
import time
button = Pin(15, Pin.IN, Pin.PULL_UP) # 按下時讀到 0
led_board = Pin(25, Pin.OUT) # 板載 LED
led_ext = Pin(16, Pin.OUT) # 外接 LED
while True:
led_ext.off()
if button.value() == 0: # 可能按下
time.sleep(0.01) # 等 10 ms 再確認,濾掉彈跳
if button.value() == 0: # 確認按下
led_board.toggle()
led_ext.on()
print("The button is pressed.")
while button.value() == 0: # 等待放開
time.sleep(0.01)
機械按鍵在按下和放開的瞬間會產生毫秒級的電位彈跳,被 CPU 讀成多次按鍵。軟體防彈跳的做法是:偵測到按下後延時 10 ms 再確認一次。
ADC 類別
ADC(類比數位轉換)把類比電壓轉成數位量。
machine.ADC(id)
id 可以是 Pin 物件,也可以是通道號:
- Pico 上通道 0–3 對應 GP26–GP29(GP29 板載接 VSYS);
- 通道 4 是晶片內建溫度感測器,可用
ADC.CORE_TEMP表示。
ADC.read_u16()
讀取轉換結果,回傳 0–65535 的整數,對應電壓範圍 0–3.3 V。
from machine import ADC, Pin
adc = ADC(Pin(26)) # 也可以寫成 ADC(0)
value = adc.read_u16() # 0 - 65535
voltage = value / 65535 * 3.3 # 換算成電壓
print(voltage, "V")
注意量程是 0–65535。RP2040 的 ADC 硬體本身是 12 位元(0–4095),MicroPython 將它線性拉伸到 16 位元,所以末尾幾位沒有實際精度。
小結
| 場景 | 關鍵點 |
|---|---|
| 數位輸入輸出 | Pin(id, mode, pull),輸入用 value() 讀,輸出用 value() / on() / off() / toggle() |
| 中斷 | Pin.irq(handler, trigger),回呼必須帶一個 Pin 參數 |
| 調光/調速 | PWM(pin) + freq() + duty_u16(),工作週期上限 65535 |
| 讀類比量 | ADC(Pin(26)) + read_u16(),回傳 0–65535 |
| 按鍵彈跳 | 偵測到變化後延時 10 ms 再確認 |
贊助 / 我一個人打車六七十回家!


何時一樽酒,重與細論文。