在单片机上玩转数字信号处理:FFT 实战
FFT (快速傅里叶变换) 是许多嵌入式工程师心中的痛。复杂的蝶形运算、倒位序算法,看着就头大。
但好消息是,现在的 MCU(特别是 Cortex-M4/M7)自带了 DSP 扩展指令,配合官方的 CMSIS-DSP 库,跑 FFT 跟呼吸一样简单。
1. 为什么需要 FFT?
时域信号(示波器看到的波形)往往看不出什么规律,特别是叠加了噪声后。
频域信号(频谱图)能一眼看穿信号的本质。
- 应用场景:音频可视化(音乐律动灯)、电机振动分析(故障诊断)、心率提取。
2. 采样定理与分辨率
在开始写代码前,必须搞懂两个数学公式:
- 奈奎斯特频率:$ F_{max} = F_s / 2 $。如果你采样率是 10kHz,你最多能测到 5kHz 的信号。
- 频率分辨率:$ \Delta F = F_s / N $。N 是 FFT 的点数(如 1024)。分辨率越小,频谱越精细。
- 例如:Fs=10kHz, N=1024。分辨率 ≈ 10Hz。
3. CMSIS-DSP 实战
不要自己手写 FFT 算法(除非为了学习)。CMSIS-DSP 库针对 ARM 汇编指令做了极致优化。
3.1 初始化
我们在 M4 上通常使用定点 FFT (q15 或 q31 格式) 以获得最高性能。FPU 虽然能算浮点,但定点通常更快且更省内存。
1 |
|
3.2 运算流程
- ADC 采样:通过 DMA 将数据填入 buffer。
- **RFFT (实数 FFT)**:因为我们的输入信号是实数(电压值),使用
arm_rfft_q15比通用的 CFFT 快一倍。 - **计算模值 (Magnitude)**:$ Mag = \sqrt{Real^2 + Imag^2} $。
1 | void DSP_Process(void) { |
4. 性能与陷阱
- 溢出风险:定点运算最怕溢出。q15 的范围只有 -32768 到 32767。如果 FFT 过程中数据不断累加,很容易溢出。CMSIS-DSP 内部会自动进行位移缩放(downscaling)来防止溢出,但这会导致小信号精度丢失。
- 窗函数:直接做 FFT 会有频谱泄露。建议在 FFT 前对输入数据加窗(如汉宁窗 Hanning Window)。
总结
不要被数学公式吓倒。对于嵌入式工程师,FFT 就是一个函数调用。把数据喂进去,它告诉你哪个频率最强,就这么简单。
- Title: 在单片机上玩转数字信号处理:FFT 实战
- Author: Evek Golden
- Created at : 2024-08-05 16:00:00
- Updated at : 2026-06-12 08:57:02
- Link: https://blog.cocodemo.uno/posts/fft7k3m/
- License: This work is licensed under CC BY-NC-SA 4.0.
Comments