使用RT-Spark及其内置的音频接口来制作一个MP3播放器
1. 引言
标准的嵌入式音频项目通常依赖外部存储设备,例如采用FAT文件系统的SD卡,来播放预先录制的音频文件。在硬件场景中,当无法使用或严格禁止使用外部大容量存储时,就需要采取替代方案。本项目概述了开发一款“无文件”实时音频播放器的过程。该系统通过STM32F407ZGT6微控制器、FreeRTOS内核以及外部ES8388音频编解码器,实时进行多音轨乐器的数学合成。
2. 设计与测试
该方法需要将音频波形的繁重计算与更新显示和读取用户输入等异步任务分离。
硬件描述
该架构以一个运行在168 MHz的ARM Cortex-M4 STM32F407ZGT6开发板为核心。音频信号的处理由ES8388音频编解码器完成。编解码器的控制寄存器通过I2C2总线进行配置,而原始合成的PCM数据则通过配置为主传输模式的I2S3外设持续流式传输。
用户界面采用TFT LCD,由微控制器的柔性静态存储控制器(FSMC)通过第1号银行的SRAM存储线驱动。模拟音量控制通过连接至ADC1外设的电位器实现(引脚PA1)。最后,使用四个按钮的并行接口(引脚PC0、PC1、PC4、PC5)进行曲目导航。
(注:硬件复现时,应参考此处完整的HTML/CSS示意图以实现这些精确的GPIO连接。)
软件说明
为防止CPU饥饿并确保音频播放无中断,该软件采用三个并发的FreeRTOS线程进行架构设计:
•update_lcd_leds_thread:管理播放状态机,并在安全的互斥锁保护下处理由FSMC驱动的LCD图形更新这一繁重任务。
•adjust_volume:定期采样12位ADC,滤除噪声底噪,并通过I2C将动态缩放值直接传输至ES8388编解码器。
•polling_buttons:评估去抖动的数字输入,以解析轨道导航。
概念与实现:合成引擎
由于没有存储介质,系统使用动态浮点正弦合成生成原始音频流,并将其映射到固定的44.1 kHz采样率。一个512字节的循环DMA缓冲区(debug_audio_buffer)充当乒乓队列。当DMA控制器将内存分配的第一半数据流传输给编解码器时,硬件中断(HAL_I2S_TxHalfCpltCallback)会触发处理器计算第二半数据的下一个数学正弦波序列。当缓冲区完成(HAL_I2S_TxCpltCallback)后,该过程便交替进行。
3. 文档
以下带注释的代码片段展示了音频合成的核心逻辑以及用于导航的独特二进制状态机。
乒乓球音频合成
并行二进制接口状态机
通过按住三个带权重的二进制按钮(BTN2、BTN3、BTN4)组合,可选择从0到7的轨道,而非使用线性上的前后按钮。
4. 结果
该项目的最终输出在测试中表现极为出色。硬件通过ES8388编解码器生成了平滑、连续的44.1 kHz正弦波音频。
在播放过程中,未出现任何可听的杂音、咔嗒声或缓冲区溢出。该架构的一大成功之处在于任务的完全隔离;观察发现,在LCD上进行大量图形屏幕清除操作时,并未中断连续的DMA音频流。
并行二进制用户界面功能按设计准确运行。5秒确认窗口的实现有效缓解了轨道切换的异常情况,相比传统的轮询循环,提供了响应更快的用户体验。
5. 结论
实时音频的成功合成证明了采用DMA驱动的乒乓缓冲区结合实时操作系统多任务处理的有效性。该项目通过数学方式生成PCM数据,有效避免了对物理存储介质的需求。
在开发阶段遇到了多个问题并已解决。最初,当LCD更新时会出现音频卡顿现象。通过发现CPU阻塞了音频数学计算,解决了该问题。将音频传输移至带有半完成硬件中断的DMA控制器后,彻底解决了饥饿问题。
为进一步改进,该软件可扩展为包含更复杂的波形发生器。通过实现方波、锯齿波或数字ADSR(攻击、衰减、保持、释放)包络,系统便能模拟不同的物理乐器,而不仅仅是基本的正弦波音。
本文编译自hackster.io





