数据可信.md §2.6 原写「ADC 从未采过已知电压」,那是 2026-10-23 挂账 时的现状,与 2026-10-27 的台架实测矛盾——按现状重写:实测 × 判据表 + ④ 段(端子 → AINn 子板变比)缺口 + M4 承诺边界(只到 ADC 引脚电压、 eng = 0);§2.6 节号与「承诺边界」口径保留,代码头注释的引用不断。 同族陈旧现在时一并更正:继电保护规划「引脚级注入验证仍为待做项」、 ADC通道映射 §7.1「不填任何实测数值」、ADC输入层单测说明「板端无信 号源、无法验证读到的是哪只脚」、adc_input.c 与 test/host/adc_input 两份注释「注入验证做不了」→ 统一改成「台架已一次性验过(§8.1), 主机单测与开机自检仍必要」。首帧悬案等历史叙述删除,只留结论。 顺带:ADC 输入层单测计数 101 → 103(runner 报 103/103 与 CHECK 调用 点 103 处双源互证),test/host/README.md 同数同步。 验证:@build 0 错 0 警(Code=236456 RO=28124 RW=1876 ZI=137084); test/host/adc_input 103/103 rc=0;check_doc_links --all 0 处失效; 该批文件里的变更记录节按同日裁定一并清理。
18 KiB
ADC 前端注入验证流程(台架)
这篇是什么:已知电压注入验证的执行侧——判据与实测记录在
docs/硬件平台/ADC通道映射说明.md§8.1, 这边写怎么接表笔、读哪一行日志、填哪张表、结果往哪回写。只验直流:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源,且 V0.1 有五路 单极性削顶(
UB/UC/IB/IC/IN),交流精度要等标准源到位后的两点标定(docs/任务规划/数据可信.md§5)。不需要示波器、信号源、标准源。只需要一块万用表 + 一个电位器 + 串口日志。
1. 为什么非做不可
下游已经全部按"工程量"消费:保护判据、104 遥测、UI 交流量页读的都是 adc_cal_apply() 的输出。系数错
一倍,三处一起错,且没有任何一处会报错。"通路活"(9 通道转换成功、零超时、互异非饱和、跨次开机
读数不同)不证明读数对。所以这一步的性质是给整条链路的量纲盖章,不是"补充测试"。
2. 前置事实:这个前端不是分压器
2026-10-27 按 docs/硬件平台/V0.1.tel 逐通道追线,以 UA 为例(图由
tools/arch_diagram/gen_adc_frontend_svg.py 生成,改图请改脚本重跑,勿手改 SVG):
ADC7 这个节点上只有 R31、C44、U3.61 三样东西,没有对地电阻。所谓"1k 到地"是 R32,
它接在 TPAFE 的负输入脚 AIN_7GND(芯片手册 pin62)上,是把差分负端经 1k 拴到 AGND,
属于差分滤波,不是信号分压。STM32 侧更直接(图 B):AIN2 —[R52 1k]— ADC17 —[C111]— AGND,
同样没有分流电阻,连 R32 那个接地电阻都没有。
由此得到两条可直接用的结论:
- 不存在 2:1 分压。旧口径"板级系数 305.18 / 1611.3 µV/码"(按 2:1 折算到
AINn侧的条件值) 在本板上不成立;docs/任务规划/数据可信.md§2.1 已于 2026-10-27 改为引脚侧系数(152.59 / 805.66)。 所以已知电压注入验证只需确认转换器 LSB 与逐通道映射,不必再判别两种读法。 - 端子侧斜率 = 引脚侧斜率。所以在端子侧注入既安全(有 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 | 采集健康计数 | 步骤 4 的节奏判据 |
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):
两把尺子不能混用:同样是"1000",在 TPAFE 上是 0.153 V,在 STM32 上是 0.806 V,差 5.3 倍。 所以 §5 各步的记录表里每一格都必须写明是哪一路(UA/UB/… 属 TPAFE,T 属 STM32), 抄错一行全盘结论作废。
本文一律用"码"而不是"伏",有两个理由:① 固件 adc: 行打印的就是码,抄数不用心算;
② 标定还没做,把码换成伏正是本次要验证的事——先换算再用,等于默认了尚未验证的系数。
判据按转换器分两档:TPAFE 侧 ≤ 30 码、STM32 侧 ≤ 5 码——即短接后读数离 0 不超过
30 / 5 个刻度,折算 ≈4.6 mV / ≈4.0 mV。两档数值差 6 倍是因为两种刻度差 5.3 倍
(TPAFE 152.59 µV/码、STM32 805.66 µV/码),统一到物理量后都在 4~5 mV 量级。
⚠ TPAFE 档于 2026-10-27 由 ≤10 放宽到 ≤30:首次实测三路残差 UA −14 / UN −15 / IA −13 (≈2 mV),按 16 位 /10 V 跨度算只有 0.02% FS。原来的 ≤10(≈1.5 mV)定判据时没有实测依据, 比实测噪声还紧,必然误判失败。这不是"把判据改成能过"——若残差继续增大(>30 码 / ≈4.6 mV), 说明前端确有真实失调(R32 侧接地断、TPAFE 失调),那时必须回前端查,不得再放宽。
⚠ 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 分钟):
- 断电,把该路注入点短接到 AGND(短接线之前先用 0 Ω 档确认该点与 AGND 直通);
- 上电,等
adc:行出现(每 10 s 一行,9 路码值都在里面); - 把该路码值抄进下面的零点记录表;
- 断电拆短接线,换下一路。
记录(现场填;判据只看"短接后"那一列,"空载"列是留证用):
⚠ 本表行序 =
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 | AIN1(U5.A3) |
11428~11429 | 1~3 | ≤ 30 |
| UB | STM32 | AIN2(U5.B7) |
993~1018 | 0~1 | ≤ 5 |
| UC | STM32 | AIN3(U5.C14) |
975~1033 | 0 | ≤ 5 |
| UN | TPAFE | AIN4(U5.A4) |
11452~11455 | 2~4 | ≤ 30 |
| IA | TPAFE | AIN8(U5.B5) |
11449~11451 | 2~3 | ≤ 30 |
| IB | STM32 | AIN9(U5.A8) |
937~960 | 2~5 | ≤ 5 |
| IC | STM32 | AIN10(U5.C9) |
991~1092 | 0 | ≤ 5 |
| IN | STM32 | AIN11(U5.C10) |
979~1065 | 1~2 | ≤ 5 |
为什么这一步最关键:空载(输入浮空)读数比判据高两个数量级,最可能的解释是输入悬空后
漏电流在滤波电容上建立的平衡点——短接 AGND 后应塌回 0。但如果短接后仍读 11430,那就是
真实偏置,且超过零点补偿上限 ADC_CAL_B_MAX(8192 码)——adc_cal_set() 会直接拒掉、
回退 ROM 系数、永远置不了 VALID,保护也就永远解不了锁。那种情况必须回前端查
(R32 那侧接地是否断、TPAFE 是否失调),不能靠软件补偿。
2026-10-27 实测结论:8 路全部 PASS。 短接后落在 0~5 码(TPAFE ≤4.6 mV、STM32 ≤4.0 mV),
全部远小于零点补偿上限 ADC_CAL_B_MAX(8192 码),可以正常标定、不会触发回退。
空载 → 短接的塌陷幅度:TPAFE 约 11430 → 04(三个数量级),STM32 约 1000 → 05(两个数量级),
两者都证明短接真实到位、输入前端没有意外直流通路。
⚠ IB 最贴边:25 码,上限 5 码正好触到。折算 1.64.0 mV,物理上没问题,但它是八路里
余量最小的一路;若日后 IB 零点继续变大,第一个该查的是 R49 那侧(AIN9 / U5.A8)。
5.3 步骤 2:三点线性(用 UA 做,免复位)
3.3 V 轨经 10 k 电位器分压作源,逐点注入。每点同时记两个数:万用表读注入点实际电压、
adc: 行读对应码值。
记录(UA 一路,三点;"目标"列是调电位器的靶子,"实测"列填万用表读数):
| 目标注入 | 实测电压(万用表) | 码值 | 反算 µV/码 | TPAFE 期望码 | STM32 期望码 |
|---|---|---|---|---|---|
| ≈ 0.3 V | 0.300 | 1954 | 153.53 | 1966 | 372 |
| ≈ 1.0 V | 1.001 | 6547 | 152.89 | 6554 | 1241 |
| ≈ 2.0 V | 2.004 | 13106 | 152.91 | 13107 | 2482 |
拟合 R² = 0.9999997 斜率 = 6544.2 码/V 偏差 = −0.14 % 截距 = −7.2 码(≈ −1.1 mV)
反算 LSB = 152.81 µV/码,与 TPAFE 期望 152.59 差 0.14 %——与斜率偏差同源,是同一个数。
期望码两列并列,是因为同样的三个注入点也可能拿去复验 STM32 侧某一路(UA 对不上时换路交叉验证); 两列数值差 5.3 倍,一眼能确认手上这支表笔当前接的是哪一片转换器。
判据:三点线性拟合 R² ≥ 0.999,斜率与期望值偏差 ≤ 2 %。
偏差 > 2 % 时先查前端(焊点、串阻实际值、电位器负载效应),不要用系数去凑—— 把硬件的错固化成"标定值"是最坏的结果。
2026-10-27 实测结论:PASS。 R² = 0.9999997(判据 ≥0.999)、斜率偏差 −0.14 %(判据 ≤2 %)。 三条残差 −2.0 / +3.5 / −1.4 码,落在读数噪声内,无系统性弯曲——即前端在这三个点上确实是 线性的,不存在未识别的分压元件。这是"③ 段变比 = 1:1"在台架上的第一次直接证据。
5.4 步骤 3:极性(只 TPAFE 三路)
TPAFE 是双极性、二进制补码,可以注负压;STM32 是单极性,负半周测不了。给 UA/UN/IA 各加一个 −1.0 V 点。
记录(三路各两个点):
| 通道 | +1.0 V 码值 | −1.0 V 码值 | 对称性偏差 |
|---|---|---|---|
| UA | 6544 | −6566 | 0.34 % |
| UN | 6549 | −6568 | 0.29 % |
| IA | 6548 | −6566 | 0.27 % |
判据:−1.0 V 点码值为负且落在 −6554 附近,幅值与 +1.0 V 点对称(差值 ≤ 2 %) → 符号位与补码解释正确。这一步专门补"连极性都没证过"这个缺口。
2026-10-27 实测结论:PASS。 三路 −1.0 V 点全部为负,落在 −6566~−6568(相对 −6554 偏 −0.18 %~−0.21 %);对称性偏差 0.27 %~0.34 %,远小于 2 % 判据。补码符号位解释正确。
5.5 步骤 4:节奏(注入期间顺带看)
注入期间 frames= 应仍严格 1000 Hz 递增(10 s 间隔 +10000 左右),idle=0,
adc1_err=0。这一条替代了原方案里"用示波器看 U3.14 BUSY 有脉冲"的判据——不需要示波器。
2026-10-27 实测结论:PASS。 注入前(20:58 那次开机)与注入后(21:29)各取两行相隔
10 s 的心跳,两边都是 Δ9998 码 / ≈10.0 s ≈ 1000.1 Hz,idle=0、adc1_rc=0、adc1_err=0:
| 时点 | frames= 两行 |
Δ | 折算 |
|---|---|---|---|
| 注入前(20:58) | 29997 → 39995 | 9998 | 1000.5 Hz |
| 注入后(21:29) | 1819639 → 1829637 | 9998 | 1000.1 Hz |
⚠ 口径说明:这两次是"注入前后",不是"注入进行中"——已知电压注入验证判据 ⑤ 要的正是"注入前后
tpafe5160_frame_seq() 仍严格 1000 Hz 递增",故按此口径已达标。若日后要连"进行中"也钉住,
在任一注入过程里再抓两行即可(注入不改变 TIM3 硬件触发,理论上无影响,但没测过就不算证过)。
adc1_gap / tgap / skip 是本次开机以来的累计值(548 / 363 / 183),10 s 内只增 3 / 2 / 1,
占比约 0.03 %,属正常漏检量级,不是停摆。
5.6 步骤 5:回写
- 把实测斜率、零点、映射结果写进
docs/硬件平台/ADC通道映射说明.md§8,把"尚未执行"改成 实测值 + 日期; - 若实测确认无分压,同步在
docs/硬件平台/ADC通道映射说明.md§7.1 的链路分段表把第 ③ 段 (AINn↔ 转换器引脚)从"待台架实测"改为实测结论; docs/任务规划/数据可信.md的已知电压注入验证行按"完成即删"销项;判据与实测证据的属主是docs/硬件平台/ADC通道映射说明.md§8.1。
6. 判据汇总
| 项 | 判据 | 2026-10-27 实测 | 结论 | 不通过意味着 |
|---|---|---|---|---|
| 零点 | TPAFE 码值绝对值 ≤ 30;STM32 码值绝对值 ≤ 5 | 8 路全部 0~5 码(≤4.0 mV) | PASS | 有真实偏置,需查前端;可能超出补偿上限 |
| 线性 | R² ≥ 0.999 | 0.9999997(UA 三点) | PASS | 前端非线性或注入源带载失真 |
| 斜率 | 偏差 ≤ 2 % | −0.14 %(6544.2 vs 6553.6 码/V) | PASS | 前端有未识别元件,或转换器档位/参考错 |
| 映射 | 注入哪路只动哪路 | 8 路短接各自塌到本路(步骤 1 代偿;串扰未单独证) | PASS | 语义表与物理通道不符(k_adc_map[] 错) |
| 极性 | −1.0 V → −6554 码 | −6566 / −6568 / −6566,对称性 ≤0.34 % | PASS | 补码符号处理错 |
| 节奏 | 注入期间仍 1000 Hz | 注入前/后各 Δ9998 / 10 s ≈ 1000 Hz,idle=0、adc1_err=0 |
PASS | 注入改变了输入共模,触发转换异常 |
总体结论(2026-10-27):六项全部 PASS。合起来证明了三件事:
① ③ 段(AINn ↔ 转换器引脚)变比确为 1:1,无隐藏分压(斜率偏差 −0.14 %);
② 8 路语义 ↔ 物理端子一一对应(零点步骤逐路代偿);
③ TPAFE 补码符号位解释正确(对称性 ≤0.34 %)。
已知电压注入验证的判据 ①②③④⑤⑥ 至此全部闭环(判据与实测记录 → docs/硬件平台/ADC通道映射说明.md §8.1)。
⚠ 两项残留口径(不影响本轮 PASS,但别当成已验证):串扰未单独证(见上表"映射"行); 节奏只测了注入前后、没测注入进行中。两项若日后怀疑,各自的补做方法已写在对应小节。
7. 安全红线
- STM32 侧严禁超过 3.3 V(VDDA + 0.3 V 即击穿),电位器上限就接 3.3 V 轨,不要接 5 V。
- TPAFE 侧按判据只到 ±2 V,虽芯片容 ±5 V,但判据不需要更大。
- 端子侧不许直接上额定电压(220 V / 100 V 二次值)。本次是直流低压注入,
与"加压试保护"是两件事,后者要等端子/子板变比确认(
docs/硬件平台/ADC通道映射说明.md§7.1 链路分段表 ④ 行)之后单独排。 - 引脚侧注入必须外串 10 k,且先接线后上电、先断电后拆线。
- 注入源与板子共地;电位器一端接 3.3 V、一端接 AGND、中间抽头串 10 k 到注入点。