简介面向信号处理与ADC性能分析场景的MATLAB程序包主要用于计算SNR、SNDR、THD、ENOB、SFDR等关键指标适合电子工程、通信及测试测量领域的工程师和学生使用可快速评估数据采集系统的信号质量与失真程度。包体十分精简共包含2个文件1个m脚本负责执行FFT频谱分析、谐波提取和功率比值计算1个txt文件提供原始采样数据压缩包大小仅4KB。目前已有4556人学习过这套程序。运行脚本后可直接从时域数据中分离信号、噪声及失真分量输出各项参数数值并支持依据SNR推算ENOB帮助使用者掌握从频谱到性能指标的完整分析流程。程序所附说明对上述指标的定义与计算方式做了系统梳理可作为ADC测试、音频处理及通信链路评估的参考工具。1. SNR、SNDR、THD、ENOB、SFDR到底是什么先搞清楚你要算哪个指标ADC和信号链评估里SNR、SNDR、THD、ENOB、SFDR这五个指标几乎是必看的但很多工程师用MATLAB算出来的数值和手册对不上怀疑程序写错了。其实大多数情况不是程序错而是你对FFT的参数设置和统计口径定义跟芯片厂商不一样。比如SNR到底要不要扣掉直流和谐波SNDR里噪声功率是否包含失真项SFDR找的是非谐波杂散还是包括谐波这些差异会让结果差好几个dBENOB甚至差1 bit以上。这篇笔记就把从采集数据到出这五个指标的完整MATLAB计算程序讲清楚包含FFT前置参数、统计口径、边界条件以及常见翻车现场。适合正在调ADC采集板、写上位机分析脚本或者想验证网上流传脚本是否靠谱的从业者。2. 从采集数据到频谱MATLAB里做 FFT 前必须搞定的四个参数2.1 相干采样为什么频率要精确落在 bin 上FFT 的结果是一条条离散谱线相邻两条谱线的间隔是 Fs/N。如果你的信号频率 f0 不恰好落在某条谱线bin上能量就会泄漏到附近很多 bin 里。泄漏掉的那部分能量会被后面的程序当成噪声计算出来的 SNR 会明显偏低而且偏低多少取决于泄漏的严重程度完全不是恒定值。这就是为什么网上很多“一键计算 ADC 指标”的脚本看起来好用换一组数据就翻车。相干采样的数学条件很简单采样点数 N、采样率 Fs、信号频率 f0 要满足下式其中 k 必须是整数。% 相干采样条件k f0 * N / Fs 必须为整数 % 如果 k 不是整数信号能量会扩散到多个 bin f0 1.00035e6; % 信号频率 1.00035 MHz N 8192; % FFT 点数 Fs 65e6; % 采样率 65 MHz k f0 * N / Fs; % 计算 bin 序号上面这个例子里 k 1.00035e6 * 8192 / 65e6 ≈ 126.28不是整数所以直接做 FFT 必定泄漏。要改成相干采样最直接的办法是固定 Fs 和 N反推 f0 的一个可取整数值。比如让 k126那 f0 k * Fs / N 126 * 65e6 / 8192 999.023 kHz这不是 1.00035 MHz 了。如果你必须用 1.00035 MHz那就得调整 N比如 N 8192 不行就试 10000但要保证 FFT 点数最好是 2 的整数次幂。实际现场的做法是用信号发生器输出一个“算好”的频率或者用锁相环让采样时钟与信号同步。注意相干采样同时保证了信号频率的整数倍谐波也落在 bin 上因为谐波频率就是 f0 的整数倍。2.2 采样点数 N 和采样率 Fs 怎么选分辨率与漏谱N 的选择直接影响频率分辨率也直接影响你最高能看到几次谐波。FFT 的频率分辨率是 Fs/N想要分辨出相邻的杂散至少要保证频率间隔大于这个值。对于 ADC 动态指标测量我一般至少取 4096 点常用 8192 或 16384。点太少噪声底平滑不下来谐波和信号容易“挤”在一起点太多计算量倒不是问题但采集时间拉长对信号源的稳定度要求更高。采样率 Fs 则决定了奈奎斯特频率 Fs/2。你需要确保你想看的谐波次数都在奈奎斯特范围内。比如 f0 是 1 MHzFs 是 10 MHz那么到第 4 次谐波是 4 MHz第 5 次谐波 5 MHz刚好到奈奎斯特。超过 5 次的谐波会被折叠到低频如果不做专门处理直接按整数倍频率在频谱里找是找不到的。常见做法是先算一下最高可用谐波次数f0 1e6; % 信号频率 Fs 10e6; % 采样率 N 8192; % FFT 点数 k round(f0 * N / Fs); % 相干 bin 序号取整后需要回头微调 f0 Nharm_max floor(Fs / (2 * f0)) - 1; % 能完整看到的最高谐波次数这里 Nharm_max 是取整后减一因为第 floor(Fs/(2*f0)) 次谐波恰好落在奈奎斯特频率上幅值已经被压缩通常不算。如果你的实际谐波次数超过这个数要么提高 Fs要么接受混叠并利用第 4 章的镜像频率修正不要指望用固定 10 次谐波就能搞定高频信号。2.3 窗函数加窗和不加窗的结果能差好几个 dB相干采样时理论上不加窗矩形窗最干净信号完全在一个 bin 里能量没有泄漏SNR 计算最准确。但实际采集总有相位噪声、时钟抖动以及信号源本身的不稳定导致信号不完全落在单一 bin 上。这时候加窗可以减少泄漏对噪声功率的影响但代价是信号主瓣变宽且信号总能量被重新分配。常用的汉宁窗Hann主瓣较窄旁瓣衰减快适合 ADC 测试。加窗后有一个关键问题信号功率不再是简单的 mag(bin)^2因为窗函数对信号有加权需要除以窗的平均功率相干增益。对于周期汉宁窗相干增益是 0.5所以加窗后的信号功率要乘以 2 修正。若不加这个修正SNDR 算出来会比真实值低 3 dBENOB 也会差约 0.5 bit。下面是一段加窗后取幅度谱的示例注意修正项。N length(x); w hanning(N, periodic); % 周期汉宁窗FFT 常用 xw x(:) .* w(:); X fft(xw); mag abs(X(1:N/21)) / sum(w) * 2; % 除以窗求和并乘 2 得到单边幅度 mag(1) mag(1) / 2; % DC 不乘 2 f (0:N/2) * Fs / N;上面 sum(w) 是窗采样值的累加用这个做归一化比直接除以 N 更稳。注意如果算法内部用了加窗那么后面找信号、谐波功率时就要用这个修正过的 mag如果后面第 3 章的代码用的是矩形窗就不要混着用。很多翻车现场就是主函数没加窗测试数据却加了窗再传进来结果信号功率偏小一半。2.4 频谱数据怎么取幅度和相位FFT 输出的复数数组中第 1 个元素是直流第 2 个到第 N/21 个是 0 到 Fs/2 的正频率部分。单边频谱幅度需要把除了直流和奈奎斯特之外的所有幅度乘以 2因为负频率能量被叠加到了正频率上。奈奎斯特频率索引 N/21只有实数采样不要乘 2。相位用 angle() 取但对 SNR 计算不重要除非你要做相位噪声分析。下面是一个标准化的频谱提取代码也是后面所有指标计算的基础。function [f, mag] single_side_spectrum(x, Fs) % 输入采集数据 x 和采样率 Fs输出频率轴和归一化幅度谱 N length(x); X fft(x); X X(1:N/21); mag abs(X) / N; % 除以 N 使幅度归一到原始信号幅度 mag(2:end-1) mag(2:end-1) * 2; % 单边修正 f (0:N/2) * Fs / N; end注意除以 N 而不是除以 N/2因为 FFT 默认是双边谱。同样上面这段代码针对的是矩形窗如果加窗要改成sum(w)的方式。幅度谱的单位是原始信号单位比如 ADC 码值或电压后面计算功率时直接用幅度平方不需要再转成实际物理单位因为 SNR 等指标都是比值单位会抵消。3. 基于 FFT 的 SNR/SNDR/THD/SFDR/ENOB 计算完整 MATLAB 函数与调用示例3.1 主函数代码与逐段解释这里给出一个完整可运行的 MATLAB 函数。它假设输入数据满足相干采样内部使用矩形窗不额外加窗处理。代码里我尽量把每一步的统计口径都写清楚方便你对照和理解。function [SNR, SNDR, THD, SFDR, ENOB] calc_adc_dynamic(x, Fs, f0, Nharm) % 基于相干采样的 ADC 动态参数计算程序 % 输入 % x : 采集的数据向量列向量长度 N 最好是 2 的幂 % Fs : 采样率单位 Hz % f0 : 信号频率单位 Hz需满足 f0*length(x)/Fs 为整数 % Nharm: 计算 THD 时包含的最高谐波次数例如 5 表示计算 2~5 次谐波 % 输出 % SNR : 信噪比dB % SNDR : 信号与噪声加失真比dB % THD : 总谐波失真dB负值表示谐波功率低于信号 % SFDR : 无杂散动态范围dB % ENOB : 有效位数bit N length(x); if mod(N, 2) 1 x x(1:end-1); % 确保点数为偶数方便单边谱处理 N N - 1; end X fft(x); X X(1:N/21); % 取单边频谱 mag abs(X) / N; % 归一化幅度 mag(2:end-1) mag(2:end-1) * 2; % 单边谱修正 freq (0:N/2) * Fs / N; % 频率轴 % ---- 找到信号 bin ---- [~, k0] min(abs(freq - f0)); k0 k0; % MATLAB 索引从 1 开始 P_sig mag(k0)^2; % 信号功率 % ---- 找谐波功率 ---- P_harm 0; k_harm false(size(mag)); % 用于标记谐波所在 bin for h 2:Nharm1 fh h * f0; if fh Fs/2 break; % 超出奈奎斯特就不再计算 end [~, kh] min(abs(freq - fh)); kh kh; P_harm P_harm mag(kh)^2; k_harm(kh) true; end % ---- 噪声功率剔除直流、信号、谐波后所有 bin 的功率和 ---- mask true(size(mag)); mask(1) false; % 去除直流 mask(k0) false; % 去除信号 mask(k_harm) false; % 去除谐波 P_noise sum(mag(mask).^2); % ---- 指标计算 ---- SNR 10 * log10(P_sig / P_noise); SNDR 10 * log10(P_sig / (P_noise P_harm)); THD 10 * log10(P_harm / P_sig); % 结果为负值单位 dBc SFDR 10 * log10(P_sig / max(mag(~mask ~k_harm).^2)); % 见下方修正 ENOB (SNDR - 1.76) / 6.02; end上面这段代码有一个问题SFDR 那行的逻辑索引写法不对。~mask表示直流和信号所在的地方~k_harm表示非谐波两个取交集正好是噪声区域实际上我们需要的是“除信号和直流之外所有位置的最大值”应该重新定义。修正如下。STD 做法是把 SFDR 定义为最大杂散不含信号但包含谐波与信号之比。所以应该在“去除 DC 和信号”的范围内找最大值。修改后的关键行% ---- 计算 SFDR排除直流和信号后最大分量含谐波 ---- mask_spur true(size(mag)); mask_spur(1) false; mask_spur(k0) false; P_spur_max max(mag(mask_spur).^2); SFDR 10 * log10(P_sig / P_spur_max);把这一段替换到前面代码中。噪声功率里仍然要排除谐波否则 SNDR 会重复计入谐波。注意如果你的实际测试中直流附近有低频 1/f 噪声SFDR 会常常在最低频处取到这不一定是你关心的杂散使用时可结合频谱图判断。3.2 信号功率、谐波功率、噪声功率的统计口径信号功率就是信号 bin 的幅度平方。在相干采样和矩形窗下这个 bin 集中了信号几乎全部能量。谐波功率是每一次谐波 bin 的幅度平方总和。噪声功率是除了直流、信号、谐波外所有 bin 的幅度平方和。这个统计口径对 SNR 来说是“谐波不算噪声”对 SNDR 来说是“谐波算失真也参与惩罚”。如果你的目标是看 ADC 的纯净噪声底用 SNR如果你关心信号链有无失真用 SNDR。数据手册里通常两者都会给且 SNDR 会低于 SNR差值就是谐波失真贡献的。用这个函数之前先确认数据长度如果数据长度是奇数函数会丢掉最后一个点但这可能破坏相干性。最好的办法是在采集端就把长度控制为 2 的幂而不是依赖程序去裁剪。如果已经是非相干数据请先按第 4 章的方法加窗插值再调用这个函数否则会得出偏低的值。3.3 SNR 和 SNDR 的区别噪声要不要把谐波算进去SNR 只关心噪声不管谐波。SNDR 把谐波和噪声加到一起英文也叫 SINAD。实际使用中如果一个 ADC 的 THD 很差但噪声底很低SNR 会很好看但 SNDR 会拉低而直接反映动态性能的是 SNDR。你在对比不同芯片时不能只看 SNR一定要 SNDR、THD、SFDR 一起看。程序里SNDR 10*log10(P_sig / (P_noise P_harm))分母是噪声加谐波功率分子是信号功率这个公式最直观。3.4 THD 和 SFDR 的计算细节THD 是谐波总功率与信号功率之比用 dB 表示时通常为负值。有的软件会取绝对值显示例如 -80 dBc 写成 80 dBc含义是谐波比信号低 80 dB。代码里THD 10*log10(P_harm / P_sig)注意 P_harm 是各次谐波功率求和。谐波次数一般取到奈奎斯特前的全部次数但如果信号频率很低谐波次数可能很多而高次谐波幅度通常很小到最后会淹没在噪声底里取太多反而把噪声计入 THD。所以一般取 5 次或 10 次结合 Nharm_max 判断。SFDR 是最大杂散spur与信号的比值这里杂散排除直流和信号本身但谐波也算杂散。在很多数据手册里SFDR 看到的值往往直接是最大的那一次谐波尤其是二次或三次谐波。如果你的程序把谐波排除在外那 SFDR 就只反映非谐波杂散这会导致你测出来的 SFDR 偏高跟手册对不上。我建议代码里把谐波也纳入杂散搜索这样得到的是最严格的动态范围指标。3.5 ENOB 从 SNDR 推算ENOB 最常用的公式是(SNDR - 1.76) / 6.02其中 1.76 dB 是理想 N bit 量化器在满摆幅正弦输入下的理论 SNR6.02 dB 对应每 bit 的增益。如果你用 SNR 而不是 SNDR 去推得到的是“噪声 ENOB”没有计入失真数值会偏高。多数芯片手册里的 ENOB 是用 SNDR 算出来的所以程序里必须用 SNDR。另外一个常见误区是当 SNDR 低于 0 dB 时ENOB 变成负数这表示失真已经淹没了信号实际测试中通常需要减小输入幅度或检查采集链路。下面是一个调用示例通过合成一段理想正弦加噪声来验证函数% 生成相干采样信号Fs65MHz, N8192, f01MHz Fs 65e6; N 8192; f0 Fs * 100 / N; % 100 是整数 binf0 793.65 kHz你随意设整数即可 t (0:N-1) / Fs; x 0.5 * sin(2*pi*f0*t); % 幅度 0.5单位 V x x 0.001 * randn(N, 1); % 加白噪声约 0.001 V RMS [SNR, SNDR, THD, SFDR, ENOB] calc_adc_dynamic(x, Fs, f0, 5); fprintf(SNR%.2f dB\nSNDR%.2f dB\nTHD%.2f dBc\nSFDR%.2f dBc\nENOB%.2f bit\n, ... SNR, SNDR, THD, SFDR, ENOB);上面 f0 被设置为Fs * 100 / N这里 100 是 bin 序号任意整数都满足相干采样。注意实际程序中 f0 要由你指定而信号源频率必须严格等于这个值否则泄漏会回来。4. 边界条件与进阶处理非相干采样、多音信号和直流分量怎么处理4.1 直流分量要不要算进信号功率直流分量通常不算作信号。ADC 的直流偏置可能来自输入共模、偏移误差它不携带有用信息如果把它算作信号SNR 会高得离谱甚至可能变成正的无限大如果噪声为零。所以代码里明确把 DC bin 排除了。如果你的信号本身是带直流的那 DC 算信息ADC 动态测试针对交流信号一律剔除直流。如果你测的是低频或直流量那就不是这五个指标的适用场景了。另外直流附近可能有数 kHz 范围内的 1/f 噪声它们不属于谐波会被计入噪声功率。如果你的测试信号频率很低比如 1 kHz1/f 噪声会显著影响 SNR这是 ADC 本身的特性不是程序错误。如果想测量真正的宽带噪声底可以适当提高输入信号频率到几 MHz 以上。4.2 非相干采样时用窗函数和插值修正很多时候现场做不到严格相干采样信号频率由晶振决定采样率也是固定的两者不正好成整数关系。这时继续用矩形窗算出来的 SNR 一定偏低。常见做法是加汉宁窗然后对信号频率做抛物线插值修正再把插值后的信号功率取出来。加窗之后信号的幅度谱会变宽主瓣内会有多个 bin。先找到幅度峰值 bin然后利用相邻两个 bin 的幅度做二次插值得到真实峰值频率和幅值。汉宁窗的插值公式比较成熟但为了实用我这里给一个简化但有效的“两步走”办法function [f_interp, amp_interp] interpolated_peak(mag, freq, k0) % 对峰值 bin 附近做抛物线插值返回更精确的频率和幅度 % 输入 mag: 单边幅度谱freq: 频率轴k0: 峰值 bin 索引 % 输出插值后的频率和幅度 k0 max(2, min(length(mag)-1, k0)); % 边界保护 y1 mag(k0-1); y2 mag(k0); y3 mag(k01); % 抛物线极值偏移量单位bin delta (y1 - y3) / (2 * (y1 - 2*y2 y3)); f_interp freq(k0) delta * (freq(2)-freq(1)); % 修正幅值 a (y2 - y1) / (delta - 1) / (freq(2)-freq(1)); % 略复杂的二次系数这里不展开 amp_interp y2 - 0.25 * (y1 - y3) * delta; end注意这个插值公式在窗函数不同时略有变化。如果你是汉宁窗这个简化公式通常能到 0.1 dB 以内。完整方案里还需要把信号功率定义为插值后幅度的平方然后从总功率中剔除主瓣附近几个 bin比如 ±5作为信号泄漏而不是单单剔除一个 bin。虽然代码变复杂但结果更接近真实值。4.3 多音信号下的 SFDR 和互调分量单频测试只能反映谐波失真多音测试能暴露互调失真。多音信号的 SFDR 计算要复杂得多因为除了各个基波和谐波还有基波之间的互调分量比如 f1f2f1-f22f1-f2。程序没法自动识别所有互调产物我一般不会写一个万能函数而是针对固定的测试信号配置提前把互调频率算出来再在频谱里找。如果你只需要粗略评估可以用两音测试频率 f1 和 f2 都满足相干采样各自单独满足整数 bin然后扫描所有 bin排除两个信号和它们的谐波以及 DC剩下的最大分量就是最强互调或杂散。但这要求你不是通用函数而是针对一组固定频率写死。对于通用程序建议只对单频信号算 SFDR多音场景单独写脚本不要指望一个函数通吃。4.4 谐波次数的选取取到奈奎斯特频率内还是固定 10 次谐波理论上会一直存在直到幅度低于噪声底。但谐波一旦超过奈奎斯特频率会被混叠到低频看起来像是一个新的杂散且它和原谐波功率相同如果不考虑抗混叠。所以有两种处理思路要么让谐波全部落在奈奎斯特内这样直接按整数倍频率找要么允许混叠然后计算混叠后的频率。后者需要知道谐波原始次数和折叠规律容易出错。我建议在实际测试中先选择 f0 使得前 5 次谐波不超过 Fs/2这通常不难。比如用 10 MHz 采样f0 设置 1 MHz前 5 次谐波到 5 MHz刚好在奈奎斯特内。然后程序里Nharm5就够用了。如果信号频率很接近 Fs/2连二次谐波都可能超出这时只能降低输入频率。不要为了追求“把谐波取全”而死磕混叠修正因为混叠后的谐波会和真实杂散叠加你根本分不清哪个是真正的杂散。第 5 章会讲一个因为混叠导致的 THD 异常案例。5. 计算程序常见问题与排查为什么你算出来的 ENOB 比手册低 1 bit5.1 频谱泄漏导致 SNR 虚低现象、原因、解决现象用同一个 ADC 采集卡喂一个干净正弦程序算出来的 SNR 只有 60 dB而数据手册写的是 75 dB。把数据画出来频谱峰值附近有一串逐渐衰减的梳状旁瓣。原因信号频率不满足相干采样f0*N/Fs不是整数FFT 能量泄漏到了旁瓣泄漏的功率被计入了噪声SNR 被压低。解决先检查 k 值是否接近整数。如果差 0.1 个 bin泄漏已经不可忽视了。要么调整信号源频率到最接近的整数 bin 对应的频率要么用加窗插值算法。临时补救也可以把数据乘以汉宁窗再用第 4 章的插值处理。5.2 窗函数选错导致 SNDR 偏差现象、原因、解决现象同一组数据直接用矩形窗算 SNDR 70 dB加上汉宁窗后算 SNDR 67 dB差了 3 dB。你以为是窗函数带来的固有衰减其实不是。原因加窗后没有除以窗的相干增益。汉宁窗的相干增益是 0.5信号功率被折半而噪声功率没有折半SNDR 就少了约 3 dB。解决用xw x .* hann(N,periodic)后幅度归一化要改成abs(fft(xw)) / sum(w)或对求出的幅度平方乘以 2。如果你用自带函数一定要确认它的归一化方式。5.3 谐波位置算错导致 THD 偏大现象、原因、解决现象输入频率 5 MHz采样率 10 MHz程序算 THD 是缺口负十几 dB明显不合理。打印谐波位置发现程序在找 2 次谐波 10 MHz 时实际上 10 MHz 是奈奎斯特频率幅度被严重压缩但程序依然取那个 bin。原因谐波频率 fh h*f0 超过 Fs/2 后本应发生混叠而程序仍然用原频率索引来找 bin找到的是错误位置。解决在找谐波前先判断fh Fs/2如果是就计算混叠后的频率f_alias Fs - fh假设 fh 在 Fs/2 到 Fs 之间。如果 fh 超过 Fs则先对 Fs 取模再折叠。最简单的办法是保证测试时最高谐波不超过 Fs/2从源头避免这个坑。5.4 噪声功率统计把信号泄漏旁瓣算入导致 SNR 偏低现象、原因、解决现象输入信号已经是相干采样频谱很干净但计算出的 SNR 比理论值低 0.5 dB。检查发现信号 bin 旁边第 2 个和第 3 个 bin 的幅度比噪声底高出一截。原因相干采样只保证峰值 bin 集中能量但实际信号源有相位噪声或者 ADC 的时钟有抖动会导致少量能量扩散到相邻几个 bin。程序把这些 bin 当成了噪声SNR 自然偏低。解决在噪声功率统计时排除信号 bin 左右各几个 bin比如排除 5 个。修改代码excl 5; % 排除信号左右各 5 个 bin lo max(2, k0-excl); hi min(N/2, k0excl); mask(lo:hi) false; % 注意不要误伤谐波如果谐波距离信号很近可考虑单独处理注意如果排除范围太大会把真实噪声也删掉SNR 会虚高。一般左右各 5 是经验值对于 8192 点 FFT 不会造成明显影响。同样谐波 bin 附近也可以排除少量 bin尤其当谐波幅度很低时。6. 验证程序正确性的技巧用理想正弦波反推你写的代码有没有 bug写好的程序不能直接拿 ADC 实测数据验证因为实测数据你不知道“正确答案”。我一般会先合成理想信号用已知参数反推代码是否正确。下面这个是最近一次项目验证用的脚本% 构造理想 ADC 输出满量程幅度 1V输入正弦 0.5V 幅度 Fs 65e6; N 8192; f0 Fs * 128 / N; % 让 bin 序号为 128整数满足相干采样 t (0:N-1) / Fs; x 0.5 * sin(2*pi*f0*t); % 添加已知方差的白噪声使理论 SNR 可算 noise_rms 0.002; % RMS 噪声 2 mV x x noise_rms * randn(N,1); % 理论 SNR 20*log10(0.5/sqrt(2) / noise_rms) theo_snr 20*log10(0.5/sqrt(2) / noise_rms);理想情况下程序输出的 SNR 应该和 theo_snr 接近差别在 ±0.1 dB 以内因为有限样本估计噪声功率会有统计波动波动幅度约为 10*log10(1 sqrt(2/N))N8192 时约 0.05 dB 量级。如果差别超过 0.3 dB说明噪声功率统计或信号功率计算有遗漏。再把 THD 设为零理想正弦没有失真THD 应该在噪声底之下程序算出来应是极大的负值比如 -120 dBc 以下如果算出 -40 dBc说明谐波搜索找错了位置把某个噪声 bin 当成了谐波。验证 SFDR 更直接在频谱里人为注入一个已知功率的杂散比如在第 500 个 bin 注入一个 -70 dBc 的正弦。运行程序算出的 SFDR 应该接近 70 dBc。如果偏差超过 1 dB多半是最大杂散搜索时把信号旁瓣或谐波混进去了。我以前遇到过一个问题程序在 8192 点下验证完美换到 4096 点就 SNR 偏低。后来发现是数据长度被裁剪成奇数程序自动丢点破坏了相干性。所以现在我在采集端就固定 N 为 2 的幂程序里只接收偶数长度如果不满足直接报错而不是默默修数据。验证通过的代码才敢拿去跑实测。我的习惯是每换一个采样率或信号频率先跑一遍理想信号合格了再审实测数据。这样后续分析出的 SNR、SNDR、THD、ENOB、SFDR 才有可信度。希望这篇笔记能帮你少踩几个坑。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?