但是要主意输入信号的定点格式 ,正弦信号用Q64.64 ,也就是字长128,小数位数64,得到的结果完美。
但是要是Q2.14则是无意义的结果。
代码:
点击查看代码
%% 生成sin信号并使用定点FFT计算频谱 - 带错误诊断
clear; clc; close all;%% 参数设置
Fs = 1000; % 采样频率 1kHz
f0 = 50; % 信号频率 50Hz
A = 1; % 信号幅度
N = 256; % FFT点数
t = (0:N-1) / Fs; % 时间向量% 定点参数
wordLength = 128 ;%16; % 总字长
fractionLength = 64;%14; % 小数位长度fprintf('信号参数: %.1fHz正弦波, 采样率%.1fHz, FFT点数%d\n', f0, Fs, N);
fprintf('定点参数: %d位, 小数位%d位\n', wordLength, fractionLength);%% 生成sin信号
signal_float = A * sin(2*pi*f0*t);% 创建定点信号
signal_fi = fi(signal_float, 1, wordLength, fractionLength);fprintf('信号范围: [%.6f, %.6f]\n', min(signal_fi), max(signal_fi));%% 配置定点FFT - 带详细错误诊断
tryfprintf('\n=== 开始配置定点FFT ===\n');fft_fixed = dsp.FFT();fprintf('✓ dsp.FFT对象创建成功\n');fft_fixed.FFTLengthSource="Property" ;fft_fixed.FFTLength = N;fprintf('✓ FFTLength设置成功\n');nt_sine = numerictype('WordLength', wordLength, 'FractionLength', fractionLength, 'Signedness', 'Auto'); nt_sine.Scaling = 'Unspecified';nt_product = numerictype('WordLength', wordLength, 'FractionLength', fractionLength, 'Signedness', 'Auto');nt_accumulator = numerictype('WordLength', wordLength, 'FractionLength', fractionLength, 'Signedness', 'Auto');nt_output = numerictype('WordLength', wordLength, 'FractionLength', fractionLength, 'Signedness', 'Auto');properties_to_set = {{'RoundingMethod', 'Nearest'},{'OverflowAction', 'Saturate'},{'SineTableDataType', 'Custom'},{'CustomSineTableDataType', nt_sine} ,{'ProductDataType', 'Custom'},{'CustomProductDataType', nt_product},{'AccumulatorDataType', 'Custom'},{'CustomAccumulatorDataType', nt_accumulator},{'OutputDataType', 'Custom'},{'CustomOutputDataType', nt_output}};for i = 1:length(properties_to_set)prop_name = properties_to_set{i}{1};prop_value = properties_to_set{i}{2};tryif ischar(prop_value)set(fft_fixed, prop_name, prop_value);elseset(fft_fixed, prop_name, prop_value);endfprintf('✓ %s 设置成功\n', prop_name);catch MEfprintf('❌ %s 设置失败:\n', prop_name);fprintf(' 错误信息: %s\n', ME.message);fprintf(' 错误标识符: %s\n', ME.identifier);fprintf(' 属性值类型: %s\n', class(prop_value));if isnumeric(prop_value) || isa(prop_value, 'embedded.numerictype')fprintf(' 属性值: %s\n', char(prop_value));end% 显示属性信息fprintf(' 属性信息:\n');meta_info = findprop(fft_fixed, prop_name);if ~isempty(meta_info)fprintf(' 类型: %s\n', meta_info.DataType);if ~isempty(meta_info.Description)fprintf(' 描述: %s\n', meta_info.Description);endendrethrow(ME);endendfprintf('\n✓ 所有定点FFT配置完成\n');%% 执行定点FFTfprintf('\n执行定点FFT计算...\n');fft_output_fixed = fft_fixed(signal_fi');fprintf('✓ 定点FFT计算成功\n');fft_output_float = double(fft_output_fixed);mag_fixed = abs(fft_output_float(1:N/2)) / (N/2);catch MEfprintf('\n❌ 定点FFT配置或计算失败!\n');fprintf('主要错误: %s\n', ME.message);fprintf('错误标识符: %s\n', ME.identifier);% 显示完整错误堆栈fprintf('\n错误堆栈:\n');for i = 1:length(ME.stack)fprintf(' %s (第%d行)\n', ME.stack(i).name, ME.stack(i).line);end% 尝试简化配置fprintf('\n=== 尝试简化配置 ===\n');tryfft_simple = dsp.FFT('FFTLength', N);fft_output_simple = fft_simple(signal_fi');mag_fixed = abs(fft_output_simple(1:N/2)) / (N/2);fprintf('✓ 简化配置成功 - 使用默认定点设置\n');catch ME2fprintf('简化配置也失败: %s\n', ME2.message);% 最后备选:使用浮点FFTfprintf('使用浮点FFT作为最后备选\n');fft_float_temp = fft(double(signal_fi));mag_fixed = abs(fft_float_temp(1:N/2)) / (N/2);end
end%% 浮点FFT作为参考
fft_float = fft(signal_float);
mag_float = abs(fft_float(1:N/2)) / (N/2);%% 频率轴
freq_axis = (0:N/2-1) * Fs / N;%% 计算误差
error_val = abs(mag_float - double(mag_fixed));%% 性能分析
[peak_float, idx_float] = max(mag_float);
freq_float = freq_axis(idx_float);
[peak_fixed, idx_fixed] = max(mag_fixed);
freq_fixed = freq_axis(idx_fixed);
max_error = max(error_val);
rms_error = rms(error_val);fprintf('\n性能对比:\n');
fprintf('浮点FFT: 峰值 %.4f @ %.1fHz\n', peak_float, freq_float);
fprintf('定点FFT: 峰值 %.4f @ %.1fHz\n', peak_fixed, freq_fixed);
fprintf('最大误差: %.6f, RMS误差: %.6f\n', max_error, rms_error);%% 绘制图形
figure('Position', [100, 100, 1400, 600]);% 子图1: 时域信号
subplot(1,3,1);
plot(t, signal_float, 'b-', 'LineWidth', 1.5);
hold on;
plot(t, double(signal_fi), 'ro', 'MarkerSize', 3, 'MarkerFaceColor', 'r');
xlabel('时间 (s)');
ylabel('幅度');
title('时域信号');
legend('浮点信号', '定点信号', 'Location', 'northeast');
grid on;% 子图2: 浮点FFT频谱
subplot(1,3,2);
stem(freq_axis, mag_float, 'b.', 'MarkerSize', 10, 'LineWidth', 1);
xlabel('频率 (Hz)');
ylabel('幅度');
title('浮点FFT频谱');
xlim([0, 200]); ylim([0, 1.2]);
grid on;
hold on;
plot(freq_float, peak_float, 'ro', 'MarkerSize', 10, 'LineWidth', 2);
text(freq_float, peak_float+0.15, sprintf('峰值: %.4f\n频率: %.1fHz', peak_float, freq_float), ...'HorizontalAlignment', 'center', 'FontWeight', 'bold', 'FontSize', 9);% 子图3: 定点FFT频谱
subplot(1,3,3);
stem(freq_axis, double(mag_fixed), 'r.', 'MarkerSize', 10, 'LineWidth', 1);
xlabel('频率 (Hz)');
ylabel('幅度');
title('定点FFT频谱');
xlim([0, 200]); ylim([0, 1.2]);
grid on;
hold on;
plot(freq_fixed, peak_fixed, 'bo', 'MarkerSize', 10, 'LineWidth', 2);
text(freq_fixed, peak_fixed+0.15, sprintf('峰值: %.4f\n频率: %.1fHz', peak_fixed, freq_fixed), ...'HorizontalAlignment', 'center', 'FontWeight', 'bold', 'FontSize', 9);% 总标题
sgtitle(sprintf('定点FFT频谱分析 (%.0fHz正弦信号, %d点FFT, %d位定点)', f0, N, wordLength), ...'FontSize', 14, 'FontWeight', 'bold');fprintf('\n图形已生成完成!\n');
点击查看代码
% 定点参数
wordLength = 16;%128 ;%16; % 总字长
fractionLength = 14;%64;%14; % 小数位长度