数字信号处理基础:采样定理、FFT与FIR/IIR滤波器原理、定点数与浮点数运算
做DSP IP开发,说白了就是跟数字信号打交道。你想想看,现实世界里的声音、温度、电压,都是连续的模拟信号。但咱们芯片只能处理离散的数字。怎么把模拟信号变成数字信号?这里头第一个坎儿,就是采样定理。
采样定理:别让信号“说谎”
采样定理又叫奈奎斯特-香农定理。它的核心就一句话:采样频率必须大于信号最高频率的两倍。为什么?
我举个例子。你拿手机拍车轮,如果快门速度太慢,拍出来的车轮看起来是倒着转的。这就是混叠效应。采样不够快,高频信号就会伪装成低频信号混进来。
核心公式:
fs > 2 × fmax
其中 fs 是采样频率,fmax 是信号最高频率。
我在项目中遇到过一件事。有个同事做音频处理,采样率设了44.1kHz,觉得够用了。结果发现20kHz以上的高频分量混叠到了低频段,听起来有“嘶嘶”的噪声。后来加了抗混叠滤波器才解决。
避坑指南:
我曾经吃过亏——采样前没加抗混叠滤波器。信号里总有你意想不到的高频噪声。记住:采样前必须用低通滤波器把高于 fs/2 的成分滤掉。这是铁律。
FFT:时域到频域的“翻译官”
FFT(快速傅里叶变换)是数字信号处理里最常用的工具。它把时域信号变成频域信号。说白了,就是告诉你信号里有哪些频率成分。
FFT的原理基于DFT(离散傅里叶变换),但计算量从O(N²)降到了O(N log N)。怎么做到的?
- 分治思想:把大DFT拆成小DFT
- 旋转因子对称性:利用WNk的周期性减少计算
- 蝶形运算:基2FFT的核心结构
我个人习惯用基2时间抽取FFT。它的代码实现很规整,适合硬件实现。
// 基2时间抽取FFT核心代码(伪代码)
void fft(complex* x, int N) {
// 位反转排序
for (int i = 0; i < N; i++) {
int j = bit_reverse(i, log2(N));
if (i < j) swap(x[i], x[j]);
}
// 蝶形运算
for (int len = 2; len <= N; len <<= 1) {
complex w = exp(-2*PI/len);
for (int i = 0; i < N; i += len) {
complex wn = 1;
for (int j = 0; j < len/2; j++) {
complex u = x[i+j];
complex v = x[i+j+len/2] * wn;
x[i+j] = u + v;
x[i+j+len/2] = u - v;
wn *= w;
}
}
}
}
实战经验:
做FFT硬件加速器时,我建议把旋转因子提前算好存到ROM里。运行时实时计算cos/sin太费资源。另外,注意位反转排序——很多新手在这步栽跟头。
FIR与IIR滤波器:两种不同的“筛子”
滤波器就是信号筛子。FIR和IIR是两种最常用的数字滤波器。
FIR滤波器
FIR(有限脉冲响应)滤波器的特点是:没有反馈,只有前馈。它的输出只取决于当前和过去的输入。
公式很简单:
y[n] = b₀x[n] + b₁x[n-1] + ... + bNx[n-N]
- 优点:线性相位,稳定,容易实现
- 缺点:要达到陡峭的截止特性,阶数很高,延迟大
我记得有一次做音频均衡器,要求相位不失真。IIR虽然计算量小,但相位非线性,听起来怪怪的。最后用了128阶的FIR,效果很好。
IIR滤波器
IIR(无限脉冲响应)滤波器有反馈。它的输出不仅取决于输入,还取决于过去的输出。
标准形式:
y[n] = b₀x[n] + b₁x[n-1] + ... - a₁y[n-1] - a₂y[n-2] - ...
- 优点:阶数低,计算量小,频率选择性好
- 缺点:相位非线性,可能不稳定
避坑指南:
我曾经用IIR做高通滤波器,系数没算好,结果系统自激振荡了。IIR的极点必须在单位圆内。做定点实现时尤其要注意——量化误差可能把极点推到圆外。
定点数与浮点数运算:精度与资源的博弈
DSP芯片里,定点数和浮点数的选择是个老话题。我个人的看法是:没有绝对的好坏,看场景。
定点数
定点数用固定的小数点位置表示数值。比如Q15格式,1位符号位,15位小数位。
| 格式 | 位数 | 范围 | 精度 |
|---|---|---|---|
| Q15 | 16位 | -1 ~ 0.99997 | 3.05e-5 |
| Q31 | 32位 | -1 ~ 0.9999999995 | 4.66e-10 |
定点数的好处是:硬件实现简单,速度快,功耗低。坏处是:动态范围小,容易溢出。
浮点数
浮点数用科学计数法表示。IEEE754标准里,单精度32位,双精度64位。
- 单精度:1位符号,8位指数,23位尾数
- 双精度:1位符号,11位指数,52位尾数
浮点数的好处是:动态范围大,不用操心溢出。坏处是:硬件复杂,功耗高,速度慢。
我的建议:
做DSP IP时,我通常这样选:
- 音频处理:定点Q15或Q31就够了
- 通信基带:定点Q31或混合精度
- 雷达/图像:浮点或块浮点
- 算法原型验证:先用浮点,再转定点
定点转浮点时,有个坑要注意——精度损失。我曾经把一个浮点滤波器系数直接截断成定点,结果滤波器特性完全变了。正确的做法是:先做系数缩放,再做舍入,最后做饱和处理。
实战技巧:
做定点化时,我习惯用MATLAB的fi对象先仿真一遍。看看量化误差对系统性能的影响。如果SNR下降超过3dB,就得考虑增加位宽或者改用浮点。
好了,以上就是数字信号处理基础的核心内容。采样定理是前提,FFT是工具,滤波器是手段,定点浮点是实现选择。做DSP IP开发,这些基础打不牢,后面设计指令集和编译器的时候会处处碰壁。
我个人觉得,理解这些概念最好的方式就是动手。拿MATLAB或者Python,写个FFT,设计个滤波器,再转成定点实现。踩过坑,才能真正理解。