RPi Pico使用blink_1Hz程序IRQ做时钟计数器异常求助
问题解决:RPi Pico PIO状态机IRQ仅触发一次的问题
问题场景
使用RPi Pico搭建时钟,参考官方blink_1hz.py程序,想用其1秒IRQ中断作为时钟计数器。原程序每秒能正确打印系统时间,但将IRQ中的lambda函数替换为自定义计数函数secs()后,程序仅打印一次而非预期的十次,全局变量t也未递增。
错误核心点
原代码中设置IRQ处理程序的语句存在问题:
sm.irq(handler = secs()) # 仅打印一次secs
问题原因
- 函数调用错误:写
secs()时是立即执行该函数,把函数返回值(None,因为secs无return语句)传给了handler参数,而非传入函数本身作为中断回调 - 参数缺失:PIO状态机的IRQ处理函数需要接收一个参数(触发IRQ的状态机对象),原
secs函数无参数,后续触发时会直接报错
修正后的完整代码
# Example using PIO to blink an LED and raise an IRQ at 1Hz. import time from machine import Pin import rp2 @rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) def blink_1hz(): # Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000 irq(rel(0)) set(pins, 1) set(x, 31) [5] label("delay_high") nop() [29] jmp(x_dec, "delay_high") # Cycles: 1 + 7 + 32 * (30 + 1) = 1000 set(pins, 0) set(x, 31) [6] label("delay_low") nop() [29] jmp(x_dec, "delay_low") def secs(p): # 添加参数接收触发IRQ的状态机对象 global t t = t+1 print("secs",t) t = 0 # 创建状态机,输出引脚25 sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25)) # 修正:传入函数引用而非调用函数 sm.irq(handler=secs) # 启动状态机 sm.active(1) time.sleep(10) # 停止状态机 sm.active(0) print("main",t)
关键修正说明
- 将
sm.irq(handler = secs())改为sm.irq(handler=secs):传递函数本身作为中断回调,而非立即执行函数 - 给
secs函数添加参数p:匹配PIO状态机IRQ触发时的参数传递要求,确保回调能正常执行
内容的提问来源于stack exchange,提问作者Guus van der wal
相关产品推荐
相关产品推荐

