class PIO —— 高级 PIO 用法

PIO 类封装了 RP2040 两个可编程 I/O(PIO)块中的一个。每个 PIO 块包含一段由四个独立状态机共享的指令内存(32 条指令),外加每个状态机的专用 FIFO 接口和一个 IRQ 控制器。

大多数脚本通过 StateMachine 与 PIO 交互——本类用于需要执行以下操作的高级用例:

  • 通过 add_program() / remove_program() 显式加载和移除程序。

  • 通过 gpio_base() 在芯片的 32 引脚窗口范围内移动 PIO 的 GPIO 基址。

  • 通过 irq() 挂接到块级 IRQ 标志。

有关汇编 PIO 程序的内容,请参见 rp2.asm_pio()

构造函数

class rp2.PIO(id: int)

返回由 id 标识的 PIO 块的单例 PIO 对象。RP2040 有两个 PIO 块,编号为 01。对于任何其他 id 都会引发 ValueError

方法

gpio_base(base: machine.Pin | int | None = None, /) int

获取或设置此 PIO 块的 GPIO 基址。

RP2040 PIO 看到的是 GPIO 空间中的一个 32 引脚窗口;该窗口可以从 GPIO0 或 GPIO16 开始。基址控制此 PIO 上所有状态机当前生效的窗口。

不带参数时,返回当前基址(GPIO 引脚号,016)。

带参数时,设置基址。base 可以是 machine.Pin 实例或整数引脚号,并且必须解析为 GPIO0 或 GPIO16。基址必须在此 PIO 块上添加任何程序或构造任何状态机之前设置。

add_program(program: Callable) None

program 加载到此 PIO 的指令内存中。生成的内存布局会在此 PIO 块上的所有状态机之间复用。

每个 PIO 只有 32 条指令的程序内存,由所有程序共享;如果新程序放不下,此方法会引发 OSError(ENOMEM)。同一个程序可以加载到两个 PIO 实例上,但它们各自占用独立的内存区域。

remove_program(program: Callable | None = None, /) None

从此 PIO 的指令内存中移除 program,为新程序释放空间。如果省略 program,则移除当前加载在此 PIO 上的所有程序。

移除一个未加载的程序属于空操作(不会引发异常)。

state_machine(id: int, program: Callable | None = None, *args, **kwargs) StateMachine

返回此 PIO 块所拥有的四个 StateMachine 实例之一。id 是本地状态机索引(0 —— 3)。

如果提供了 program,则配置状态机来运行它——所有位置参数/关键字参数都会转发给 StateMachine.init()

示例:

>>> rp2.PIO(1).state_machine(3)
StateMachine(7)

返回对象的全局状态机 ID 为 pio_id * 4 + sm_id

irq(handler: Callable[[PIO], None] | None = None, trigger: int = IRQ_SM0 | IRQ_SM1 | IRQ_SM2 | IRQ_SM3, hard: bool = False) Callable

获取或配置此 PIO 的块级 IRQ。

handler 是当任何被请求的状态机 IRQ 锁存时触发的回调。该处理函数接收此 PIO 实例作为其唯一参数;在处理函数内部,可以通过 self.irq().flags()IRQ_SM* 常量进行按位与运算来识别触发的状态机。

trigger 是一个或多个 IRQ_SM0 .. IRQ_SM3 的位掩码。默认情况下任何状态机都会触发。

hard=True 注册一个硬中断处理函数(回调中不进行堆分配)。

MicroPython 绑定了每个 PIO 块上的 IRQ 0;IRQ 1 是保留的,无法从 Python 访问。

常量

IN_LOW: int

传递给 asm_pio()out_init / set_init / sideset_init,使引脚以驱动为低电平的输入状态启动(即输出缓冲区保持 0 的三态)。

IN_HIGH: int

传递给 asm_pio()out_init / set_init / sideset_init,使引脚以输出缓冲区保持 1 的输入状态启动。

OUT_LOW: int

传递给 asm_pio()out_init / set_init / sideset_init,使引脚以逻辑 0 的驱动输出状态启动。

OUT_HIGH: int

传递给 asm_pio()out_init / set_init / sideset_init,使引脚以逻辑 1 的驱动输出状态启动。

SHIFT_LEFT: int

传递给 asm_pio()StateMachine.init()in_shiftdir / out_shiftdir,使移位将位向 MSB 方向移动。

SHIFT_RIGHT: int

传递给 asm_pio()StateMachine.init()in_shiftdir / out_shiftdir,使移位将位向 LSB 方向移动。

JOIN_NONE: int

传递给 asm_pio()fifo_join,使状态机拥有独立的 4 字 TX 和 RX FIFO(默认值)。

JOIN_TX: int

传递给 asm_pio()fifo_join,通过吸收 RX FIFO 将 TX FIFO 加倍到 8 字。此状态机将无法再接收数据。

JOIN_RX: int

传递给 asm_pio()fifo_join,通过吸收 TX FIFO 将 RX FIFO 加倍到 8 字。此状态机将无法再发送数据。

IRQ_SM0: int

irq() trigger 标志:状态机 0 触发了它的 IRQ。

IRQ_SM1: int

irq() trigger 标志:状态机 1 触发了它的 IRQ。

IRQ_SM2: int

irq() trigger 标志:状态机 2 触发了它的 IRQ。

IRQ_SM3: int

irq() trigger 标志:状态机 3 触发了它的 IRQ。