在树莓派 Pico 上用 MicroPython 时,rp2 端口的固件只支持“虚拟定时器”(也叫软定时器),也就是 machine.Timer 里 id 固定为 -1 的那一只;硬件定时器(id 从 0 起)在 Pico 上没有开放给 Python。
因此“全部用法”其实就是围绕 这一只虚拟定时器 的几种典型玩法,归纳如下:
from machine import Timer on_tick 要先定义好):tim = Timer(-1) # 创建计时器对象,或 Timer() 留空也默认 -1
tim.init(period=500, # 周期,单位毫秒
mode=Timer.PERIODIC, # PERIODIC 周期性重复,ONE_SHOT 只执行一次
callback=on_tick) # 到点调用哪个函数;这一句执行完定时器就启动了
tim.deinit() # 停止定时器
回调函数 回调函数必须带一个形参(定时器对象本身),例如:
def toggle(t): # t 就是触发它的 Timer 实例
led.value(not led.value())
sleep 阻塞。# ============ 接线 ============
# 本段用板载 LED(Pin 25),不需要外接元件
# =============================
from machine import Pin, Timer # 导入 GPIO 和定时器模块
import time
led = Pin(25, Pin.OUT) # 创建板载 LED 对象
def blink(timer_obj): # 回调函数,参数必须是定时器自身
led.value(not led.value()) # 每进来一次就把 LED 电平翻转
t = Timer(-1) # 申请系统软定时器,编号固定 -1
t.init( # 初始化定时器
period=100, # 周期 100 毫秒
mode=Timer.PERIODIC, # 模式设为“周期性”
callback=blink) # 时间到就调用 blink 函数
# 主循环可以空转,也可以干别的事,LED 会自己闪
i = 0
while True:
print(i)
time.sleep(1)
i = i + 1
mode 设成 Timer.ONE_SHOT,到点执行一次后自动关闭,适合做“20 s 后关闭灯”这类场景。# ============ 接线 ============
# 本段用板载 LED(Pin 25),不需要外接元件
# =============================
from machine import Pin, Timer # 同样导入必要模块
led = Pin(25, Pin.OUT) # 板载 LED
def once_off(timer_obj): # 一次性定时器回调
led.off() # 时间到了关闭 LED
led.value(1) # 先打开灯
t = Timer(-1) # 新建一个软定时器
t.init( # 初始化成“一次性”
period=2000, # 延时 2000 毫秒
mode=Timer.ONE_SHOT, # 模式:只执行一次
callback=once_off)
# 主循环同样空转,等待执行
while True:
pass # 程序持续运行,不退出
t1 = Timer(-1); t1.init(period=500, mode=Timer.PERIODIC, callback=job1)
t2 = Timer(-1); t2.init(period=2000, mode=Timer.PERIODIC, callback=job2)
# ============ 接线 ============
# 板载 LED:不用外接
# 按键:一脚 → GP0,另一脚 → GND(开内部上拉,不用外接电阻)
# =============================
from machine import Pin, Timer
led = Pin(25, Pin.OUT) # 板载 LED
key = Pin(0, Pin.IN, Pin.PULL_UP) # 按键,内部上拉
timer = Timer(-1) # 软定时器对象先建好
# 消抖时间 150 ms,可视手感微调
DEBOUNCE_MS = 150
def real_handler(timer_obj):
"""真正的处理:只在消抖结束后调用一次"""
led.value(not led.value()) # 翻转 LED
def key_isr(pin_obj):
"""按键中断:只做一件事——启动一次性定时器"""
# 先关闭可能还在跑的定时器(防连续快速抖动重复触发)
timer.deinit()
# 重新初始化成一次性,到点后再执行 real_handler
timer.init(
period=DEBOUNCE_MS,
mode=Timer.ONE_SHOT,
callback=real_handler)
# 给按键注册下降沿中断
key.irq(trigger=Pin.IRQ_FALLING, handler=key_isr)
# 主循环空转,系统全靠中断+定时器干活
while True:
pass
运行效果:
按键每次 稳定按下(经过 150 ms 消抖窗口),LED 翻转一次;
快速抖动、机械弹跳都会被定时器过滤掉,不会误触发。
“看门狗”式刷新
周期定时器里定期喂狗、采样传感器或刷新屏幕,主循环只做高优先级事务,系统整体响应更快。
动态改周期 / 开关
运行中可随时 deinit() 再 init() 改参数,也可以先 tim.deinit() 关闭,等需要时再打开,节省一点 CPU。
# ============ 接线 ============
# 本段用板载 LED(Pin 25),不需要外接元件
# =============================
from machine import Pin, Timer # 导入必要模块
import time
led = Pin(25, Pin.OUT) # 创建板载 LED 对象
cnt = 0 # 全局计数器:记录已翻转次数
def blink(timer_obj): # 回调函数:每进来一次就翻转 LED 并计数
global cnt # 声明使用外部变量
led.value(not led.value()) # 翻转 LED
cnt += 1 # 次数 +1
t = Timer(-1) # 申请系统软定时器(编号固定 -1)
t.init( # 第一次初始化:慢闪模式 1000 ms 周期
period=1000, # 1000 毫秒
mode=Timer.PERIODIC, # 周期性
callback=blink) # 回调函数
while True: # 主循环:持续监控次数,到达 5 次就重设定时器
if cnt >= 5: # 已经闪了 5 次
t.deinit() # 先关闭旧定时器,释放资源
cnt = 0 # 计数器清零
t.init(
period=200, # 新周期 200 毫秒
mode=Timer.PERIODIC,
callback=blink) # 重新注册同一个回调
# 这里可以干别的事,不会被 sleep 阻塞
time.sleep_ms(50) # 给 CPU 一点喘息,防止 while 跑满
运行现象:
前 5 次翻转间隔 1000 ms(慢闪),随后自动变成每 200 ms 翻转一次(快闪),
全程只靠 deinit() → 改参数 → init() 完成,无需重启或重新导入。