Funpack5-3 - 基于MAX32690EVKIT 的音频频谱分析与显示
该项目使用了MAX32690EVKIT,实现了音频频谱分析与显示的设计,它的主要功能为:音频采集,信号处理,频谱显示,波形显示。
标签
FFT
MAX32690EVKIT
MAX9867
空耳-
更新2026-08-12
32

Funpack5-3 - 基于MAX32690EVKIT 的音频频谱分析与显示


1. 项目介绍

本项目基于 MAX32690EVKIT 开发板,实现了一个实时音频频谱分析dome

  • 通过板载LINE IN输入音频信号;
  • MAX9867 音频编解码芯片完成模拟信号采集与数字转换;
  • 主控通过 I2C 配置编解码器,通过 I2S + DMA 双缓冲方式连续采集音频数据;
  • 在 MCU 内完成 FFT(快速傅里叶变换) 频谱分析;
  • ST7735 TFT 彩屏(128×128) 上实时显示时域波形图频域频谱柱状图

系统最终实现了刷新率 20fps 的实时显示。


2. 硬件介绍

硬件

型号

作用

主控 MCU

MAX32690

Arm Cortex-M4 @120MHz,负责采集控制、FFT 计算与显示

音频编解码器

MAX9867

I2S 立体声编解码,完成 ADC 采样与数字音频输出

彩色显示屏

ST7735 TFT(128×128)

实时显示波形与频谱,采用软件 SPI(bit-bang)驱动

板载输入

LINE IN

音频信号输入源

2.1 主控 —— MAX32690

  • 高性能 Arm Cortex-M4 内核,最高 120MHz,带硬件浮点单元(FPU);
  • 片内集成 I2C / I2S / SPI / DMA 等丰富外设;
  • 具有充足的 SRAM(1MB),可容纳帧缓冲与双缓冲音频数据。

2.2 音频编解码器 —— MAX9867

  • 高集成度立体声 I2S 音频编解码器
  • 通过 I2C 接口配置寄存器(采样率、增益、ADC 使能等);
  • 通过 I2S 数字接口 将采集到的 PCM 音频数据送给主控;
  • 本设计工作在 48kHz 采样率,主时钟 12.288MHz

2.3 显示屏 —— ST7735 TFT

  • 128×128 像素,RGB565 16 位色;
  • 支持 SPI 接口,本板采用 软件模拟 SPI(bit-bang) 驱动(未接硬件 SPI 实例);
  • 用于显示上半屏时域波形、下半屏频域频谱


3. 方案框图与设计思路

3.1 系统整体框图

deepseek_mermaid_20260809_9865c7.png

3.2 数据流与设计思路

deepseek_mermaid_20260809_081d98.png

设计思路

  1. 音频采集:采用 I2S 从机模式 + DMA 乒乓双缓冲。DMA 在后台连续搬运数据到两片缓冲区,一个在填充、一个在主循环处理,实现"处理与采集并行",避免丢数据。
  2. 信号处理:每帧取 64 个采样点,先加 Hamming 窗(抑制频谱泄漏),再做 64 点 FFT,得到 32 个频点幅度。
  3. 屏幕显示:将波形和频谱先渲染到内存帧缓冲,再整帧一次性写入屏幕,减少逐点 SPI 通信次数,显著提升刷新率。
  4. 性能优化:FFT 旋转因子与汉明窗查表预计算,配合 -O2 编译优化,提高显示帧率。


4. 软件设计

4.1 开发与调试工具

MaximSDK (MSDK) 官方 SDK,提供外设驱动与 BSP。

4.2 软件整体流程图

deepseek_mermaid_20260809_7661ce.png

4.3 关键代码介绍

4.3.1 DMA 乒乓双缓冲采集

DMA 中断回调中切换活跃缓冲,实现连续采集:

static void dma_cb(int channel, int result)
{
   if (channel == dma_ch_rx) {
       dma_ready[dma_active] = 1;              /* 当前缓冲已填满 */
       dma_active = 1 - dma_active;            /* 切换到另一缓冲 */
       MXC_DMA_ReleaseChannel(dma_ch_rx);
       dma_ch_rx = MXC_I2S_RXDMAConfig(i2s_rx_buf[dma_active],
                                        CAPTURE_WORDS * sizeof(...));
  }
}

