MATLAB中的FFT在频率上移动

信息处理 fft matlab
2022-02-15 07:27:12

我在 MATLAB 中有一个信号,我想在其上执行 FFT。我的信号存储在 s 中,我使用下面的代码(受 MATLAB 帮助的启发):

L = length(s);
nfft = 2^nextpow2(L);
S = fft(s,nfft)/L;
fftf = 1/Ts/2*linspace(0,1,nfft/2+1);
ffts = (2*abs(S(1:nfft/2+1)));

s 是一个 GMSK 调制的比特序列,也就是说,它在fc2400赫兹和fc+2400在我的情况下,分别传输 0 或 1 时的 Hz。fc设置为 100kHz。对于长输入,例如 250 位 1 和 250 位 0,我得到了我所期望的,请参见下面的第一张图片。

如果我改为选择少量位数,例如 10 1 位后跟 10 0 位,我会得到预期的结果,但它会向下移动到 ~90kHz 而不是以 100kHz 为中心。这是我不太明白的事情 - 似乎改变 FFT 的采样率和长度完全没有改变。

谁能向我解释为什么?提前致谢!

长数据:

http://f.cl.ly/items/0R1i0x0m46221A230m25/fft1.png

短数据:

http://f.cl.ly/items/2a320I2l2r3M1i2o2N11/fft1.png

用于生成信号和 FFT 的代码:

%% Configuration
clear; clf;

DataRate = 9600;          % 9600 kbps for AIS
N = 100;                  % Samples per bit
Tb = 1/DataRate;          % Bit period
Ts = Tb/N;                % Sampling period
BT = 0.5;                 % AIS spec, time-bandwidth product
Ftrans = 100e3;           % Frequency of "transmitted" signal

num = 200;
Bits = zeros(1,num)+1;
Bits = [Bits zeros(1,num)-1];
clear num;

%% Modulation

% Prep a time axis from -2Tb to 2Tb
t_g = -2*Tb:Ts:2*Tb;

% Gaussian response to rectangular pulse [Haykin4th, p. 397]
x = pi*sqrt(2/log(2))*BT;
gr = 1/2*(erfc(x*(t_g/Tb-1/2))-erfc(x*(t_g/Tb+1/2))); 

% Truncate to 3Tb, pulse centered at 1.5Tb
gr = gr(0.5*N+2:3.5*N+1);

% Normalize
% when integrating, we want to end at 0.5 (phase changes by 0.5pi)
% so, we want sum(y)=0.5 -> normalize by sum(y) and divide by two.
gr = (gr)./(2*sum(gr));

% Generate the Gaussian filtered pulse train by centering a "Gaussian
% rectangle" on each bit, and adding inter-symbol interference
f = zeros(1,(length(Bits)+2)*N);
for n = 1:length(Bits)
    f((n-1)*N+1:(n+2)*N) = f((n-1)*N+1:(n+2)*N) + Bits(n).*gr;
end

% Since gr corresponds to changing the phase 0.5, multiplying by pi and
% integrating gives the resulting phase.
theta = pi*cumsum(f);

% Prep I,Q
I = cos(theta);
Q = sin(theta);

% Transmitted signal, shifted to ftrans
t = linspace(0,length(Bits)*N,length(I))*Ts;
s = -sin(2*pi*Ftrans.*t).*Q+cos(2*pi*Ftrans.*t).*I;

%% FFT

L = length(s);
% faster w/ a pow2 length, signal padded with zeros
nfft = 2^nextpow2(L);
% do the nfft-point fft and normalize
S = fft(s,nfft)/L;
% x-axis from 0 to fs/2, nfft/2+1 points
fftf = 1/Ts/2*linspace(0,1,nfft/2+1);
% only plotting the first half since its mirrored, thus 1:nfft/2+1
% why multiplied with 2?
ffts = (2*abs(S(1:nfft/2+1)));

%% Plotting

% FFT PLOT
plot(fftf/1e3,ffts);
title('FFT of transmitted signal S(f)');
set(gca,'xlim',[Ftrans/1e3-20 Ftrans/1e3+20]);
ylabel('|S(f)|');
xlabel('Frequency [kHz]');
grid;

通过改变 N 来调整采样频率似乎没有效果——但是将 num 从例如 10 更改为 100(改变位数)显然会使绘制的频谱更接近 100kHz。

1个回答

不幸的是,我现在没有 Matlab,但我认为您的问题与 linspace 有关。记住 linspace 总是给出实际的第一个和最后一个值。当您进行 FFT 分箱时,我不相信您希望以这种方式固定边界。我会尝试使用冒号运算符和适当的起始值和增量值。

编辑:如果您查看 DFT 的定义,它是:

X(k)=n=0N1x(n)ej2πknN

这表明处的第一个 DFT 输出位于基带。每个后续频率的间隔为因此,如果您有 10 个点,则 bin 中心将从对于 1000 点,它将跨越另一方面,Linspace 总是准确地保留第一个和最后一个点。您需要精确的起点和间距,或使用 linspace 调整终点。k=0Fs/N0...(N1NFs=0.9Fs)0...0.999Fs