MIDI音乐播放器--STM32+蜂鸣器
1. 简介
之前使用micropython在ESP32C3上用自定义音符编码通过蜂鸣器播放了《敢问路在何方》,这种方式的缺点有下面几个:
- 需要手动按照自定义音符编码规则拿到编码字符串
- 音符固定,频率固定,只有单轨道。丢失了部分音乐的美感
恰逢最近在研究MIDI音乐文件,发现MIDI音乐文件里完美的包含了让蜂鸣器发声的所有元素。如果能通过实时解析MIDI音乐文件将音符元素发送至开发板,让蜂鸣器完成音乐播放一定是一件很酷的事情!
话不多说,开整!
2. 接线图
- A0 -> 蜂鸣器正极
- A9 -> Daplink串口RX
- A10 -> Daplink串口TX
2.1 用到的器件
STM32F103C6T6
- 10KB RAM, 32KB Flash
无缘蜂鸣器1个
Daplink烧录器 + 串口传输
3. MIDI音乐文件
众所周知,MIDI音乐文件是最经典的乐器发音存储标准文件格式,区别与MP3等声音记录文件,MIDI文件里包含了乐器发音控制元数据,而今天用到的蜂鸣器便是模拟其中一种乐器发音效果对MIDI文件进行演奏。
标准的MIDI文件格式定义在这里:MIDI 1.0
从github上找到了一份面向程序编码的MIDI格式文档:Github MIDI Format
字节中文MIDI音乐文件格式入门:音乐研发必备:理解 MIDI 协议与标准 MIDI 文件格式
详细文件格式大家自行阅读文档,这里不做过多展开。要让蜂鸣器发声,最关键的几个元素:声音持续时间,声音频率(C4音符等),声音大小(高亢还是低沉)
MIDI文件里记录的:NOTE_ON
,NOTE_OFF
事件包含了所有我们想要的信息
4. 制作思路
4.1 STM32解码MIDI文件+蜂鸣器播放
这里将解码逻辑放在STM32单片机上的原因是为了支持多输入源不依赖特定上位机,等之后接入wifi模块后便可实现无线播放。
STM32单片机上的程序通过串口接收MIDI音乐源文件数据,实时解码出蜂鸣器关注的MIDI事件,通过单片机上的PWM模块模拟输出不同音频,通过占空比调节模拟不同声音大小,通过定时器实现声音持续。
采用蜂鸣器做发声单元,演奏MIDI音乐。
4.2 上位机发送MIDI音乐文件
选用最方便快速的python作为上位机服务,使用pyserial
模块实现串口通信发送MIDI源文件数据到STM32,使用tqdm
模块做简单的音乐播放进度条UI展示。
5. 效果展示
6. 源码
STM32解码和蜂鸣器发声程序
https://github.com/caftxx/stm32_buzzer_midi_player上位机python串口数据传输程序
https://github.com/caftxx/midi_serial单独的MIDI C库
https://github.com/caftxx/midi
7. 总结
本文介绍了在STM32上自制MIDI音乐播放器的详细流程和开发思路,作为之前自定义音符编码技巧的补充,让蜂鸣器演奏成为可能。
过程中被PWM频率和占空比调整最为繁琐,最开始没理解清楚PWM原理和频率+占空比与音频的关系,被折磨了一天。后来在B站学习了正点原子系列视频里对PWM的解释恍然大悟,最终完成了自制MIDI音乐播放器的制作。
8. 附录
记录几个MIDI音乐下载网站