ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

16位ADDA回环实测:正弦幅值对不上,从信号链逐级排查是关键

16位ADDA回环实测:正弦幅值对不上,从信号链逐级排查是关键 做 16 位 ADDA 回环实测最常见的困惑不是“能不能通”而是“为什么对不上”。DAC 输出一个 1 kHz 正弦代码里查表生成的正弦幅度是 10000 码本以为 ADC 读回来算出峰值也是 10000 码左右结果只有 8500 码。第一反应是芯片坏了换一片还是这样再怀疑 SPI 读写时序有问题把示波器接上去看波形数据又好像没错最后干脆在采集结果后面乘一个 0.85 的系数现象“消失”了可换一台设备又不对。这不是某一个器件坏了而是整条信号链里至少有一个环节没有对齐。16 位精度的回环测试真正的难点不是误差本身而是定位误差。我更建议先别急着补系数先把 DA 侧、AD 侧、中间模拟通路拆开验证找到偏差发生在哪一级再决定是改硬件、改参数还是改软件。1. 回环不一致先别怪芯片这是信号链问题1.1 一次回环叠加了三段误差很多人把“DAC 输出、ADC 采集、比对数据”理解成一根直线代码进去代码出来中间不应该有任何差异。实际上一次回环至少经过三段独立环节每一段都有自己的误差。第一段是 DA 侧。DAC 芯片要把 16 位数字码转换成电压这个电压取决于它的参考电压、输出放大器增益、失调、稳定时间。同一个型号的 DAC不同批次、不同温度下实际满量程电压都会有微小差异。第二段是中间模拟通路。DAC 引脚到 ADC 引脚之间通常不只有一根导线可能还有运放缓冲、RC 滤波、防倒灌电阻、连接器、线缆、PCB 走线。这一段的增益、带宽、阻抗、接触电阻都会直接叠加到信号上。第三段是 AD 侧。ADC 输入前端有采样开关和采样电容采样保持的时间够不够输入阻抗会不会拉低信号参考电压是多少输出数据格式怎么解释都会影响最终读回来的码值。所以回环测试真正测的不是“DAC 正常”或“ADC 正常”而是这三段链路叠加之后的一致性。幅值对不上意味着至少有一段不是你预期的那样。1.2 16 位下 1 个 LSB 的物理尺寸决定了你的容错空间16 位系统里一个 LSB 的“物理尺寸”非常小。以 5 V 参考电压为例1 LSB 约等于 76.3 µV如果参考电压是 3.3 V1 LSB 约等于 50.4 µV。这意味着什么10 mV 的直流偏移在 16 位系统里可能造成 130 多个 LSB 的误差。一个 1% 精度的参考电压配合另一个 1% 精度的参考电压再加上运放增益的 1% 偏差整体幅值偏差就能到 3% 到 5%换算成码值就是几千个 LSB。所以“幅值不一样”在 16 位体系里其实是常态如果每个环节都没有经过实测确认那才是意外。我们真正要做的是把每一段的实际误差量化出来而不是默认芯片手册上的理想值。1.3 为什么“凭感觉乘个系数”是最危险的做法一批板子测试时发现幅值偏小就在软件里乘一个 0.85 修正系数现象立刻消失。这个操作看起来很快但你会面临几个问题换一批板子参考电压偏差漂移0.85 不再成立环境温度变化运放增益漂移0.85 也不再成立如果误差不是纯增益误差而是包含直流偏置单独乘系数会把偏移也放大或缩小。更麻烦的是一旦你习惯了补系数就会忽略真正的根因。比如采样时间不够导致的幅值下降它随频率变化正弦 1 kHz 时偏小500 Hz 时偏小程度不同这样一个固定系数完全无法覆盖。定位根因看起来多花几个小时实际上比后面反复换系数省时间。2. 四个最容易翻车的环节格式、参考、通路、时序2.1 数据格式和极性看起来对其实从源头就偏了先检查最简单、最容易被忽略的一层数据格式。16 位 DAC 和 ADC 的输出格式并不统一。有的芯片输出无符号二进制码0x0000 对应 0 V0xFFFF 对应满量程有的则是偏移二进制或者二进制补码0x8000 对应 0 V。如果 DAC 是无符号单极性输出正弦查表要围绕 0x8000 生成负半周才不会削底如果 DAC 是双极性输出正弦查表要围绕 0 生成套用单极性查表就会在负半周直接截断。ADC 那边也一样。有些 ADC 输出偏移二进制有些输出补码。回环比对时如果两边数据格式不一致最常见的结果不是幅值成比例缩小而是直流中点整体偏移。你可能看到正弦的峰峰值差不多但上下沿不对称或者最小码值低到了不可能出现的区域。还要注意字节序和左右对齐。SPI 读回来的 16 位数据如果高低字节交换或者左对齐右对齐没处理对读回来的码值会是完全混乱的。这类问题用恒定码测试最容易暴露给 DAC 写 0x8000ADC 读回来如果也是 0x8000说明格式基本对如果读回来是 0x0080 之类先查字节序和移位。2.2 参考电压成比例误差的最大来源如果幅值整体偏小而且静态码也成比例偏小第一个要查的就是参考电压。回环链路里存在两个参考点DAC 的 VREF 和 ADC 的 VREF。它们共同决定数字码和物理电压之间的换算关系。理想情况下两者应该相等或者至少要让 ADC 端的满量程电压和 DAC 端的满量程电压匹配。换算关系很直接DAC 输出电压等于 DAC 码除以 65536 再乘以 DAC 参考电压再乘以模拟通路增益。ADC 读回码等于输入电压除以 ADC 参考电压再乘以 65536。两条式子合并ADC 回读码和 DAC 输出码之间满足ADC 码 DAC 码 ×DAC 参考电压 / ADC 参考电压× 通路增益如果 DAC 参考是 2.5 VADC 参考是 3.0 V通路增益是 1那么回读码就是输出码的 0.833 倍。这就是“幅值少了 16.7%”的典型来源。排查时不要只看原理图上的标称值要用万用表实测 DAC 参考引脚和 ADC 参考引脚的对地电压。很多板卡为了省电参考电压经过一个开关、一个滤波电阻甚至一个二极管才到芯片负载变化时电压会偏。还要确认两个参考是否真的同源即使同源走线电阻和地平面压差也可能造成几十毫伏差异在 16 位系统里就是几百个 LSB。2.3 模拟通路一个 RC 就够让你的幅值“蒸发”15%如果参考电压实测没有问题接下来查模拟通路。最常见的是 DAC 和 ADC 之间加了 RC 低通滤波。滤波器设计时的截止频率可能只考虑了抗混叠没有考虑正弦频率落在幅频特性曲线上。比如 1 kHz 正弦R 取 1 kΩ、C 取 100 nF截止频率约 1.59 kHz1 kHz 处理论衰减约 84%也就是幅值直接掉 16%。这不是芯片问题是滤波器本身的幅频特性。然后是运放缓冲。有些板子 DAC 输出能力不够会加一级运放做缓冲如果运放接成了同相放大结构增益是 1 Rf/Rg。两个电阻用 1% 精度增益误差最高可以到 2% 左右。看起来不多但在 16 位回环里这已经是上千个 LSB 的误差。还有一个容易被忽略的点是 ADC 输入阻抗。很多 SAR 型 ADC 的输入不是高阻而是等效为一个采样开关加一个采样电容。如果前端输出阻抗太高采样电容在采样窗口内没有完全充满读回来的电压就偏低。源阻抗越高、采样时间越短、信号频率越高误差越明显。这种情况看起来像增益误差但它不是常数而是随频率变化。用低输出阻抗的运放做缓冲比单纯在软件里补系数可靠得多。2.4 采样时序和稳定时间幅值波动常常是这里的问题如果幅值不是稳定偏小而是忽大忽小或者前几个点明显不对就要看时序。DAC 写完 SPI 帧输出不是瞬间稳定的。不同型号的 16 位 DAC稳定到 1 LSB 可能需要几微秒到十几微秒。如果 DAC 更新后立刻触发 ADC 采样ADC 抓到的可能是一条还在爬升的曲线看起来就是幅值偏低且随机。ADC 采样保持也有最小采样时间要求。为了追求采样率把采样窗口压得太短内部采样电容没充满读回来的码会稳定偏低而且信号频率越高越明显。在某些 ADC 里这个问题会表现为幅值和信号频率强相关。连续正弦回环时还要注意 DAC 更新时刻和 ADC 采样时刻是否同步。如果两边靠软件延时错开采样点落在正弦不同相位用峰峰值估算幅值时这一轮采样可能没采到真正峰值下一轮又采到就会造成幅值跳动。更稳妥的做法是用定时器固定触发节奏让 ADC 采样间隔严格等间隔这样后续的 RMS 或 FFT 计算结果才稳定。3. 正弦幅值对不上先按现象分类再决定往哪查3.1 幅值成比例偏小静态码也跟着偏这是最常见的一种DAC 输出幅值 10000 码的正弦ADC 读回来按换算系数算出来是 8500 码而且 DAC 输出 0x4000、0x8000、0xC000 这些恒定码时ADC 读回码和理论值的比例也同样是 0.85。优先排查顺序DAC 参考电压、ADC 参考电压、中间通路增益、RC 滤波器衰减。先用万用表实测两个参考电压计算比例是否接近 0.85再看通路里有没有串电阻、有没有滤波器最后看 ADC 输入阻抗和采样时间是否不足。如果比例和理论计算完全吻合基本可以断定是某个环节的增益没有达到 1。3.2 幅值没问题但直流中点不对如果正弦的峰峰值和预期一致但整体往上或往下偏比如正弦峰值从 40000 变成了 43000谷值从 25536 变成了 28536峰峰值没变只是中心漂了。先查数据格式解释。ADC 输出偏移二进制你按补码解释读回来的整数会凭空多一个直流偏置。再查信号链路里有没有电平搬移电路比如双极性信号转单极性 ADC 输入的加法电路搬移基准电压不对直流中点就偏。最后查 ADC 本身的失调误差有些 ADC 的失调可以到几百个 LSB需要用校准寄存器或软件归零。3.3 正负半周不对称甚至单边削顶这种情况说明信号已经碰到某个环节的线性范围边界。DAC 如果是单极性输出0x0000 对应 0 V负半周在电路上根本不存在查表数据一旦低于 0输出的就全是 0波形底部被削平。反过来如果 ADC 输入范围是 0 到 VREF而 DAC 输出的是双极性 ±VREF负半周直接被 ADC 前端限幅。检查时直接打印 DAC 的码值下限和 ADC 读回码值下限。如果 DAC 码值一直大于 0但 ADC 读数在低端饱和说明 ADC 输入范围不够。如果 DAC 码值本身出现负数说明查表生成或者 DAC 数据格式转换有 bug。3.4 幅值波动、峰值忽大忽小先怀疑噪声和计算方式最后一种比较隐蔽每次采集算出来的幅值都不一样甚至同一个文件里用不同段数据算出来的峰峰值差别很大。优先怀疑两个方向。一是噪声参考电压纹波、地平面噪声、电源耦合在 16 位精度下都会显示出来。二是计算方式用“最大值减最小值”算峰峰值对偶发毛刺特别敏感一个尖峰就能把峰峰值抬高几十个 LSB。正弦波如果带一点谐波或者噪声峰峰值也不能准确代表基波幅值。所以动态回环里我很少直接看峰峰值而是先去掉直流分量再算 RMS纯正弦下峰值等于 RMS 乘以根号 2或者直接做 FFT取基波频点的幅度。这样能把目标信号和噪声、谐波分开幅值对比才有意义。4. 推荐的四步实测流程分侧直流、静态回环、动态回环、线性修正4.1 第一步DAC 输出定码先确认 DA 自己没问题在做任何回环之前先把链路拆开。给 DAC 写入几组固定码比如 0x0000、0x4000、0x8000、0xC000、0xFFFF用万用表在 DAC 输出引脚直接量电压。理论值很容易算码值除以 65536乘以实测的 DAC 参考电压。如果实测电压和理论值差得很远问题在 DAC 配置、参考电压或 DAC 后端负载如果电压正确DAC 这一侧是可信的。这一步不会太久但能把后续排查范围缩小一半。// 伪代码DAC 输出恒定码这一步只看 DA 输出电压 uint16_t codes[] {0x0000, 0x4000, 0x8000, 0xC000, 0xFFFF}; for (int i 0; i 5; i) { dac_write(codes[i]); delay_ms(50); // 等 DAC 输出稳定 // 此时用万用表测量 DAC 输出引脚电压 }4.2 第二步ADC 输入定压再确认 AD 自己没问题然后单独验证 ADC。用一个已知直流电压接到 ADC 输入引脚或者把之前已经确认过的 DAC 输出作为信号源接进去读取 ADC 码和理论码值比较。理论码值等于输入电压除以实测的 ADC 参考电压再乘以 65536。如果 ADC 这侧单独验证也通过那 DAC 和 ADC 各自没问题回环对不上就一定是中间通路、时序或者数据计算方式的问题。这一步非常重要因为它直接回答了一个关键问题到底该修哪一边。4.3 第三步静态扫码画一条“DAC 码 → ADC 码”传递曲线把 DA 和 AD 接回真实回环路径做静态扫描。DAC 从 0x0000 开始按固定步进输出每次等稳定后读一次 ADC记录一组“输出码、回读码”。扫完之后做线性拟合得到两个关键参数斜率 k代表 DAC 参考电压、ADC 参考电压、模拟通路增益的综合影响。截距 b代表系统里累积的直流偏移。如果拟合残差很小说明系统接近线性后面用软件修正就很简单。如果残差很大比如某些码段偏差特别明显说明不是简单的增益偏移问题可能要查电源纹波、参考电压稳定性或者器件本身的 INL。# 伪代码用线性拟合求增益和偏移 import numpy as np # out_codes: DAC 输出码 # in_codes: ADC 回读码 k, b np.polyfit(out_codes, in_codes, 1) print(f增益系数 k {k:.6f}, 偏移 b {b:.2f} LSB)4.4 第四步正弦动态回环用 RMS/FFT 算幅值而不是只看峰峰值静态链路确认之后再上正弦信号。正弦查表用中点做中心幅度不要拉满建议 30% 到 40% 满量程避免碰到边缘非线性区。采集一段等间隔采样数据去掉直流均值后算 RMS正弦峰值约等于 RMS 乘以根号 2。如果系统里有噪声和谐波更推荐做 FFT取基波频点的幅值计算公式是 2 倍的频谱幅度除以采样点数。# 伪代码采集一段回环数据用 RMS 和 FFT 分别计算幅值 import numpy as np # data: ADC 采集到的原始码值数组 dc np.mean(data) ac data - dc rms np.sqrt(np.mean(ac ** 2)) peak_rms rms * np.sqrt(2) # 纯正弦下的峰值 spectrum np.fft.rfft(ac) peak_fft 2 * np.abs(spectrum[fund_bin]) / len(data) # 基波幅值这里要说明一下RMS 和 FFT 计算的是交流分量的幅值和 DAC 查表里的正弦峰值码值做对比时两边要用同一个定义。DAC 侧输出峰值码如果是 10000那么回读码的期望峰值也应该写成同样含义的码值而不是直接拿电压数值和码值比。5. 什么时候能用软件修正什么时候必须改硬件5.1 两点校准增益误差和偏移误差怎么拟合如果静态回环扫出来的传递曲线接近直线且残差在可接受范围内软件修正就是有效的。最简单的做法是两点校准。选取 DAC 输出码的两个点比如 0x2000 和 0xE000分别读回 ADC 码值算出斜率 k 和截距 b。之后软件里做反向换算把目标 ADC 码转换成 DAC 应该输出的码值再写入 DAC。# 伪代码软件校准时把目标 ADC 码转成 DAC 码 dac_code int((target_adc_code - b) / k) dac_code max(0, min(65535, dac_code)) dac_write(dac_code)但要注意这个修正只在系统保持线性的前提下成立。校准时的温度、参考电压、负载情况如果和实际使用时差别很大修正系数也要跟着变。批量生产时最好每块板都单独校准并将系数写回非易失存储而不是所有板卡共用一套固定系数。5.2 软修不了的三类情况软件修正看起来很万能但有三类情况不建议硬修。第一类是削顶和饱和。信号已经超出 DAC 或 ADC 的线性范围波形被切掉了丢失的信息无法通过乘法或加法恢复。这种情况下要调整信号幅度或电平搬移电路。第二类是强非线性。如果静态扫出来的传递曲线弯弯曲曲残差有几十个甚至上百个 LSB一个线性修正公式根本不够。需要先检查参考电压是否稳定、电源纹波是否过大、PCB 地回路是否合理而不是增加一个二次项拟合去掩盖真正的问题。第三类是频率相关误差。ADC 采样时间不够、源阻抗太高、滤波器带宽不足都会造成幅值随频率变化。软件里一个固定增益系数只能让某一个频率点“看起来对了”换一个频率又偏。这类问题必须从模拟前端或采样配置下手。5.3 把回环测试固化成可重复的自动化流程回环测试不应该只做一次。建议把它写成可以重复运行的脚本或者测试用例每次硬件改版、换料、量产抽检时都跑一遍。完整流程应包括DAC 恒定码测试、ADC 恒定码测试、静态扫点并拟合、正弦采集并计算 RMS/FFT 幅值、输出校准系数。把每次测试结果存成文件方便对比不同板卡、不同温度、不同批次之间的差异。这个习惯看起来多花一点时间但在长期维护阶段能省下大量排查成本。5.4 16 位回环长期稳定的几点工程建议最后给几条工程层面的建议体感会比调试代码更影响结果参考电压要用低噪声 LDO 或者专用基准源并做好去耦开关电源直接给 VREF 供电在 16 位系统里很容易出问题。模拟信号走线要远离数字信号和 SPI 时钟线地平面尽量完整不要在模拟路径上制造大电流回路。DAC 和 ADC 之间如果必须加驱动电路用低输出阻抗的运放保证 ADC 采样电容能快速充电。SPI 时序要留足裕量SCK 频率不要拉满芯片上限CS 建立时间和保持时间按数据手册要求设置。正弦回环的动态测试中DAC 更新和 ADC 采样尽量由硬件定时器触发避免软件延时导致相位抖动。回到最初的问题16 位 ADDA 回环正弦幅值不一样绝大多数情况下都不是芯片坏了而是信号链路里某个环节没有对齐。处理顺序应该是先分侧验证直流再静态扫点再做动态正弦计算最后根据拟合结果决定要不要软件修正。如果能养成这个习惯你会发现自己不再需要猜“乘多少才对”而是直接知道该去修哪里。
返回列表