基于MAX32690EVKIT的实时音频频谱分析与显示
一、项目介绍
本项目基于 MAX32690EVKIT 和 Zephyr RTOS,实现音频信号的连续采集、频谱分析以及彩屏实时显示。电脑播放的音乐通过双头 3.5 mm 音频线接入开发板 J5 LINE_IN,板载 MAX9867 Codec 将模拟信号转换为 44.1 kHz、16 bit、双声道 PCM 数据;MAX32690 通过 I2S 和 DMA 连续接收数据,取左声道完成 1024 点 FFT,最后在板载彩屏上同时显示时域波形和频域频谱。串口还会输出主频率、dBFS 电平、DSP耗时和丢块计数,便于定量验证。
本项目最终保持经过实际验证的 44.1 kHz 采样率和 1024 点分析窗口。1024 点对应 23.2 ms 音频,FFT频点间隔约为 43.1 Hz;屏幕以 80 ms 为刷新周期,实测约 12.3~12.5 fps,满足不低于 10 fps 的要求。
二、使用到的硬件
- MAX32690EVKIT:主控为 120 MHz Arm Cortex-M4F,带单精度FPU、DMA、I2S、I2C和丰富片上存储,适合实时音频及DSP处理。板上集成彩色TFT、USB转串口和调试接口。
- MAX9867音频Codec:集成立体声ADC、DAC及音频接口。本项目通过I2C2配置寄存器,通过I2S传输音频。其7 bit I2C地址为
0x18,板载12.288 MHz晶振为Codec提供主时钟。 - 板载ST7735R彩屏:约1.45英寸,Zephyr设备树中的逻辑分辨率为130×132、RGB565格式。上半屏绘制时域波形,下半屏绘制32根频谱柱。
- 音频及调试附件:电脑作为Line-In信号源,使用双头3.5 mm音频线连接J5;USB串口用于日志观察,SWD/J-Link或OpenOCD用于下载和调试。调试输出通路时还使用耳机连接J6 HD_PHONE验证过Codec的DAC和耳机链路。
需要特别注意:JP9、JP10必须置于2-3,才能把P1.7/P1.8连接到Codec的I2C2 SDA/SCL。
三、方案框图与设计思路

时钟方面,MAX9867作为I2S控制器端产生LRCLK和BCLK,MAX32690的I2S控制器工作在target端。设备树在应用自己的board overlay中启用 i2s@40060000,配置P2.26~P2.29和DMA通道,同时关闭复用相同引脚的SPI0,未修改Zephyr仓库中的板级文件。
软件采用“采集、DSP、显示”解耦设计。主线程只负责读取I2S块、提取左声道并归还内存块;DSP线程通过双分析缓冲和消息队列处理完整的1024点数据;显示线程只读取最新快照,即使屏幕写入较慢也不会阻塞音频采集。
四、调试软件、软件流程及关键代码
开发使用Zephyr RTOS、west、CMake/Ninja和GNU Arm工具链;CMSIS-DSP提供优化后的浮点RFFT、窗函数、复数模平方和最大值搜索;OpenOCD/J-Link负责烧录,串口终端用于检查Codec版本、峰值频率、电平、DSP时间、刷新率和丢块数。

I2S配置的关键参数如下,主控接收端使用44.1 kHz、16 bit双声道,并声明为时钟target:
const struct i2s_config config = {
.word_size = 16,
.channels = 2,
.format = I2S_FMT_DATA_FORMAT_I2S,
.options = I2S_OPT_BIT_CLK_TARGET | I2S_OPT_FRAME_CLK_TARGET,
.frame_clk_freq = 44100,
};
FFT前先去除直流分量并乘Hann窗,以减轻直流偏置和频谱泄漏,再调用CMSIS-DSP:
fft_input[i] = (fft_input[i] - mean) * hann_window[i];
arm_rfft_fast_f32(&fft, fft_input, fft_output, 0);
arm_cmplx_mag_squared_f32(&fft_output[2], &power_spectrum[1], 511);
时域显示没有简单抽取1024点中的130点,而是把每列覆盖的样本取最小值和最大值形成包络,这样能保留瞬态峰值并避免“只有散点”的雪花效果。频域则把约512个有效FFT频点按对数频率合并为32柱,使用绿色、黄色和红色表示由低到高的幅度区间。
五、功能展示及说明


最终显示界面示意。 上半屏是青色连续时域包络及网格线,下半屏是32根对数频谱柱;柱高随dBFS变化,并带有限速上升/下降处理,使画面稳定但仍能跟随音乐。
调试阶段的实际结果如下:
验证项目 | 板端结果 |
|---|---|
电脑播放音乐 | 输入电平约 -10 dBFS,波形和频谱明显变化 |
电脑暂停播放 | 底噪约 -55 dBFS,与播放状态差异明显 |
1024点FFT耗时 | 约1.28 ms |
显示刷新率 | 约12.3~12.5 fps |
分析数据丢块 | 0 |
以上结果说明模拟输入、Codec ADC、I2S/DMA、FFT及显示链路均已贯通。
六、遇到的难题及解决方法
- Codec初始化返回
-5:开始时MAX9867第一次I2C写入就失败。检查原理图和跳线后发现JP9、JP10未把I2C2连接到Codec;改为2-3后初始化成功,耳机输出测试也能听到测试音。 - 输入电平异常偏低:最初插入或拔出音频线几乎没有区别。重新以本地已验证的Zephyr
echo和output例程为基准,统一44.1 kHz时钟、I2S格式、主从关系和Line-In选择,并关闭模拟直通。修正后音乐约为-10 dBFS,停止播放约为-55 dBFS。 - 波形撕裂和“雪花”:逐点脏区刷新虽然发送数据少,却破坏了线段连续性;通用GPIO bit-bang也限制了速度。最终采用130列min/max包络、连接相邻中点,并利用MAX32690 GPIO2 bit-band直接发送9 bit、Mode 0显示数据,同时保持中断可抢占。显示稳定在12 fps以上,音频分析不丢块。
- 波形高度超出范围:最初缩放基准偏小,较大输入会顶到屏幕边界。后来按16 bit PCM满量程32768映射到半屏高度,避免正常音乐轻易越界。
七、心得体会
本项目最大的收获是认识到实时音频系统必须按完整链路调试:模拟接口、跳线、Codec寄存器、I2S时钟、DMA缓冲、DSP算法和显示带宽缺一不可。能够编译或看到串口数据并不代表声音一定采集正确,必须使用已知音源、dBFS差异、主频率、耗时、刷新率和丢块数共同验证。
同时,FFT点数和显示点数并不需要相等。1024点决定频率分辨率和23.2 ms分析窗口;彩屏只有130列,因此时域使用min/max包络压缩,频域再汇总成32柱。通过线程解耦和“只显示最新结果”,较慢的屏幕不会拖住连续采集。整个调试过程也说明,应优先复用本地已经过硬件验证的配置,再用数据逐层缩小问题范围,这比反复试寄存器更可靠。
八、项目文件
工程目录:max32690_i2s_loopback
src/main.c:I2S采集、缓冲管理和FFT处理。src/max9867.c:MAX9867的I2C初始化和Line-In配置。src/audio_display.c:波形、频谱及快速屏幕刷新。boards/max32690evkit_max32690_m4.overlay:应用级I2S、DMA、引脚和Codec设备树配置。