在线咨询 切换到宽版
eetop公众号 创芯大讲堂 创芯人才网

 找回密码
 注册

手机号码,快捷登录

手机号码,快捷登录

搜全文
查看: 137|回复: 5

[求助] 求一个对ADC和PLL输出结果作FFT频谱分析的matlab程序,求推荐!

[复制链接]
发表于 昨天 05:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

×
本帖最后由 wolaila1 于 2025-12-11 19:11 编辑

求一个对ADC和PLL输出结果作FFT频谱分析的matlab程序,求推荐!
发表于 昨天 08:56 | 显示全部楼层
%% ADC和PLL输出结果FFT频谱分析程序
% 作者:MATLAB助手
% 功能:对ADC和PLL输出信号进行频谱分析
% 说明:可以处理实际数据或生成测试信号进行分析

clear; clc; close all;

%% 1. 参数设置
Fs = 100e6;          % 采样频率 (Hz)
Ts = 1/Fs;           % 采样间隔
N = 8192;            % 采样点数 (FFT长度)
f0 = 10e6;           % 信号频率 (Hz)
Amplitude = 1.0;     % 信号幅度

% ADC参数
adc_bits = 12;       % ADC位数
adc_vref = 2.0;      % ADC参考电压 (V)
adc_noise_rms = 0.01; % ADC噪声RMS值

% PLL参数
pll_phase_noise = -100; % PLL相位噪声 (dBc/Hz @ offset)
pll_jitter_rms = 1e-12; % PLL抖动RMS值 (秒)

%% 2. 生成测试信号 (如果无实际数据)
% 生成理想的模拟信号
t = (0:N-1)*Ts;        % 时间向量
analog_signal = Amplitude * sin(2*pi*f0*t);

% 添加噪声
noise = randn(1, N) * adc_noise_rms;
analog_signal_noisy = analog_signal + noise;

%% 3. ADC量化过程模拟
% 计算ADC量化步长
adc_lsb = adc_vref / (2^adc_bits);

% 量化信号 (模拟ADC采样和量化)
adc_signal = round(analog_signal_noisy / adc_lsb) * adc_lsb;

% 添加ADC量化误差
quantization_error = adc_signal - analog_signal_noisy;

%% 4. PLL输出信号生成 (模拟频率合成)
% 添加相位噪声模拟PLL输出
phase_noise = pll_jitter_rms * randn(1, N) * 2*pi*f0;
pll_signal = Amplitude * sin(2*pi*f0*t + phase_noise);

% PLL信号也经过ADC量化
pll_adc_signal = round(pll_signal / adc_lsb) * adc_lsb;

%% 5. FFT频谱分析函数
function [freq, spectrum, dB_spectrum] = perform_fft_analysis(signal, Fs, window_type)
    % 对信号进行FFT分析
    N = length(signal);
   
    % 选择窗函数
    switch window_type
        case 'hann'
            win = hann(N)';
        case 'hamming'
            win = hamming(N)';
        case 'blackman'
            win = blackman(N)';
        otherwise
            win = ones(1, N);  % 矩形窗
    end
   
    % 加窗
    windowed_signal = signal .* win;
   
    % FFT计算
    fft_result = fft(windowed_signal, N);
   
    % 计算单边频谱
    spectrum = abs(fft_result/N);
    spectrum = spectrum(1:floor(N/2)+1);
    spectrum(2:end-1) = 2*spectrum(2:end-1);
   
    % 转换为dB
    dB_spectrum = 20*log10(spectrum);
   
    % 频率向量
    freq = (0:floor(N/2)) * Fs/N;
end

%% 6. 分析ADC信号
% 执行FFT分析
window_type = 'hann';  % 选择窗函数
[freq_adc, spectrum_adc, dB_spectrum_adc] = perform_fft_analysis(adc_signal, Fs, window_type);

% 找到信号峰值
[adc_peak_val, adc_peak_idx] = max(dB_spectrum_adc(2:end));  % 忽略DC
adc_peak_freq = freq_adc(adc_peak_idx + 1);

