文号
949983
阅读
527
回复
3
收藏
0
所有教程由网友发布,仅供参考,请谨慎采纳。科创不对教程的科学性、准确性、可靠性负责。
单片机RP2040学习之PIO入门
2026/05/08
IP:北京

用RP2040单片机一段时间了,最近测试了一下PIO,专门测试了一段简单代码,适合入门避坑,使用microPython(Thonny)编程开发。

首先拿到一个RP2040 Zero板,用USB线插电脑上,然后下载一个Thonny.exe,安装到电脑上。运行Thonny可以在编辑窗口或下方命令行写简单的Python代码如print并运行,这与单片机还没有关系,只是确认这个编辑器是正常的。然后需要向单片机boot状态下(按住boot键插USB,插好后释放boot键)的U盘中,拷入一个RPI_PICO-20260406-v1.28.0uf2这样的文件。等一会儿就可以在<运行><设置编辑器>里面,选RP2040,及相应的com连接,这样就搭建好了microPython开发系统。

可以测试一个简单的microPython代码,验证此开发系统正常,比如一个数字输出程序:

from machine import Pin

p5 = Pin(5, Pin)

p5.value(1)

运行此程序,可以测到5脚有高电平(可以直接插个LED在5脚和GND之间),把value值改成0,再运行就变成了低电平。

然后就可以测试PIO,一个简单的方波发生器:


from machine import Pin

from rp2 import PIO, asm_pio

machine.freq(280000000)

@asm_pio(set_init=rp2.PIO.OUT_LOW)

def blink():

set(pins, 1)

set(pins, 0)

sm = rp2.StateMachine(0, blink, freq=280000000, set_base=Pin(5))

sm1.active(1) #启动PIO

运行后在5脚能测到140MH方波。


from machine import Pin

from rp2 import PIO, asm_pio, StateMachine


machine.freq(100000000) #这句挺重要,网上很多例程没有这个设置,会导致信号上升或下降沿有+/-7ns的跳动,因为默认的CPU的freq与PIO的freq有可能不成整数比例关系

p2 = Pin(2, XXXXXX) #可用于外部输入触发,在wait()中用到

p4 = Pin(4, Pin.OUT) #用于同步软启动多通道


@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)

def pulse_gen():

wait(0, gpio, 4) # 等待4上升沿

wait(1, gpio, 4) # 出现4上升沿

mov(x, osr) # 加载延迟参数

label("delay_loop")

jmp(x_dec, "delay_loop") # 延时循环

wrap_target() #周期脉冲循环

set(pins, 1) [10] # 输出脉宽ON

set(pins, 0) [10] # OFF

wrap()

# 初始化4个状态机,对应5-8脚输出

for i in range(4):

sm = rp2.StateMachine(i, pulse_gen, freq=100000000, set_base=Pin(i+5))

sm.put(i*2) #设置信号间延迟

sm.active(1) #启动

p4.value(0)

p4.value(1) #4个状态机虽然已经启动,但是会处于等待wait(…,4),直到这里第4脚出现上升沿,因此这里提供了一个软启动用于同步。如果在wait(…,2)中等待的是2脚,那就是硬触发同步

通过这个例程,测试了几个基本功能,如多通道工作、信号延迟、软触发同步或硬触发同步,实现起来还比较容易。PIO还有很多其他功能,入门以后再深入研究就比较容易了。


[ 修改于5个月16天前 - 2026/05/17 12:08:40 ]
Tangshm作者
5个月25天前IP:北京
949984
1楼

在microPython开发系统下,使用file是可以存数据至单片机板上flash,不过我还没找到直接用USB可访问这些数据的办法(也就是设置成一个板载U盘),只能在Thonny窗口里面去open看flash上的数据,不让arduino IDE下设置成U盘方便

引用
评论
5个月11天前IP:山东
950213
2楼

老师,可以使用circuitPython固件,可以模拟一个fat格式的U盘

引用
评论(1)
5个月2天前IP:山东
950311
3楼

可以的,下面是我写的MP3播放器


import board

import audiopwmio

import audiomp3

import time

import microcontroller

import digitalio

import os

# ==================== 硬件配置 ====================

AUDIO_PIN = board.GP13 # 音频输出引脚

BUTTON_PIN = board.GP24 # 切歌按键(短接 GND 触发)

OVERCLOCK_FREQ_HZ = 150000000 # 超频以获得更流畅的解码

# ==================== 初始化按键(内置上拉,短接时为低电平) ====================

button = digitalio.DigitalInOut(BUTTON_PIN)

button.switch_to_input(pull=digitalio.Pull.UP)

# ==================== 扫描根目录下的 MP3 文件 ====================

def get_mp3_files():

files = []

for file in os.listdir("/"):

if file.lower().endswith(".mp3"):

files.append(file)

files.sort()

return files

playlist = get_mp3_files()

if not playlist:

# 没有歌曲时闪灯或仅保持静默,这里简单进入死循环

while True:

time.sleep(1)

current_index = 0

def next_song():

global current_index

current_index = (current_index + 1) % len(playlist)

# ==================== 主播放逻辑 ====================

microcontroller.cpu.frequency = OVERCLOCK_FREQ_HZ

audio_out = None

try:

audio_out = audiopwmio.PWMAudioOut(AUDIO_PIN)

while True:

mp3_file_name = playlist[current_index]

try:

with open(mp3_file_name, "rb") as mp3_file:

decoder = audiomp3.MP3Decoder(mp3_file)

audio_XXXXXXXXXXXXXXX(decoder)

button_last = button.value

while audio_out.playing:

# 检测按键下降沿(按下)

current_button = button.value

if button_last and not current_button:

audio_out.stop()

next_song()

# 等待按键释放,避免连续触发

while not button.value:

time.sleep(0.01)

time.sleep(0.2)

break # 退出内层循环,开始播放新歌

button_last = current_button

time.sleep(0.05) # 短延时,保证按键响应灵敏

else:

# 歌曲自然播放完毕,自动切下一首

next_song()

time.sleep(0.5)

except Exception as e:

# 单曲播放异常,等待 2 秒后尝试下一首

time.sleep(2)

next_song()

except Exception as e:

# 音频输出初始化失败,陷入死循环

while True:

time.sleep(1)

finally:

if audio_out:

audio_out.stop()

audio_out.deinit()

+1
科创币
Always_with_myself
2026/08/23
Star★ +1
引用
评论
3
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的