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 再确认 |
赞助 / 我一个人打车六七十回家!


何时一樽酒,重与细论文。