%% 7. 分析PLL信号
% 执行FFT分析
[freq_pll, spectrum_pll, dB_spectrum_pll] = perform_fft_analysis(pll_adc_signal, Fs, window_type);

% 找到信号峰值
[pll_peak_val, pll_peak_idx] = max(dB_spectrum_pll(2:end));  % 忽略DC
pll_peak_freq = freq_pll(pll_peak_idx + 1);

%% 8. 计算性能指标
function metrics = calculate_metrics(dB_spectrum, freq, peak_idx, Fs, N)
    % 计算各种频谱性能指标
   
    % 信号功率
    signal_power_dB = dB_spectrum(peak_idx);
   
    % 计算噪声基底
    % 排除信号区域和DC附近的频点
    exclude_bandwidth = 100;  % 排除带宽 (Hz)
    exclude_bins = ceil(exclude_bandwidth / (Fs/N));
   
    noise_start = 10;  % 从第10个频点开始,避开DC
    noise_end = length(dB_spectrum);
   
    % 创建噪声掩码
    noise_mask = true(1, noise_end);
    noise_mask(max(1, peak_idx-exclude_bins):min(noise_end, peak_idx+exclude_bins)) = false;
    noise_mask(1:noise_start) = false;
   
    % 计算噪声功率
    noise_dB = dB_spectrum(noise_mask);
    noise_floor = mean(noise_dB);
    noise_std = std(noise_dB);
   
    % 计算SFDR (无杂散动态范围)
    % 查找除主信号外的最高峰值
    search_range = 1:length(dB_spectrum);
    search_range(peak_idx) = [];  % 移除主信号
    [spur_val, spur_idx] = max(dB_spectrum(search_range));
    sfdr = signal_power_dB - spur_val;
   
    % 计算SNR (估算)
    % 假设信号带宽为1个bin
    signal_bw_bins = 1;
    signal_bins = max(1, peak_idx-signal_bw_bins):min(length(dB_spectrum), peak_idx+signal_bw_bins);
   
    % 计算信号功率 (线性)
    signal_linear = 10.^(dB_spectrum(signal_bins)/20);
    signal_power_linear = sum(signal_linear.^2);
   
    % 计算噪声功率
    noise_linear = 10.^(noise_dB/20);
    noise_power_linear = sum(noise_linear.^2);
   
    % SNR计算
    snr_linear = signal_power_linear / (noise_power_linear/length(noise_dB)*length(signal_bins));
    snr_dB = 10*log10(snr_linear);
   
    % 返回指标结构体
    metrics.signal_power_dB = signal_power_dB;
    metrics.noise_floor = noise_floor;
    metrics.noise_std = noise_std;
    metrics.sfdr = sfdr;
    metrics.snr_dB = snr_dB;
    metrics.fundamental_freq = freq(peak_idx);
end

% 计算ADC信号指标
adc_metrics = calculate_metrics(dB_spectrum_adc, freq_adc, adc_peak_idx, Fs, N);

% 计算PLL信号指标
pll_metrics = calculate_metrics(dB_spectrum_pll, freq_pll, pll_peak_idx, Fs, N);

%% 9. 绘制结果
% 设置图形参数
figure('Position', [100, 100, 1200, 800]);

% 子图1: 原始信号时域图
subplot(3, 2, 1);
plot(t(1:200)*1e6, analog_signal(1:200), 'b', 'LineWidth', 1.5);
hold on;
plot(t(1:200)*1e6, adc_signal(1:200), 'r--', 'LineWidth', 1);
xlabel('时间 (\mu s)');
ylabel('幅度 (V)');
title('ADC输入输出时域信号');
legend('模拟输入', 'ADC输出', 'Location', 'best');
grid on;

% 子图2: PLL时域信号
subplot(3, 2, 2);
plot(t(1:200)*1e6, pll_signal(1:200), 'g', 'LineWidth', 1.5);
xlabel('时间 (\mu s)');
ylabel('幅度 (V)');
title('PLL输出时域信号');
grid on;

