项目介绍
本次参加硬禾推出全新RP2350B核心开发板,芯片主控是RP2350B,相对于PR2040在资源和引脚都有很大的提升。本次采用STEP_RP2350B核心板+扩展底板完成一个音乐播放器设计。
硬件介绍
STEP_RP2350B核心板采用DIP40封装,支持小脚丫FPGA外设扩展板的大部分功能,板上有10颗单色LED、2颗三色彩灯、4个按键、4个开关、2个数码管以及一个姿态传感器,并有SWD调试端口,采用蛇形排孔,方便在无焊接的情况下进行扩展。
核心板板载资源
板载8颗单色LED
2个三色LED,
使用了两颗74HC595实现2个7段数码管显示
使用个一个ADC实现4个拨码开关,4个轻触按键的判断。
扩展底板板载资源
扩展底板的资源非常丰富
1.简易波形发生器:通过R-2R阶梯网络生成0-2MHz的任意波形。
2.板上有一颗SPI接口的串行ADC,可以采集电位计上的电压,通过旋转电位计,可以观察采集到的电压值的变化;
3.温度传感器:板载DS18B20单总线采集温度传感器;
4.屏幕交互:板上采用了一块128*32分辨率的OLED作为信息显示。
5.音频输出:上板载使用三极管驱动的蜂鸣器,可以通过PWM来实现声音的输出,比如播放音乐、声音报警等;
6.通信交互:板载USB-UART芯片CH340C,能够实现FPGA和上位机PC的通信;
方案框图
本期我通过以上的硬件实现一个简易音乐播放器功能
任务要求:
- 通过PWM产生不同的音调,并驱动板上蜂鸣器将音调输出
- 能够播放三首不同的曲子,可以切换播放
- 曲子的切换使用核心板上的按键,需要有按键消抖的功能
- 播放的曲子的名字在OLED屏幕上显示出来(汉字显示)
因此接下来我在软件层面需要驱动蜂鸣器,ADC按键识别,OLED屏幕驱动。
设计思路
得到任务之后,首先从驱动开始。
我们先要完成的是硬件的驱动,本次任务有三个功能,
- ADC读取实现按键功能
- PWM引脚输出实现蜂鸣器播放功能
- SPI协议实现OLED屏幕显示功能
- 通过状态机实现不同音乐的切换
因此我们要学习RP2350如何实现ADC的电压读取,PWM音乐的播放,OLED屏幕的显示,中文字符的取模
关键代码说明
通过ADC读取引脚上的电压,根据原理图电阻的配置,按下不同的按键输出不同的电压值,从而判断哪个按键按下
adc = analogio.AnalogIn(board.GP47)
def get_voltage(raw):
return (raw * 3.3) / 65535
def get_button(voltage):
if 2.75 < voltage < 2.85:
return 1
elif 2.60 < voltage < 2.70:
return 2
elif 2.20 < voltage < 2.40:
return 3
elif 1.40 < voltage < 1.60:
return 4
else:
return 0
OLED采用软件SPI模拟实现,通过引入adafruit_ssd1306 库实现oled的配置
from adafruit_ssd1306 import SSD1306_SPI
代码主要包括配置引脚模式,配置引脚号,再进行初始化
class SoftSPI:
def __init__(self, sck, mosi, miso=None):
self.sck = digitalio.DigitalInOut(sck)
self.mosi = digitalio.DigitalInOut(mosi)
self.sck.direction = digitalio.Direction.OUTPUT
self.mosi.direction = digitalio.Direction.OUTPUT
self._locked = False
def configure(self, **kwargs):
return self
def try_lock(self):
if not self._locked:
self._locked = True
return True
return False
def unlock(self):
self._locked = False
def write(self, buffer):
for byte in buffer:
for i in [7, 6, 5, 4, 3, 2, 1, 0]: # MSB first
self.sck.value = False
self.mosi.value = (byte >> i) & 0x01
self.sck.value = True
# 初始化OLED引脚
dc_pin = digitalio.DigitalInOut(board.GP42)
reset_pin = digitalio.DigitalInOut(board.GP43)
cs_pin = digitalio.DigitalInOut(board.GP41)
# 创建软件SPI对象
spi = SoftSPI(board.GP45, board.GP44) # sck, mosi
# 初始化OLED屏幕
oled = SSD1306_SPI(
width=128,
height=32,
spi=spi,
dc=dc_pin,
reset=reset_pin,
cs=cs_pin
)
PWM音乐播放实现音乐中不同的频率实现不同的音调
# === 蜂鸣器 ===
buzzer = pwmio.PWMOut(board.GP20, duty_cycle=0, frequency=440, variable_frequency=True)
def start_note(freq):
buzzer.frequency = freq
buzzer.duty_cycle = 0x8000
def stop_note():
buzzer.duty_cycle = 0
软件流程
本次代码是在 CircuitPython 框架下开发上,使用开发板, 使用蜂鸣器播放音乐,通过按钮实现音频的切换和状态,并通过OLED 屏幕显示状态音乐名称。
初始化阶段
- 初始化 OLED 显示屏,通过自定义汉字字模显示“音乐播放器”欢迎界面。
- 初始化 ADC 用于电压读取、按键识别。
- 初始化 PWM 蜂鸣器用于发声。
- 软件 SPI 驱动 OLED。
主循环逻辑(事件轮询)
- 不断读取 ADC 电压,通过预设电压范围判断按键类型:
- 按钮1:上一首
- 按钮2:下一首
- 按钮3:播放 / 暂停
- 按钮4:停止播放
- 根据按钮动作,切换当前曲目、更新 OLED 显示、播放状态控制。
音乐播放机制
- 非阻塞式播放:记录每个音符的开始时间、持续时间,在主循环中轮询判断是否应进入下一个音符。
- 使用
buzzer.frequency
控制频率,用duty_cycle
控制响度,播放对应旋律。 - 支持暂停、恢复、停止播放。
OLED 显示逻辑
- 在切歌、暂停、播放、停止等操作后,根据状态刷新显示内容。
- 使用 16x16 汉字点阵字模进行中文渲染
启动后:显示“音乐播放器”。
按下按钮:
- 按钮1:切换到上一首,立即开始播放。
- 按钮2:切换到下一首,立即开始播放。
- 按钮3:
- 若未播放,则开始播放当前曲目;
- 若播放中,则暂停;
- 若暂停中,则恢复播放。
- 按钮4:停止播放。
播放中:音符依次按节奏播放,OLED 保持当前歌曲名显示。
暂停时:OLED 显示“暂停”,蜂鸣器静音。
停止时:OLED 显示“停止”,播放进度清零。
实物功能展示图及说明
软件运行后显示当前任务的标题,并开始检测按键是否按下。
当点击第二个按键表示下一曲,开始播放第一首歌。
点击第一个按键可实现上一首音频的播放
通过第三个按键可实现音乐当前播放进度的暂停,再次点击可从暂定的地方继续播放。
对本次活动的心得体会
本次活动使用了 PR2350 核心板与配套底板,使用Python实现简易的音乐播放器功能,本次的新品非常值得学习,本次活动虽然完成了任务,但期间还有很多外设和功能没有学习,今后会在这款板子上继续开发,实现数码管驱动,波形显示,数据采集等功能,感谢电子森林提供的硬件平台与技术支持,使我们在实践中收获颇丰。