内容介绍
内容介绍
1、功能要求
上电开机显示PWM Music Player,按下任意按键时,会根据对应的设定播放不同音调,按键是通过ADC进行判断是哪一个按键按下的,再通过PWM驱动蜂鸣器播放不同音调,并支持按键切换歌曲和OLED显示曲名,使用的是CircuitPython固件代码。代码中按键消抖、PWM控制、OLED显示和音频播放逻辑。
2、硬件引脚
蜂鸣器:PWM输出引脚:GP20(驱动),frequency=44000
按键:ADC引脚GP47(通过ADC检测按键,需配置为电阻分压模式)
按键工作电压分别是1.6V,2.5V,2.75V,3.0V
OLED SPI引脚:
SCK: 45,MOSI: 44,RES: 43,DC: 42,CS: 41.
3、软件框架图

4、代码:
下面的代码是音频音调
# 音符频率(Hz)
notes = {
'C4': 262, 'D4': 294, 'E4': 330, 'F4': 349,
'G4': 392, 'A4': 440, 'B4': 494,
'C5': 523, 'D5': 587, 'E5': 659, 'F5': 698,
'G5': 784, ' ': 0
}
# 生日快乐
melody_birthday = [
'G4', 'G4', 'A4', 'G4', 'C5', 'B4', ' ', ' ',
'G4', 'G4', 'A4', 'G4', 'D5', 'C5', ' ', ' ',
'G4', 'G4', 'G5', 'E5', 'C5', 'B4', 'A4', ' ',
'F5', 'F5', 'E5', 'C5', 'D5', 'C5', ' ', ' '
]
# 欢乐颂
melody_joy = [
'E4', 'E4', 'F4', 'G4', 'G4', 'F4', 'E4', 'D4',
'C4', 'C4', 'D4', 'E4', 'E4', 'D4', 'D4', ' ',
'E4', 'E4', 'F4', 'G4', 'G4', 'F4', 'E4', 'D4',
'C4', 'C4', 'D4', 'E4', 'D4', 'C4', 'C4', ' '
]
# 两只老虎
melody_tiger = [
'C4', 'D4', 'E4', 'C4', 'C4', 'D4', 'E4', 'C4',
'E4', 'F4', 'G4', 'E4', 'F4', 'G4', ' ', ' ',
'G4', 'A4', 'G4', 'F4', 'E4', 'C4', 'G4', 'A4', 'G4', 'F4', 'E4', 'C4', ' ',
'C4', 'C4', 'C4', ' ', 'C4', 'C4', 'C4', ' '
]
PWM引脚与ADC相关的代码
# 蜂鸣器PWM输出 - 使用GP20
buzzer = pwmio.PWMOut(board.GP20, duty_cycle=0, frequency=44000, variable_frequency=True)
# 初始化ADC用于按钮检测
adc = analogio.AnalogIn(board.GP47)
# 按键ADC值范围 (根据实际测量调整)
BUTTON_RANGES = [
(10000, 20000), # 按钮0 (停止)
(30500, 32000), # 按钮1 (歌曲1)
(30500, 33000), # 按钮2 (歌曲2)
(30500, 34000) # 按钮3 (歌曲3)
]
软件SPI代码和OLED
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优先
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,
cs=cs_pin,
reset=reset_pin
)
显示字体代码
FONT_SHENG = [
0x01,0x00,0x11,0x00,0x11,0x00,0x11,0x00,
0x3F,0xFC,0x21,0x00,0x41,0x00,0x81,0x00,
0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,
0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00
] # 生
FONT_RI = [
0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10
] # 日
FONT_KUAI = [
0x10,0x40,0x10,0x40,0x10,0x40,0x13,0xF8,
0x18,0x48,0x54,0x48,0x50,0x48,0x50,0x48,
0x97,0xFE,0x10,0x40,0x10,0xA0,0x10,0xA0,
0x11,0x10,0x11,0x10,0x12,0x08,0x14,0x06
] # 快
FONT_LE = [
0x00,0x20,0x00,0xF0,0x1F,0x00,0x10,0x00,
0x11,0x00,0x21,0x00,0x21,0x00,0x3F,0xFC,
0x01,0x00,0x09,0x20,0x09,0x10,0x11,0x08,
0x21,0x04,0x41,0x04,0x05,0x00,0x02,0x00
] # 乐
FONT_HUAN = [
0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,
0x1F,0xF0,0x10,0x10,0x10,0x10,0x1F,0xF0,
0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,
0x10,0x10,0x1F,0xF0,0x10,0x10,0x00,0x00
] # 欢
FONT_SONG = [
0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,
0x3F,0xF8,0x20,0x08,0x20,0x08,0x3F,0xF8,
0x20,0x08,0x20,0x08,0x3F,0xF8,0x20,0x08,
0x20,0x08,0x3F,0xF8,0x20,0x08,0x00,0x00
] # 颂
FONT_LIANG = [
0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,
0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,
0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,
0x20,0x08,0x3F,0xF8,0x20,0x08,0x00,0x00
] # 两
FONT_ZHI = [
0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0x1F,0xF0,0x10,0x10,0x00,0x00
] # 只
FONT_LAO = [
0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,
0x10,0x10,0x1F,0xF0,0x10,0x10,0x10,0x10,
0x10,0x10,0x1F,0xF0,0x10,0x10,0x10,0x10,
0x10,0x10,0x1F,0xF0,0x10,0x10,0x00,0x00
] # 老
FONT_HU = [
0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,
0x20,0x08,0x3F,0xF8,0x20,0x08,0x20,0x08,
0x20,0x08,0x3F,0xF8,0x20,0x08,0x20,0x08,
0x20,0x08,0x3F,0xF8,0x20,0x08,0x00,0x00
] # 虎
主循环代码
# 主循环
def main():
current_song = 0 # 0=停止, 1=生日, 2=欢乐颂, 3=两只老虎
is_playing = False
last_button = None
# 初始显示
show_song_title(current_song)
while True:
button = get_button_pressed()
if button is not None and button != last_button:
last_button = button
if button == 0: # 停止
stop_music()
current_song = 0
is_playing = False
print("音乐停止")
elif button == 1: # 生日快乐
stop_music()
current_song = 1
is_playing = True
print("播放生日快乐")
elif button == 2: # 欢乐颂
stop_music()
current_song = 2
is_playing = True
print("播放欢乐颂")
elif button == 3: # 两只老虎
stop_music()
current_song = 3
is_playing = True
print("播放两只老虎")
show_song_title(current_song)
# 播放音乐
if is_playing:
if current_song == 1:
play_song(melody_birthday)
elif current_song == 2:
play_song(melody_joy)
elif current_song == 3:
play_song(melody_tiger)
time.sleep(0.1)
if __name__ == "__main__":
main()
OLED初始化:使用SPI接口初始化OLED屏幕,显示“PWM Music Player”和当前播放歌曲名。
PWM输出:通过GP20引脚输出PWM信号驱动蜂鸣器。
按键检测:通过ADC检测按键值,使用debounce_key函数实现消抖。
4、文字取模