% 子图3: ADC信号频谱
subplot(3, 2, 3);
semilogx(freq_adc(2:end)/1e6, dB_spectrum_adc(2:end), 'b', 'LineWidth', 1.5);
xlabel('频率 (MHz)');
ylabel('幅度 (dB)');
title('ADC输出频谱');
grid on;
xlim([freq_adc(2)/1e6, Fs/2/1e6]);

% 标记信号频率
hold on;
plot(adc_metrics.fundamental_freq/1e6, adc_metrics.signal_power_dB, 'ro', ...
     'MarkerSize', 10, 'LineWidth', 2);
text(adc_metrics.fundamental_freq/1e6, adc_metrics.signal_power_dB+5, ...
     sprintf('f0=%.3fMHz\n%.1f dB', adc_metrics.fundamental_freq/1e6, adc_metrics.signal_power_dB), ...
     'FontSize', 8);

% 子图4: PLL信号频谱
subplot(3, 2, 4);
semilogx(freq_pll(2:end)/1e6, dB_spectrum_pll(2:end), 'r', 'LineWidth', 1.5);
xlabel('频率 (MHz)');
ylabel('幅度 (dB)');
title('PLL输出频谱');
grid on;
xlim([freq_pll(2)/1e6, Fs/2/1e6]);

% 标记信号频率
hold on;
plot(pll_metrics.fundamental_freq/1e6, pll_metrics.signal_power_dB, 'bo', ...
     'MarkerSize', 10, 'LineWidth', 2);
text(pll_metrics.fundamental_freq/1e6, pll_metrics.signal_power_dB+5, ...
     sprintf('f0=%.3fMHz\n%.1f dB', pll_metrics.fundamental_freq/1e6, pll_metrics.signal_power_dB), ...
     'FontSize', 8);

% 子图5: 频谱细节对比
subplot(3, 2, [5, 6]);
plot(freq_adc/1e6, dB_spectrum_adc, 'b', 'LineWidth', 1.5);
hold on;
plot(freq_pll/1e6, dB_spectrum_pll, 'r--', 'LineWidth', 1.5);
xlabel('频率 (MHz)');
ylabel('幅度 (dB)');
title('ADC vs PLL频谱对比');
legend('ADC输出', 'PLL输出', 'Location', 'best');
grid on;
xlim([0, Fs/2/1e6]);

% 添加标注
annotation('textbox', [0.15, 0.02, 0.3, 0.1], 'String', ...
           sprintf('ADC指标:\nSNR: %.1f dB\nSFDR: %.1f dB\n噪声基底: %.1f ± %.1f dB', ...
           adc_metrics.snr_dB, adc_metrics.sfdr, adc_metrics.noise_floor, adc_metrics.noise_std), ...
           'FontSize', 9, 'EdgeColor', 'blue', 'BackgroundColor', [0.9, 0.9, 1]);

annotation('textbox', [0.6, 0.02, 0.3, 0.1], 'String', ...
           sprintf('PLL指标:\nSNR: %.1f dB\nSFDR: %.1f dB\n噪声基底: %.1f ± %.1f dB', ...
           pll_metrics.snr_dB, pll_metrics.sfdr, pll_metrics.noise_floor, pll_metrics.noise_std), ...
           'FontSize', 9, 'EdgeColor', 'red', 'BackgroundColor', [1, 0.9, 0.9]);

