包络跟踪与脉宽调制功能异常,FFT结果不符预期求助
问题描述
我正在实现包络跟踪(Envelope tracking)与脉宽调制(Pulse width modulation)功能。本次实验中,使用1MHz正弦波,以3MHz频率对其采样,每个采样值决定周期为0.33μs的脉冲信号的占空比。
脉冲信号:
正弦波:
对脉冲信号进行FFT分析时,期望能看到1MHz的频率成分,但实际频域图如下:
请问哪里操作出错了?
以下是实验代码:
pkg load signal clear all; close all; % Parameters f_sine = 1e6; % Frequency of the sine wave (1 MHz) t_sine = 2e-6; % Time duration to plot (2 us) f_sample = 3e6; % Sampling frequency (3 MHz) t_sample = 0:1/f_sample:t_sine; % Time vector for sampled signal t_cont = linspace(0, t_sine, 1000); % Sine wave sine_wave_cont = 1 + sin(2 * pi * f_sine * linspace(0, t_sine, 1000)); % Continuous sine wave from 0 to 2 sine_wave_sample = 1 + sin(2 * pi * f_sine * t_sample); % Sampled sine wave % Compute percentage of sampled amplitude compared to max amplitude max_amplitude = max(sine_wave_sample); percentage_amplitude = (sine_wave_sample / max_amplitude) * 100; % Square wave parameters T_square = 0.33e-6; % Period of the square wave (0.33 us) % Initialize the array for the square wave with varying duty cycles square_wave_varying = []; % Generate the square wave with varying duty cycle for i = 1:length(percentage_amplitude) duty_cycle = percentage_amplitude(i)*0.9; t_current = linspace(0, T_square, 1000); % Time vector for the current period if length(t_current) > 1 square_wave_current = 0.5 * (square(2 * pi * (1/T_square) * t_current, duty_cycle) + 1); square_wave_varying = [square_wave_varying, square_wave_current(1:end-1)]; % Avoid overlapping periods end end % Adjust time vector for the concatenated square wave t_varying = linspace(0, length(square_wave_varying)/f_sample, length(square_wave_varying)); % Plot continuous sine wave figure; plot(linspace(0, t_sine, 1000) * 1e6, sine_wave_cont); % Time in us for x-axis ylim([-0.5 2.5]); xlabel('Time (us)'); ylabel('Amplitude'); title('Sine Wave at 1 MHz'); grid on; % Turn on grid % Plot square wave with varying duty cycle figure; plot(t_varying * 1e3, square_wave_varying); % Time in us for x-axis ylim([-0.2 1.4]); xlabel('Time (us)'); ylabel('Amplitude'); title('Square Wave with Varying Duty Cycle'); grid on; % Turn on grid % Plot percentage amplitude figure; stem(t_sample * 1e6, percentage_amplitude, 'filled'); % Time in us for x-axis ylim([0 110]); xlabel('Time (us)'); ylabel('Percentage Amplitude'); title('Percentage Amplitude of Sampled Sine Wave at 3 MHz'); grid on; % Turn on grid % Frequency domain analysis N = length(square_wave_varying); % Number of points f = (0:N-1)*(f_sample/N); % Frequency range Y = fft(square_wave_varying); % Compute FFT % Plot frequency spectrum figure; plot(f(1:N/2)/1e6, abs(Y(1:N/2))); % Plot single-sided amplitude spectrum xlabel('Frequency (MHz)'); ylabel('Magnitude'); title('Frequency Spectrum of Square Wave with Varying Duty Cycle'); grid on; % Turn on grid
问题分析与修正方案
核心错误点
采样频率与PWM周期不匹配
设定的采样频率是3MHz(采样周期≈0.333μs),但PWM周期设为0.33μs,两者周期存在偏差,导致每个PWM周期内的采样点数量不固定,且后续FFT计算时错误使用了3MHz作为采样率,实际生成的PWM波采样率远高于此(每个周期1000点,采样率≈3.03GHz),频率轴完全失真。FFT频率轴计算错误
t_varying的生成逻辑错误,直接用length(square_wave_varying)/f_sample计算总时长,但实际PWM波的采样率是1000/T_square,不是3MHz,导致频率轴刻度完全错误,无法正确显示1MHz成分。信号时长过短
仅采集了2μs的正弦波(对应2个周期),FFT的频率分辨率为1/t_sine=500kHz,难以清晰分辨1MHz的频率成分,频谱会出现严重的泄漏。占空比计算冗余
对采样后的正弦波除以max_amplitude再乘以100,额外引入了缩放误差,原正弦波1+sin(...)的范围是02,直接归一化到0100%即可,无需除以最大值。
修正后的代码
pkg load signal clear all; close all; % Parameters f_sine = 1e6; % 1MHz正弦波频率 t_total = 10e-6; % 延长信号时长到10μs,提高FFT分辨率 f_sample = 3e6; % 3MHz采样频率 T_sample = 1/f_sample; % 采样周期≈0.333μs,与PWM周期对齐 t_sample = 0:T_sample:t_total-T_sample; % 采样时间向量 % 生成正弦波(范围0~2,直接用于占空比计算) sine_wave_sample = 1 + sin(2 * pi * f_sine * t_sample); % 归一化到0~100%的占空比,无需除以max_amplitude(原信号范围固定) duty_cycles = (sine_wave_sample / 2) * 100; % 可选:保留0.9的缩放,避免占空比达到100% duty_cycles = duty_cycles * 0.9; % 生成PWM波:每个采样周期对应一个PWM周期,每个周期用固定采样点 pwm_samples_per_cycle = 100; % 每个PWM周期采样点数 T_pwm = T_sample; % PWM周期与采样周期对齐 t_pwm_cycle = linspace(0, T_pwm, pwm_samples_per_cycle+1); t_pwm_cycle = t_pwm_cycle(1:end-1); % 去掉最后一个点避免重叠 square_wave_varying = []; for dc = duty_cycles % 生成单个PWM周期的波形 pwm_cycle = 0.5 * (square(2*pi*(1/T_pwm)*t_pwm_cycle, dc) + 1); square_wave_varying = [square_wave_varying, pwm_cycle]; end % 计算实际PWM波的采样率 f_pwm_sample = pwm_samples_per_cycle / T_pwm; t_varying = linspace(0, t_total, length(square_wave_varying)); % 绘图部分 figure; plot(t_sample*1e6, sine_wave_sample); xlabel('时间 (μs)'); ylabel('幅度'); title('1MHz正弦波(3MHz采样)'); grid on; figure; plot(t_varying*1e6, square_wave_varying); xlabel('时间 (μs)'); ylabel('幅度'); title('变占空比PWM波'); grid on; % FFT分析 N = length(square_wave_varying); % 用实际PWM采样率计算频率轴 f = (0:N-1)*(f_pwm_sample/N); Y = fft(square_wave_varying); % 归一化幅度 Y_amp = 2*abs(Y)/N; figure; % 只显示0~5MHz的范围,聚焦目标频率 plot(f(1:N/2)/1e6, Y_amp(1:N/2)); xlabel('频率 (MHz)'); ylabel('幅度'); title('PWM波频谱'); xlim([0 5]); grid on;
修正后效果说明
- 对齐了PWM周期与采样周期,保证每个采样点对应一个PWM周期,逻辑更清晰。
- 延长信号时长到10μs,FFT分辨率提升到100kHz,能清晰分辨1MHz的频率成分。
- 使用实际PWM波的采样率计算频率轴,频谱刻度准确。
- 简化占空比计算,避免不必要的缩放误差。
内容的提问来源于stack exchange,提问作者fpga_noob
相关产品推荐
相关产品推荐

