RP2040自定义板MicroPython中嵌套UART引脚中断实现问题求助
在RP2040 MicroPython上实现无阻塞UART中断的正确方法
针对你的场景,核心问题在于中断回调的上下文限制和核心资源抢占,以下是两种可行的解决思路:
方案一:优化核心任务分配(无需额外引脚中断)
放弃用第二个引脚中转中断的方案,直接利用_thread模块将UART命令处理放到Core1,同时在Core1的循环中加入短暂休眠,避免抢占定时器资源:
from machine import UART, Pin import _thread import utime # 初始化UART uart = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5)) rx_pin = Pin(5, Pin.IN) # 全局标志位与锁 rx_trig = False lock = _thread.allocate_lock() # RXD引脚中断回调(仅设置标志) def on_uart_rx(pin): global rx_trig with lock: rx_trig = True # Core1的命令处理循环 def core1_task(): global rx_trig while True: with lock: if rx_trig: # 读取UART数据并处理命令 if uart.any(): data = uart.read() # 替换为你的命令处理逻辑 print(f"Received command: {data}") rx_trig = False # 主动让出CPU时间,避免阻塞Core0的定时器 utime.sleep_ms(1) # 注册RXD上升沿中断 rx_pin.irq(trigger=Pin.IRQ_RISING, handler=on_uart_rx) # 启动Core1任务 _thread.start_new_thread(core1_task, ()) # Core0的主逻辑(含定时器任务) while True: # 替换为你的定时器相关代码 utime.sleep(1) print("Core0 timer tick")
方案二:用PIO实现硬件级UART接收中断(更可靠)
RP2040的PIO可独立处理UART接收,不受CPU核心调度影响,适合低延迟场景:
from machine import Pin import rp2 import utime # PIO程序:接收UART字节后触发中断 @rp2.asm_pio() def uart_rx(): # 配置UART波特率适配(基于125MHz时钟,9600波特) set(x, 130) set(y, 12) label("bit_loop") wait(0, pin, 0) # 等待起始位 wait(1, pin, 0) # 跳过起始位 in_(pins, 1) # 读取数据位 jmp(x_dec, "bit_loop") # 循环读取8位 irq(block, 0) # 触发中断 # 初始化PIO状态机 sm = rp2.StateMachine(0, uart_rx, freq=125000000, in_base=Pin(5)) # PIO中断回调 def on_pio_rx(sm): data = sm.get() >> 24 # 提取接收到的字节 # 替换为你的命令处理逻辑 print(f"PIO received: {chr(data)}") # 注册PIO中断 sm.irq(on_pio_rx) # 启动状态机 sm.active(1) # Core0主逻辑(含定时器) while True: utime.sleep(1) print("Core0 timer tick")
关键注意事项
- 中断回调函数必须极简,不能包含耗时操作(如串口打印、复杂计算),否则会阻塞其他中断或定时器。
- 若坚持用引脚中转方案,需确保cmdPin的中断优先级高于RXD,且回调仅做设置标志的操作,而非直接触发电平变化。
- RP2040的MicroPython定时器默认运行在Core0,Core1的任务必须通过
utime.sleep_ms()主动让出CPU时间,避免抢占资源。
内容的提问来源于stack exchange,提问作者Aaditya Dengle
相关产品推荐
相关产品推荐