%% 10. 相位噪声分析 (针对PLL)
% 提取相位噪声信息
if exist('pll_signal', 'var')
    figure('Position', [100, 100, 800, 600]);
   
    % 计算相位噪声
    % 使用Hilbert变换提取瞬时相位
    analytic_signal = hilbert(pll_signal);
    instantaneous_phase = unwrap(angle(analytic_signal));
    ideal_phase = 2*pi*f0*t;
    phase_noise_rad = instantaneous_phase - ideal_phase;
   
    % 对相位噪声进行FFT
    [freq_phase, ~, dB_phase_noise] = perform_fft_analysis(phase_noise_rad, Fs, 'hann');
   
    % 转换为dBc/Hz
    % 注意:这里简化处理,实际需要更精确的归一化
    dBc_per_Hz = dB_phase_noise - 10*log10(Fs/N);
   
    % 绘制相位噪声曲线
    semilogx(freq_phase(2:end)/1e6, dBc_per_Hz(2:end), 'LineWidth', 1.5);
    xlabel('频率偏移 (MHz)');
    ylabel('相位噪声 (dBc/Hz)');
    title('PLL相位噪声分析');
    grid on;
    xlim([freq_phase(2)/1e6, Fs/2/1e6/100]);  % 只显示低频部分
   
    % 添加参考线
    hold on;
    plot([1e-3, 1e3], [pll_phase_noise, pll_phase_noise], 'r--', 'LineWidth', 1);
    text(1e-2, pll_phase_noise+5, sprintf('目标: %.0f dBc/Hz', pll_phase_noise), ...
         'FontSize', 10, 'Color', 'red');
end

%% 11. 保存结果
% 保存频谱数据
results.adc.freq = freq_adc;
results.adc.spectrum = dB_spectrum_adc;
results.adc.metrics = adc_metrics;

results.pll.freq = freq_pll;
results.pll.spectrum = dB_spectrum_pll;
results.pll.metrics = pll_metrics;

results.parameters.Fs = Fs;
results.parameters.N = N;
results.parameters.f0 = f0;
results.parameters.adc_bits = adc_bits;

% 保存到文件
save('fft_analysis_results.mat', 'results');

%% 12. 显示总结信息
fprintf('\n========== FFT频谱分析结果 ==========\n');
fprintf('采样频率: %.1f MHz\n', Fs/1e6);
fprintf('采样点数: %d\n', N);
fprintf('FFT分辨率: %.1f Hz\n', Fs/N);
fprintf('信号频率: %.3f MHz\n\n', f0/1e6);

fprintf('ADC信号分析:\n');
fprintf('  信号功率: %.1f dB\n', adc_metrics.signal_power_dB);
fprintf('  信噪比(SNR): %.1f dB\n', adc_metrics.snr_dB);
fprintf('  无杂散动态范围(SFDR): %.1f dB\n', adc_metrics.sfdr);
fprintf('  噪声基底: %.1f ± %.1f dB\n\n', adc_metrics.noise_floor, adc_metrics.noise_std);

fprintf('PLL信号分析:\n');
fprintf('  信号功率: %.1f dB\n', pll_metrics.signal_power_dB);
fprintf('  信噪比(SNR): %.1f dB\n', pll_metrics.snr_dB);
fprintf('  无杂散动态范围(SFDR): %.1f dB\n', pll_metrics.sfdr);
fprintf('  噪声基底: %.1f ± %.1f dB\n', pll_metrics.noise_floor, pll_metrics.noise_std);

fprintf('\n分析完成!结果已保存到 fft_analysis_results.mat\n');
回复 支持 2 反对 0

使用道具 举报

发表于 昨天 09:40 | 显示全部楼层


   
eaglesmiling 发表于 2025-12-11 08:56
%% ADC和PLL输出结果FFT频谱分析程序
% 作者:MATLAB助手
% 功能:对ADC和PLL输出信号进行频谱分析


点赞
回复 支持 反对

使用道具 举报

发表于 昨天 09:58 | 显示全部楼层
Thanks for sharing
回复 支持 反对

使用道具 举报

发表于 昨天 14:02 | 显示全部楼层
谢谢
回复 支持 反对

使用道具 举报

发表于 昨天 15:32 | 显示全部楼层
Thanks
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

手机版| 小黑屋| 关于我们| 联系我们| 用户协议&隐私声明| 版权投诉通道| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 ) |网站地图

GMT+8, 2025-12-12 03:49 , Processed in 0.015107 second(s), 4 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表