Matlab中的频率计算和快速傅里叶变换

Frequency computation and fast fourier transform in Matlab

我有一个与快速傅里叶变换相关的问题。我想计算相位并使 FFT 绘制功率谱密度。但是,当我计算频率 f 时,出现了一些错误。这是我的程序代码:

n = 1:32768;

T = 0.2*10^-9; % Sampling period

Fs = 1/T; % Sampling frequency

Fn = Fs/2; % Nyquist frequency

omega = 2*pi*200*10^6; % Carrier frequency

L = 32768; % % Length of signal

t = (0:L-1)*T; % Time vector

x_signal(n) = cos(omega*T*n + 0.1*randn(size(n))); % Additive phase noise (random)

y_signal(n) = sin(omega*T*n + 0.1*randn(size(n))); % Additive phase noise (random)

theta(n) = atan(y_signal(n)/x_signal(n));

f = (theta(n)-theta(n-1))/(2*pi)

Y = fft(f,t);

PSD = Y.*conj(Y); % Power Spectral Density

%Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector

正如发布的那样,您会收到错误

error: subscript indices must be either positive integers less than 2^31 or logicals

指的是操作 theta(n-1)n=1 导致索引为 0(这是越界,因为 Matlab 使用基于 1 的索引)。为避免这种情况,可以使用 n:

中的索引子集
f = (theta(n(2:end))-theta(n(1:end-1)))/(2*pi);

就是说,如果您这样做是为了尝试获得频率的瞬时测量值,那么您将有更多的问题需要处理。最微不足道的是你还应该除以 T。由于使用了 / 运算符,theta 是一个标量(参见 Matlab's mrdivide) rather than the ./ operator 执行逐元素除法。因此,更好的表达式是:

theta(n) = atan(y_signal(n)./x_signal(n));

现在,您可能会注意到的下一个问题是您实际上丢失了一些相位信息,因为 atan 的结果是 [-pi/2,pi/2] 而不是完整的 [-pi,pi] 范围。为避免这种情况,您应该改用 atan2:

theta(n) = atan2(y_signal(n), x_signal(n));

即便如此,您可能会注意到,只要相位在 -pi 附近和 pi 附近跳跃,估计的频率就会定期出现尖峰。这可以通过计算相位差模 2*pi:

来避免
f = mod(theta(n(2:end))-theta(n(1:end-1)),2*pi)/(2*pi*T);

最后要注意的一点是:调用 fft 时,您不应传入时间变量(默认假定输入以固定时间间隔进行采样)。但是,您可以指定所需的 FFT 长度。因此,您将计算 Y 如下:

Y = fft(f, L);

然后您可以使用以下方法绘制结果 PSD

Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
plot(Fv, abs(PSD(1:L/2+1)));