# ADC 前端注入验证流程(台架) > **这篇是什么**:把「ADC 采到的数到底对不对」从"没人验过"推进到"有实测斜率与零点"的固定动作。 > 它是 `docs/任务规划/数据可信.md` 卡 0 的**执行侧**——那边写判据,这边写怎么接表笔、读哪一行日志、 > 填哪张表、结果往哪回写。补的是 `docs/硬件平台/ADC通道映射说明.md` §8「逐通道验证方法」 > 长期挂账的"尚未执行"(挂账自 2026-10-09)。 > > **只验直流**:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源,且 V0.1 有五路 > 单极性削顶(`UB/UC/IB/IC/IN`),交流精度要等标准源到位后的两点标定(`docs/任务规划/数据可信.md` 卡 12)。 > > **不需要**示波器、信号源、标准源。**只需要**一块万用表 + 一个电位器 + 串口日志。 --- ## 1. 为什么非做不可 现有台架判据只证明过"通路是活的":9 通道全部转换成功、零超时、互异非饱和、跨次开机读数不同。 这些**一条都不证明读数正确**——连符号位对不对都没验过。而下游已经全部按"工程量"消费了: 保护判据、104 遥测、UI 交流量页读的都是 `adc_cal_apply()` 的输出。系数错一倍,三处一起错,且 没有任何一处会报错。 所以这一步的性质是**给整条链路的量纲盖章**,不是"补充测试"。 ## 2. 前置事实:这个前端不是分压器 2026-10-27 按 `docs/硬件平台/V0.1.tel` 逐通道追线,以 UA 为例(图由 `tools/arch_diagram/gen_adc_frontend_svg.py` 生成,改图请改脚本重跑,勿手改 SVG): ![UA 通道前端:端子 → R31 → ADC7 → TPAFE AIN_7P;C44 / R32 在差分负端,不在信号通路上](../images/ADC前端电路.svg) `ADC7` 这个节点上**只有** R31、C44、U3.61 三样东西,**没有对地电阻**。所谓"1k 到地"是 R32, 它接在 TPAFE 的**负输入脚 AIN_7GND**(芯片手册 pin62)上,是把差分负端经 1k 拴到 AGND, 属于差分滤波,不是信号分压。STM32 侧更直接(图 B):`AIN2 —[R52 1k]— ADC17 —[C111]— AGND`, 同样没有分流电阻,连 R32 那个接地电阻都没有。 **由此得到两条可直接用的结论**: 1. **不存在 2:1 分压**。旧口径"板级系数 305.18 / 1611.3 µV/码"(按 2:1 折算到 `AINn` 侧的条件值) 在本板上不成立;`docs/任务规划/数据可信.md` §2.1 已于 2026-10-27 改为引脚侧系数(152.59 / 805.66)。 所以卡 0 只需**确认转换器 LSB 与逐通道映射**,不必再判别两种读法。 2. **端子侧斜率 = 引脚侧斜率**。所以在**端子侧**注入既安全(有 1k 串阻护着芯片)又能直接验 LSB, 不必去碰 LQFP 引脚。 期望斜率(由转换器满量程事实推出,与前端无关): | 转换器 | 满量程 | LSB | **期望斜率** | | ---------- | ----------------------- | ---------------- | -------------- | | TPAFE5160 | ±5 V(10 V 跨度 / 65536 码) | 152.587890625 µV | **6553.6 码/V** | | STM32 ADC1 | 0~3.3 V(3.3 V / 4096 码) | 805.6640625 µV | **1241.2 码/V** | ## 3. 注入点清单 串联电阻的两只焊盘就是两个注入层级:**1 脚 = 端子侧(靠 U5)**,**2 脚 = 引脚侧(靠转换器)**。 | 语义 | 串阻 | 端子侧节点 | 引脚侧节点 | 转换器脚 | 期望斜率 | | -- | --- | --------------- | ------- | ----------- | ------------- | | UA | R31 | `AIN1`(U5.A3) | `ADC7` | U3.61 | 6553.6 | | UN | R28 | `AIN4`(U5.A4) | `ADC6` | U3.59 | 6553.6 | | IA | R19 | `AIN8`(U5.B5) | `ADC3` | U3.53 | 6553.6 | | UB | R52 | `AIN2`(U5.B7) | `ADC17` | U17.44(PC4) | 1241.2 | | UC | R20 | `AIN3`(U5.C14) | `ADC12` | U17.37(PA3) | 1241.2 | | IB | R49 | `AIN9`(U5.A8) | `ADC15` | U17.42(PA6) | 1241.2 | | IC | R46 | `AIN10`(U5.C9) | `ADC10` | U17.35(PA1) | 1241.2 | | IN | R48 | `AIN11`(U5.C10) | `ADC11` | U17.36(PA2) | 1241.2 | | 温度 | R47 | `V_ZL2`(U5.C11) | `ADC14` | U17.41(PA5) | 不验(非线性,不参与标定) | > 引脚侧没有串阻保护,注入前**必须外串 10 k 限流**。除非端子侧结果对不上、需要分离 > "转换器的错"和"前端的错",否则不要用引脚侧。 ## 4. 读数出口(固件只给这四行,没有命令控制台) | 日志行 | 频率 | 内容 | 用途 | | ----------------------------------------------------------- | ------ | ------------------------ | ------------------- | | `adc: UA=.. UB=.. UC=.. UN=.. IA=.. IB=.. IC=.. IN=.. T=..` | 每 10 s | **9 路原始码值** | 本次验证的主读数 | | `cal: ua_mv=.. un_mv=.. ia_mv=.. vl=.. cl=..` | 每 10 s | UA/UN/IA 折算后毫伏 + 标定/削顶位图 | 旁证:码值 → 电压是否自洽 | | `first: UA=.. … T=..` | 每次开机一次 | 9 路原始码值 | 与 `adc:` 行互校(同序同格式) | | `frames=.. idle=.. adc1_err=.. tgap=..` | 每 10 s | 采集健康计数 | 步骤 5 的节奏判据 | `adc:` 行是 2026-10-27 新增的(`App/task/adc_task.c` 心跳块),此前只有 `cal:` 的三路, 验 8 个通道要复位二十余次。现在**全程不必复位**。 **「码」是什么**:ADC 输出的**原始整数**,中文常写「码值」/「AD 码」,英文对应 raw code / counts。 它表示"多少个最小刻度(LSB)",**本身不是物理量**——电压 = 码 × LSB,而两片转换器的 LSB 不同: | 转换器 | 位数与极性 | 码的范围 | 1 码 = | 换算示例 | |---|---|---|---|---| | TPAFE5160 | 16 位双极性 | −32768 ~ +32767(共 65536 码 = 10 V 跨度) | 152.59 µV | 11430 码 × 152.59 µV ≈ **1.744 V** | | STM32 ADC1 | 12 位单极性 | 0 ~ 4095(共 4096 码 = 3.3 V 跨度) | 805.66 µV | 1000 码 × 805.66 µV ≈ **0.806 V** | 同一个整数落在两把刻度尺上代表不同电压(图由 `tools/arch_diagram/gen_adc_code_scale_svg.py` 生成,改图请改脚本重跑,勿手改 SVG): ![两把刻度尺:TPAFE5160 16 位双极性 −32768~+32767、1 码 152.59 µV、11430 码≈1.744 V;STM32 ADC1 12 位单极性 0~4095、1 码 805.66 µV、1000 码≈0.806 V](../images/ADC码值刻度.svg) **两把尺子不能混用**:同样是"1000",在 TPAFE 上是 0.153 V,在 STM32 上是 0.806 V,差 5.3 倍。 所以 §5 各步的记录表里每一格都必须写明是哪一路(UA/UB/… 属 TPAFE,T 属 STM32), 抄错一行全盘结论作废。 本文一律用"码"而不是"伏",有两个理由:① 固件 `adc:` 行打印的就是码,抄数不用心算; ② **标定还没做,把码换成伏正是本次要验证的事**——先换算再用,等于默认了尚未验证的系数。 判据里的"码值绝对值 ≤ 10"= 短接后读数离 0 不超过 10 个刻度,即 TPAFE 侧 ≈1.5 mV、 STM32 侧 ≈4 mV。 ⚠ `adc:` 行某路取数失败时该槽打 0,所以"9 路全 0"要读作"没数据",判据是同一份心跳里 `frames` 是否还在涨。 ## 5. 步骤 ### 5.1 步骤 0:断电核阻(5 分钟) 断电,万用表电阻档量两处,**期望值不一样**: | 量哪里 | 期望 | 验的是什么 | |---|---|---| | **串阻两端**(1 脚 ↔ 2 脚,即端子侧焊盘 ↔ 引脚侧焊盘) | **≈ 1 kΩ** | 串阻焊好、没虚焊 | | **注入点 ↔ AGND**(TPAFE 侧,UA/UN/IA) | **≈ 1 MΩ 量级** | 无意外短路;**不是 1 kΩ** | | **注入点 ↔ AGND**(STM32 侧,UB/UC/IB/IC/IN) | 高阻,不定量 | 无设计直流通路,只作短路排查 | ### 5.2 步骤 1:零点(这一步是整套测试的分水岭) **做什么**(8 路逐个重复,每路约 1 分钟): 1. 断电,把该路**注入点短接到 AGND**(短接线之前先用 0 Ω 档确认该点与 AGND 直通); 2. 上电,等 `adc:` 行出现(每 10 s 一行,9 路码值都在里面); 3. 把该路码值抄进**下面的零点记录表**; 4. 断电拆短接线,换下一路。 **记录**(现场填;判据只看"短接后"那一列,"空载"列是留证用): > ⚠ **本表行序 = `adc:` 日志的列序**(UA UB UC UN IA IB IC IN),照着日志**从左往右**抄, > 不要按"TPAFE 三路 / STM32 五路"重新分组。2026-10-27 现场实测就栽在这里:按语义分组抄, > 结果 UN/IA 填成了 STM32 的 ~1000、UB/UC 填成了 TPAFE 的 ~11450——而 UN/IA 属 TPAFE、 > UB/UC 属 STM32,这两个量级在物理上不可能。**"转换器"列就是给这一眼准备的**。 | 通道 | 转换器 | 空载码值(浮空) | 短接 AGND 后码值 | 判据 | | --- | --- | --- | --- | --- | | UA | TPAFE | | | ≤ 10 | | UB | STM32 | | | ≤ 5 | | UC | STM32 | | | ≤ 5 | | UN | TPAFE | | | ≤ 10 | | IA | TPAFE | | | ≤ 10 | | IB | STM32 | | | ≤ 5 | | IC | STM32 | | | ≤ 5 | | IN | STM32 | | | ≤ 5 | **怎么抄短接后的数**:短接一路时日志仍然打 9 路,只抄**该路**那一列,不要把整行贴进来。 顺手记下"哪一路塌到 0"——**若塌的不是你以为的那一路,那不是零点问题,是注入点标签与 固件通道名对不上,转 §5.4 逐通道映射去查**。另外:**短接后读到 0 是短接到位,不是取数失败** (取数失败只在**没短接**时表现为恒 0,那种情况同一份心跳里 `frames` 仍在涨)。 空载列的量级参考:TPAFE 三路(UA/UN/IA)≈ 11430 码,STM32 五路 ≈ 1000 码。两列都记下来, 是因为"空载高两个数量级、短接后塌回 0"本身就是一个结论;只记短接后的数,看不出这件事。 **2026-10-27 首次实测(空载,已按日志列序归位)**: UA 11429 · UB 1044 · UC 954 · UN 11453 · IA 11451 · IB 1040 · IC 1062 · IN 980。 与 18:04 烧录后那次开机日志(11428 / 1087 / 953 / 11452 / 11450 / 999 / 1016 / 987)一致, 两次都落在 TPAFE ≈11430、STM32 ≈1000 的量级。 短接列本轮仅 TPAFE 三路有效:UA −14、UN −15、IA −13(均 ≈2 mV);STM32 五路当时记的是 整行日志、无法归属到具体通道,待重测。 **为什么这一步最关键**:空载(输入浮空)读数比判据高两个数量级,最可能的解释是输入悬空后 漏电流在滤波电容上建立的平衡点——短接 AGND 后应塌回 0。但如果**短接后仍读 11430**,那就是 真实偏置,且超过零点补偿上限 `ADC_CAL_B_MAX`(8192 码)——`adc_cal_set()` 会直接拒掉、 回退 ROM 系数、永远置不了 `VALID`,保护也就永远解不了锁。**那种情况必须回前端查** (R32 那侧接地是否断、TPAFE 是否失调),不能靠软件补偿。 ### 5.3 步骤 2:三点线性(用 UA 做,免复位) 3.3 V 轨经 10 k 电位器分压作源,逐点注入。**每点同时记两个数**:万用表读注入点实际电压、 `adc:` 行读对应码值。 **记录**(UA 一路,三点;"目标"列是调电位器的靶子,"实测"列填万用表读数): | 目标注入 | 实测电压(万用表) | 码值 | 反算 µV/码 | TPAFE 期望码 | STM32 期望码 | | -------- | --------- | -- | ------- | --------- | --------- | | ≈ 0.3 V | | | | 1966 | 372 | | ≈ 1.0 V | | | | 6554 | 1241 | | ≈ 2.0 V | | | | 13107 | 2482 | 拟合 R² = \______ 斜率 = \______ 码/V 偏差 = \______ % 期望码两列并列,是因为同样的三个注入点也可能拿去复验 STM32 侧某一路(UA 对不上时换路交叉验证); 两列数值差 5.3 倍,一眼能确认手上这支表笔当前接的是哪一片转换器。 判据:三点线性拟合 **R² ≥ 0.999**,斜率与期望值偏差 **≤ 2 %**。 偏差 > 2 % 时**先查前端**(焊点、串阻实际值、电位器负载效应),不要用系数去凑—— 把硬件的错固化成"标定值"是最坏的结果。 ### 5.4 步骤 3:逐通道映射(8 路各一次) 对每一路单独注入 1.0 V,其余路保持短接 AGND,读 `adc:` 行: - **只有对应的那一路上升**,幅值落在期望码附近; - 其余七路仍在零点附近。 任何"注入 A 路、B 路动"都是映射错。这一条比斜率更重要——映射错时斜率可能完全正常。 **记录**(8 路各一次): | 注入路 | 注入 1.0 V 后实际变动的路 | 码值 | 是否符合预期 | | --- | --- | --- | --- | | UA | | | | | UN | | | | | IA | | | | | UB | | | | | UC | | | | | IB | | | | | IC | | | | | IN | | | | `ADC通道映射说明.md` §3 的映射表如有不符,以实测为准并当场记在本表"是否符合预期"列。 ### 5.5 步骤 4:极性(只 TPAFE 三路) TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,负半周测不了。给 UA/UN/IA 各加一个 **−1.0 V** 点。 **记录**(三路各两个点): | 通道 | +1.0 V 码值 | −1.0 V 码值 | 对称性偏差 | | -- | --------- | --------- | ----- | | UA | | | | | UN | | | | | IA | | | | 判据:−1.0 V 点码值为**负**且落在 **−6554** 附近,幅值与 +1.0 V 点对称(差值 ≤ 2 %) → 符号位与补码解释正确。这一步专门补"连极性都没证过"这个缺口。 ### 5.6 步骤 5:节奏(注入期间顺带看) 注入期间 `frames=` 应仍**严格 1000 Hz 递增**(10 s 间隔 +10000 左右),`idle=0`, `adc1_err=0`。这一条替代了原方案里"用示波器看 U3.14 BUSY 有脉冲"的判据——不需要示波器。 ### 5.7 步骤 6:回写 1. 把实测斜率、零点、映射结果写进 `docs/硬件平台/ADC通道映射说明.md` §8,把"尚未执行"改成 实测值 + 日期; 2. 若实测确认无分压,同步在 `docs/硬件平台/ADC通道映射说明.md` §7.1 的链路分段表把第 ③ 段 (`AINn` ↔ 转换器引脚)从"待台架实测"改为实测结论; 3. `docs/任务规划/数据可信.md` 卡 0 销项(按该文件夹"完成即删"的约定,删行不留记录)。 ## 6. 判据汇总 | 项 | 判据 | 不通过意味着 | | -- | ---------------------------- | --------------------------- | | 零点 | TPAFE 码值绝对值 ≤ 10;STM32 码值绝对值 ≤ 5 | 有真实偏置,需查前端;可能超出补偿上限 | | 线性 | R² ≥ 0.999 | 前端非线性或注入源带载失真 | | 斜率 | 偏差 ≤ 2 % | 前端有未识别元件,或转换器档位/参考错 | | 映射 | 注入哪路只动哪路 | 语义表与物理通道不符(`k_adc_map[]` 错) | | 极性 | −1.0 V → −6554 码 | 补码符号处理错 | | 节奏 | 注入期间仍 1000 Hz | 注入改变了输入共模,触发转换异常 | ## 7. 安全红线 1. **STM32 侧严禁超过 3.3 V**(VDDA + 0.3 V 即击穿),电位器上限就接 3.3 V 轨,不要接 5 V。 2. **TPAFE 侧按判据只到 ±2 V**,虽芯片容 ±5 V,但判据不需要更大。 3. **端子侧不许直接上额定电压**(220 V / 100 V 二次值)。本次是直流低压注入, 与"加压试保护"是两件事,后者要等变比确认(`docs/任务规划/数据可信.md` 卡 0b)之后单独排。 4. **引脚侧注入必须外串 10 k**,且先接线后上电、先断电后拆线。 5. 注入源与板子**共地**;电位器一端接 3.3 V、一端接 AGND、中间抽头串 10 k 到注入点。