在学习数字信号处理时,很多种频率很容易搞混淆,有模拟/数字/频率/角频率等等,也不是特别清楚不同频率之间的关系,希望这篇文件可以为各种频率来个了结.
4种频率及其数量关系
实际物理频率表示物理信号的真实频率; fs为采样频率,表示ADC采集物理信号的频率,由奈奎斯特采样定理可以知道,fs必须≥信号最高频率的2倍才不会发生信号混叠,因此fs能采样到的信号最高频率为fs/2。
角频率Ω是物理频率的2π倍, 这个也称模拟频率。
归一化频率是将物理频率按fs归一化之后的结果,最高的信号频率为fs/2对应归一化频率0.5(ω=π),这也就是为什么在matlab的fdatool工具中归一化频率为什么最大只到0.5的原因。归一化频率中不含fs的信息.
圆周频率是归一化频率的2*pi倍,这个也称数字频率ω。
有关FFT频率与实际物理频率的分析
做n个点的FFT,表示在时域上对原来的信号取了n个点来做频谱分析,n点FFT变换的结果仍为n个点。
换句话说,就是将2π数字频率ω分成n份,而整个数字频率ω的范围覆盖了从0-2π*fs
的模拟频率范围。这里的fs是采样频率。而我们通常只关心0-π
中的频谱,因为根据奈科斯特定律,只有f=fs/2范围内的信号才是被采样到的有效信号。那么,在w的范围内,得到的频谱肯定是关于n/2对称的。
举例说,如果做了16个点的FFT分析,你原来的模拟信号的最高频率f=32kHz,采样频率是64kHz,n的范围是0,1,2...15。这时,64kHz的模拟频率被分成了16分,每一份是4kHz,这个叫频率分辨率。那么在横坐标中,n=1时对应的f是4kHz, n=2对应的是8kHz, n=15时对应的是60kHz,你的频谱是关于n=8对称的。你只需要关心n=0到7以内的频谱就足够了,因为,原来信号的最高模拟频率是32kHz。
这里可以有两个结论:
- 必须知道原来信号的采样频率fs是多少,才可以知道每个n对应的实际频率是多少,第k个点的实际频率的计算为f(k)=k*(fs/n)
- 你64kHz做了16个点FFT之后,因为频率分辨率是4kHz,如果原来的信号在5kHz或者63kHz有分量,你在频谱上是看不见的,这就表示你越想频谱画得逼真,就必须取越多的点数来做FFT,n就越大,你在时域上就必须取更长的信号样本来做分析。但是无论如何,由于离散采样的原理,你不可能完全准确地画出原来连续时间信号的真实频谱,只能无限接近(就是n无限大的时候),这个就叫做频率泄露。在采样频率fs不变得情况下,频率泄漏可以通过取更多的点来改善,也可以通过做FFT前加窗来改善,这就是另外一个话题了。
为什么抽取/内插看起来对频谱有影响?
在数字信号处理时,经常需要对数据进行抽取或者内插处理.抽取之后的频率展宽了n倍,内插之后的频率压缩了n倍,从而需要在变采样率之后添加抗混叠滤波器.但是实际上信号的频率在抽取/内插的前后并没有发生变化.这里的核心原因是:归一化频率失去了采样率fs信息.
抽取和内插的实质是采样率fs的变化
举个例子:
我们设定fs=30.72MHz
,使用3个cw信号的合成信号代表一个BW=8MHz
的宽带信号,使用实际频率来表示信号,看到BW没有变化,使用数字频率w来表示信号,信号的BW似乎被压缩了.
Q: 为什么要在归一化频率下来分析信号?
clear all;
close all;
fs = 30.72e6;
ts = 1/fs;
nFFT=4096;
%nFFT=32768;
t=0:ts:(nFFT-1)*ts;
d0=100*sin(2*pi*10e6*t);
d1=50*cos(2*pi*5e6*t);
d2=10*cos(2*pi*2e6*t);
dSum=d0+d1+d2;
dFFT = abs(fftshift(fft(dSum,nFFT)))/(nFFT/2);
%dFFT = abs(fft(dSum,nFFT))/(nFFT/2);
fAxis = (-1/2*nFFT:(1/2*nFFT-1))/nFFT*fs;
figure(1)
subplot(2,1,1)
plot(fAxis,dFFT)
title('original signal')
subplot(2,1,2)
dSumI= zeros(1,2*nFFT);
for k =1:nFFT
dSumI(2*k) = dSum(k);
end
dFFTI = abs(fftshift(fft(dSumI,2*nFFT)))/(nFFT);
fAxisI = (-nFFT:(nFFT-1))/(2*nFFT)*fs*2; %fs double
plot(fAxisI,dFFTI)
title('interpolated signal')
figure(2)
subplot(2,1,1)
wAxis = 2*pi*(-1/2*nFFT:(1/2*nFFT-1))/(nFFT);
plot(wAxis,dFFT)
set(gca,'XTick',-2*pi:pi/2:2*pi)
title('original signal normalize')
subplot(2,1,2)
wAxisI = 2*pi*(-nFFT:(nFFT-1))/(2*nFFT);
plot(wAxisI,dFFTI)
set(gca,'XTick',-2*pi:pi/2:2*pi)
title('interpolated signal normalize')