Pico PIO 中断开发:原理、时序与实战全解析
示例代码如下:
# Python env : MicroPython v1.23.0
# -*- coding: utf-8 -*-
# @Time : 2024/7/28 上午10:32
# @Author : 李清水
# @File : main.py
# @Description : PIO类实验,在PIO程序中使用irq指令触发中断,并打印中断标志位
# ======================================== 导入相关模块 ========================================
# 导入时间相关的模块
import time
# 导入RP2040相关的模块
import rp2
# ======================================== 全局变量 ============================================
# ======================================== 功能函数 ============================================
# irq_test() 函数使用 rp2.asm_pio() 装饰器定义了一个 PIO(Programmable I/O)程序
@rp2.asm_pio()
def irq_test() -> None:
"""
定义一个用于测试中断的 PIO 程序。
Args:
None
Returns:
None
Description:
该 PIO 程序通过执行 nop 指令和触发中断来测试中断功能。
程序会依次触发状态机 0 和状态机 1 的中断,并在每次中断后插入延迟。
"""
# 标记了程序的开始位置
wrap_target()
# 4 个 nop() 无操作指令,每个指令都有 31 个时钟周期的延迟
nop() [31]
nop() [31]
nop() [31]
nop() [31]
# 触发状态机 0 的中断
irq(0)
# 4 个 nop() 无操作指令,每个指令都有 31 个时钟周期的延迟
nop() [31]
nop() [31]
nop() [31]
nop() [31]
# 触发状态机 1 的中断
irq(1)
# 标记了程序的结束位置,并返回到开始位置
wrap()
# 转为固定位数的二进制数据
def to_bin(value: int, num: int) -> str:
"""
将一个十进制数转为固定位数的二进制数。
Args:
value (int): 需要转换的十进制数。
num (int): 二进制数的固定位数。
Returns:
str: 转换后的二进制字符串。
"""
# 初始化一个空字符串 bin_chars 来存储最终的二进制数据
bin_chars = ""
# 将原始的十进制数 value 保存到一个临时变量 temp 中
temp = value
# 进行 num 次循环
for i in range(num):
# 获取 temp 除以 2 的余数,即二进制数的最后一位,转换为字符串并赋值给 bin_char
bin_char = bin(temp % 2)[-1]
# 将 temp 除以 2 (整除),得到新的值赋值给 temp
temp = temp // 2
# 将 bin_char 拼接到 bin_chars 的开头,建立正确的二进制位顺序
bin_chars = bin_char + bin_chars
# 返回转换后的二进制字符串 bin_chars,并将其转换为大写形式
return bin_chars.upper()
# ======================================== 自定义类 ============================================
# ======================================== 初始化配置 ==========================================
# 上电延时3s
time.sleep(3)
# 打印调试信息
print("FreakStudio: PIO IRQ Test")
# 设置了一个 lambda 函数作为 PIO 0 的中断处理程序。当发生 IRQ 时,该函数会打印中断标志位和中断标志位对应的二进制数(12位宽)
rp2.PIO(0).irq(lambda pio: print(pio.irq().flags(),to_bin(pio.irq().flags(),12)))
# 创建了一个状态机,将 irq_test() 函数作为程序,并设置频率为 系统时钟/2000 Hz
sm = rp2.StateMachine(0, irq_test, freq=2000)
# ======================================== 主程序 ===========================================
# 启动状态机
sm.active(1)
# 等待 5 秒
time.sleep(5)
# 停止状态机
sm.active(0)
这里,在 PIO0 的中断处理程序部分:
# 设置了一个 lambda 函数作为 PIO 0 的中断处理程序。当发生 IRQ 时,该函数会打印中断标志位和中断标志位对应的二进制数(12位宽)
rp2.PIO(0).irq(lambda pio: print(pio.irq().flags(),to_bin(pio.irq().flags(),12)))
在这里,pio 是 lambda 函数的参数,表示传入的 PIO 实例,其后为表达式部分:
pio.irq()获取当前 PIO 的中断对象,.flags()是中断对象的一个方法,返回当前的中断标志位;to_bin()是一个自定义函数,用于将整数转换为固定位数的二进制字符串
即每次中断都会打印中断标志位的十进制值和中断标志位的 12 位二进制字符串。
将代码烧录到 Pico 中,远程连接中断,数据输出如下:


我们来看一下 PIO0 的中断掩码输出寄存器:

可以看到:
- 512 对应二进制数据为
0b001000000000,表示SM1产生中断 - 256 对应二进制数据为
0b000100000000,表示SM0产生中断

即每次中断都会打印中断标志位的十进制值和中断标志位的 12 位二进制字符串。
将代码烧录到 `Pico` 中,远程连接中断,数据输出如下:
浙公网安备 33010602011771号