4.3.2 FFT 查表优化

预计算旋转因子与汉明窗,避免每帧重复调用 cosf/sinf

static void fft_init_tables(void)
{
   /* 汉明窗 */
   for (j = 0; j < n; j++)
       hamming_win[j] = 0.54f - 0.46f * cosf(2*PI*j/(n-1));
   /* 旋转因子 */
   for (len = 2; len <= n; len <<= 1) {
       half = len >> 1;
       for (j = 0; j < half; j++) {
           tw_cos[idx] = cosf(step * j);
           tw_sin[idx] = sinf(step * j);
           idx++;
      }
  }
}



5. 功能展示

5.1 屏幕布局

image.png

  • 上半屏(y=0..63):实时时域波形,绿色折线,带青色中线与灰色网格。
  • 下半屏(y=64..127):实时频域频谱,32 根彩色柱状图,低频在左、高频在右,仅显示 20kHz 以下。
  • 右上角:实时 FPS 刷新率数字。

5.2 已实现功能

功能

说明

状态

音频采集

I2C 配置 MAX9867,I2S+DMA 连续采集 48kHz

✅ 完成

FFT 频谱分析

64 点 FFT,提取 32 个频点幅度

✅ 完成

时域波形显示

实时折线显示

✅ 完成

频域频谱显示

彩色柱状图,含缓落动画

✅ 完成

噪声抑制

抑制直流与高频噪声频点

✅ 完成

刷新率

≥10fps(实测约 10~25fps)

✅ 完成

测试工具:在线频率发生器 | 专业的音频信号生成工具 - 968T工具箱

image-20260809231527716.png


6. 遇到的问题及解决方法

问题 1:MAX9867 通过 I2C 初始化失败

  • 现象:串口打印 audio_codec_init failed
  • 原因:I2C 传输频率配置、寄存器写时序不稳定,偶发 SCL 拉伸导致驱动卡死。
  • 解决:在寄存器写操作间加入适当延时(MXC_Delay)保证稳定初始化。

问题 2:刷新率过低(<10fps)

  • 现象:逐点写屏导致刷新很慢,画面卡顿。
  • 原因:ST7735 采用软件 bit-bang SPI,逐像素多次通信开销极大。
  • 解决
    1. 引入帧缓冲 + 整帧一次写屏,减少 SPI 通信次数;
    2. 旋转因子与汉明窗查表预计算,显著降低 CPU 计算时间。
    3. -O2 编译优化,从10pfs提升到20pfs。

问题 3:静音时频谱仍有固定残留柱

  • 现象:无音频输入时屏幕仍有立柱。
  • 原因:直流偏置(bin0)、Nyquist 高频采样/量化噪声在静音时也有固定幅值。
  • 解决:加入静音检测门限,并强制抑制 bin0 高频噪声频点。


7. 心得体会

通过本项目,我完整经历了一个"采集 → 处理 → 显示"的嵌入式实时系统开发流程,收获颇多:

  1. DMA + 双缓冲的设计思想:理解了如何用乒乓缓冲实现"采集与处理并行",避免数据丢失,这是实时系统中非常经典且重要的一种设计模式。
  2. 数字信号处理的落地:将课本上的 FFT 理论真正应用到工程中,理解了采样率、频点分辨率(f = 采样率/FFT点数)、窗函数、频谱泄漏、Nyquist 定理等概念在真实系统中的体现。
  3. 性能优化的系统思维:面对刷新率不足的问题,没有停留在"改代码"层面,而是从通信方式(整帧写屏)、算法(查表)、编译(-O2)等多维度优化,体会到嵌入式优化的综合性。

总而言之,这次项目不仅加深了我对 MCU 外设、数字信号处理和实时显示的理解,也让我体会到"理论联系实际"的魅力。

附件下载
00_tft.zip
团队介绍
kone
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号