取模方式更改为逐行式,尺寸为16*16,格式需要为C51,取模走向为顺向。
5.演示操作图
待机界面

播放音频欢乐颂

播放音频两只老虎

播放生日快乐

6.设计流程

总结:
从这个任务,其实我从中还是学到了不少的东西,特别是软件SPI,这个之前我一直在研究,连屏都点不亮,最终是朋友的指导,细心的讲解了要点,才把屏驱动 起来,其次是这个音调,从来没有想过,用2350这个能实现音频声音的发出,只听说过能用蜂鸣器能播放音乐,没想到自己也能实现,总的来说还是收获满满,又前进了一小步。
附件下载
main1.py
团队介绍
个人
评论
0 / 100
查看更多
猜你喜欢
基于STEP PICO的音乐播放器这是一个关于基于SETP PICO的音乐播放器的项目报告。其中详细介绍了开发环境、硬件平台、实现的功能以及音乐播放的具体实现方法。
Gary
2564
Tangara音乐播放器一款便携式音乐播放器。 它通过 3.5 毫米耳机插孔或蓝牙输出高品质声音,电池续航时间长,并且包含一个强大的处理器,足以支持您可以使用的任何音频格式。 它也是运行开源软件的 100% 开放硬件,这使得定制、修复和升级变得容易。
refdesignshare
1832
基于RP2350B实现音乐播放器该项目使用了RP2350B核心板、综合技能训练板,实现了音乐播放器的设计,它的主要功能为:PWM播放音乐,按键切换曲目,OLED屏幕显示歌曲名。
FuShenxiao
305