PIO 中的赋值魔术,MOV 指令
前言
在普通编程语言中,mov 可以理解为“赋值指令”,将一个值从一个地方拷贝到另一个地方。在 RP2040 的 PIO 汇编语言中,mov 同样是数据传递的关键指令,但它操作的是 PIO 独有的几个寄存器。
在 PIO 中,你可以用 mov 把值从一个寄存器传到另一个寄存器,或者从一个常量设定某个寄存器状态。PIO 的寄存器包括:
x、y:通用寄存器
osr(Output Shift Register):主控写入 PIO 的数据在这里
isr(Input Shift Register):PIO 采集到的数据进入这里
pins:GPIO 当前状态(作为输入)
pc:程序计数器(一般不用动)
null:空目标,丢弃数据用
语法格式
mov <destination>, (op) <source>
参数 | 含义 |
---|---|
destination | 目标寄存器,如 x, y, isr, osr |
source | 来源寄存器或值,如 x, y, pins, osr, null |
op(可选) | 求反(按位求补),反转比特顺序 |
用法示例
1. 把 x 的值给 y:
mov(y, x)
用途:x 计数器计算完毕后,把值传给 y 用于下一步处理。
2. 从主控写入的 osr 中取值放到 x 中:
mov(x, osr)
用途:主控通过 .put() 写入一个值,PIO 用这个指令加载进 x。
注意:这条指令默认是阻塞的,如果 osr 没准备好,会停在这里等待。
3. 将当前引脚状态读到 isr 中:
mov(isr, pins)
用途:一次读取所有输入引脚状态(适用于并口采集等并发场景)
4. 把某个值清空:
mov(x, null)
用途:清空某个寄存器(实际作用是丢弃)
5. 将寄存器取反再传递(适用于补码或反相逻辑):
mov(x, invert(x))
用途:对信号进行反向处理,比如 PWM 输出反向控制
代码示例
from machine import Pin
from rp2 import StateMachine
import time# PIO 程序:取反 OSR 的值,送入 X 寄存器,再写入 ISR 推送出去
@rp2.asm_pio()
def not_example():pull(block) # 从主控获取数据mov(x, osr) # 把 osr 的值放入 xmov(x, invert(x)) # 对 x 按位取反mov(isr, x) # 将 x 放入 isrpush(block) # 推送 isr 值# 创建状态机
sm = StateMachine(0, not_example, freq=2000)
sm.active(1)# 发送一个测试值,比如 0xAAAAAAAA(101010...)
input_val = 0xAAAAAAAA
sm.put(input_val)
time.sleep(0.01)
result = sm.get()print(f"输入值: 0x{input_val:08X}")
print(f"取反后: 0x{result:08X}")
程序输出
输入值: 0xAAAAAAAA
取反后: 0x55555555
与 set 的区别
指令 | 特点 | 用途 |
---|---|---|
set | 设置一个寄存器为常量(立即数) | 初始化常量,如 set x, 10 |
mov | 寄存器间或从特殊寄存器传值 | 动态传值,如 mov x, osr |
结论:
-
set:静态赋值
-
mov:动态传递
总结
mov 在 PIO 中的意义远超简单的“赋值”,它是串起主控与状态机之间沟通的桥梁,是 PIO 灵活处理控制逻辑的核心指令之一。
掌握了 mov,你就能玩转:
主控数据驱动 PIO(如动态 PWM、协议适配)
多寄存器交互(如延时、复位、反向处理)
多状态机协同(配合 irq 与 mov isr/pins)
注:
测试PC(Program Counter)这个,始终返回的是0,我用的micropython是1.24版,据查询资料,可能是官方为了性能等原因考虑,没有提供该功能(pico提供,micropython未实现),未验证。