docs: 数据可信与 ADC 通道映射只留现状,清历史与悬空引用

数据可信.md 与 ADC通道映射说明.md 按「只写现状」口径重写:
删历史沿革、推理过程与已删小节的残留指针,保留现行判据。

- 数据可信:§2.7 删「当时的证据」六行表;§4.6.1 标题改「范围与
  幅度上限」、四行改现状陈述;§4.6.2 删轮次名历史映射注;§4.6.3
  段文件行去过程语;删节尾孤立排程段;§4.4 负零点段收成现状结论。
- 数据可信:把「系数合法带」从已删的 §8 风险表搬回 §4.1(代码头注释
  仍指向它,属搬回不是新发明)。
- 数据可信:行号纠错 adc_task.c:382 -> :425、protect_task.c:245 ->
  :268,逐个 grep 核对。
- 跨文档与代码:12 处指向已删 §4.6.4/§4.6.5/§8/§9/§10 的悬空引用改到
  现存小节或内联结论,涉 6 处 App 源文件头注释与 6 篇文档。
- 两个 SVG 生成器文案同步重跑,产物同笔提交。

check_doc_links --all 通过(221 篇);pre-commit 全绿。
This commit is contained in:
2026-11-06 17:41:11 +08:00
parent c2a946f993
commit 163b933715
18 changed files with 181 additions and 375 deletions
+3 -3
View File
@@ -108,7 +108,7 @@ ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」
V0.2 改版与本目录 `adc_input` 映射表同步改。
- 三态可用性 `adc_cal_flags()`:VALID(已按变比标定,二次值成立——端子变比确认与两点标定前恒 0)
/ CLIPPED(运行期按来源派生,V0.2 后自动清零)。**消费者判「能不能信」只许查它**,
`adc_cal_apply()` 不返回可用性(「数据可信」§8 风险表)。
`adc_cal_apply()` 不返回可用性(「数据可信」§4.2 三态可用性表)。
- 合法带哨兵:k ∉ ROM×[0.5,2.0] 或 |b| > 8192 → 折算回退 ROM + 每通道每开机一条
`[ERR]` + VALID 被压制(**即便文件位图说已标定**);这层兜底同时挡坏文件与坏标定。
- `adc_cal_set()` / `adc_cal_two_point()`:整定与两点公式的算术核已齐备(单测还原合成
@@ -118,8 +118,8 @@ ADC 引脚电压 V)+ `adc_health_rail_watch()` ×9(「采样通道自检」
### 3.9 `meas.c` / `.h` — 遥测快照发布(全周傅氏相量发布侧,「数据可信」波次)
- **唯一发布者 = adcTask**:`phasor_run()`/`freq_run()` 同拍、200 ms **tick 经过**分频
调 `meas_tick()`(非拍计数——idle/skip 拍拉长名义节拍)。docs/任务规划/数据可信.md §8
风险表"快照双写"行 = 评审判据:全仓 `meas_tick` 调用点数须为 1;iec104Task /
调 `meas_tick()`(非拍计数——idle/skip 拍拉长名义节拍)。`docs/任务规划/数据可信.md` §4.5
定"唯一发布者 = `adc_task`" = 评审判据:全仓 `meas_tick` 调用点数须为 1;iec104Task /
uiTask 只读。
- 值口径(第二轮「遥测快照发布」的 A-lite 裁决):**基波有效值瞬时透传**,与 phasor 使用区
**同拍同核逐位相等**(单测钉死);**不做** 4 点平均 / 谐波方和根——按
+1 -1
View File
@@ -290,7 +290,7 @@ uint32_t adc_cal_flags(adc_semantic_t sem) {
}
/* CLIPPED 由**来源**派生(R5:STM32 侧单极性无偏置 → 负半周削顶)——
* V0.2 改版(8 路全接 TPAFE,消除双转换器无共同采样触发)后本位自动恒 0,无需改码,
* 对应「数据可信」§10「页面与 104 绑定零改动」的要求 */
* 对应「数据可信」§4.2 三态可用性表「页面与 104 绑定零改动」的要求 */
if (s_rom_k_stm32((unsigned)sem) != 0) {
f |= ADC_CAL_F_CLIPPED;
}
+2 -2
View File
@@ -62,7 +62,7 @@ extern "C" {
#define ADC_CAL_K_Q16_TPAFE (10000000L)
#define ADC_CAL_K_Q16_STM32 (52800000L)
/* 系数合法带(「数据可信」§8 风险表):k 必须落在板级 ROM 系数的 ×[0.5, 2.0]
/* 系数合法带(「数据可信」§4.1 尾注):k 必须落在板级 ROM 系数的 ×[0.5, 2.0]
* 区间内;带宽用 ROM 值移位实现(>>1 / <<1),不设独立宏防两处真相 */
/* 零点偏移幅值上限(码值):超此即判文件损坏/异常标定,回退 ROM 并留痕 */
@@ -188,7 +188,7 @@ int adc_cal_set(adc_semantic_t sem, int32_t k_q16, int32_t b_codes);
* v_lo_uv/v_hi_uv - 两点实测电压(µV,v_hi > v_lo,端子/引脚域均可) int32_t
* p_k_q16 / p_b - 输出:系数(Q16)与零点偏移(码值) int32_t *
* 返 回 值:0 - 成功;-1 - 参数/斜率非法;-2 - 零点越 ±ADC_CAL_B_MAX(先查前端,
* 不得用系数凑错斜率,「数据可信」§8 风险表) int
* 不得用系数凑错斜率,「数据可信」§4.1 尾注) int
* 限定条件:无(纯整数运算,主机侧可直接单测)
* 函数说明:k = (v_hi−v_lo)×65536/(c_hi−c_lo)(四舍五入),b = v_lo×65536/k − c_lo;
* 实测注入未做(台架待跑),本函数即「公式齐备」的交付物
+4 -4
View File
@@ -61,8 +61,8 @@ typedef struct {
* 频率点不适用"额定百分比"(额定附近 0.5 Hz 与旧值同量级,维持 0.5 并随
* 运行参数段可调)。自 104 改读快照起本表**只作工厂默认载体**:生效死区 =
* App/algo/run_par.c 的 [run_par] 引擎副本(运行参数段真源收编,本层不再存副本);削顶五路不再 sem=-1 绑死,而是绑快照槽、由品质 CLIPPED
* 驱动线上 IV——V0.2 削顶消失后点位零改动自动启用(docs/任务规划/
* 数据可信.md §10 的「双转换器无共同采样触发」行)。
* 驱动线上 IV——V0.2 削顶消失后点位零改动自动启用(口径见 docs/任务规划/
* 数据可信.md §4.2 三态可用性表)。
* ⚠ 过渡期(eng=0 引脚电压域,两点标定完成前):上送值本身非二次值,死区
* 数字按本域偏保守(迟报不漏报);标定落地后复核(「数据可信」§2.3 表
* 第 2 行)。判定 = 死区连续 2 点确认(104 改读快照),见 iec104_pts.h COV 说明。 */
@@ -176,8 +176,8 @@ uint32_t iec104_pts_yc_ioa(uint8_t idx) {
* 入口参数:q16 - 源侧品质(低字节与线上同值;高字节为 MEAS_QDS_CLIPPED 域内位)
* 返 回 值:线上 QDS 字节 uint8_t
* 函数说明:CLIPPED(硬件削顶,104 无对应位)映射为 IV——「削顶通道 104 恒
* IV」口径(docs/任务规划/数据可信.md §8 风险表「削顶通道被当成可测」
* 行)改由快照品质驱动,不再靠点表绑死 -1;OV/NT/IV 透传,其余高位丢弃。
* IV」口径(docs/任务规划/数据可信.md §4.2 三态可用性表)
* 改由快照品质驱动,不再靠点表绑死 -1;OV/NT/IV 透传,其余高位丢弃。
*/
static uint8_t s_q_map(uint16_t q16) {
uint8_t w = (uint8_t)(q16 & (uint16_t)(IEC104_QDS_OV | IEC104_QDS_NT
+1 -1
View File
@@ -9,7 +9,7 @@
* 测频与遥测快照(App/algo/meas.h,「数据可信」104 改读快照与频率点绑定):电气 8 路绑快照槽,
* 有效性由快照品质驱动——V0.1 削顶路(docs/算法/继电保护功能复现规划.md
* §1.6)快照置 CLIPPED → 本层映射为线上 IV(V0.2 后自动启用,绑定零
* 改动,见 docs/任务规划/数据可信.md §10「双转换器无共同采样触发」行);0x401d 绑频率源,
* 改动,见 docs/任务规划/数据可信.md §4.2 三态可用性表);0x401d 绑频率源,
* freq_valid()==0 → IV;
* - YX:IOA 1~33(§1.5 表(3));双点 = 开关位置类(YX1~4,本期无硬件 → IV),
* 保护动作类 YX15~23 映射 prot_elm 状态,闭锁类 YX31~33 映射 prot_set;
+1 -1
View File
@@ -443,7 +443,7 @@ void adc_task_func(void *arg) {
/* 测频与遥测快照发布(「数据可信」这一项,道D,M5):200 ms tick 经过分频。
* 唯一发布者 = 本任务(全仓 meas_tick 调用点数 = 1 为评审判据,
* 「数据可信」§8 风险表"快照双写"行);只在**压环成功的真新帧拍**发布
* 「数据可信」§4.5 定"唯一发布者 = adc_task");只在**压环成功的真新帧拍**发布
* ——idle/skip 拍压环未推进,发布 = 重复旧窗。品质注入唯一源 =
* adc_cal_flags()(§4.2 三态表;纯读,每 200 ms 才跑一遍)。 */
if ((uint32_t)(now - s_meas_ms) >= MEAS_PERIOD_MS) {
+14 -15
View File
@@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1060" height="818" viewBox="0 0 1060 818" font-family="Microsoft YaHei, Segoe UI, PingFang SC, sans-serif">
<rect x="0" y="0" width="1060" height="818" fill="#ffffff"/>
<text x="46.0" y="42.0" font-size="21" font-weight="700" fill="#0f172a">同一个针脚,两种证法 —— 直流只证「高度」,正弦才证「形状与节拍」</text>
<text x="46.0" y="68.0" font-size="13" fill="#475569">上排已做完(2026-10-27 静态注入六项判据全 PASS);下排一次也没做过:正弦波从没进过这条链,所以后面的相量、测频、削顶、谐波对不对,现在无人能答</text>
<text x="46.0" y="68.0" font-size="13" fill="#475569">上排 2026-10-27 静态注入六项判据全 PASS;下排 2026-11-02 / 11-04 台架两轮跑完六轮,幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波全部闭合</text>
<text x="46.0" y="87.0" font-size="13" fill="#475569">两排共用同一个注入点、同一套前端、同一份折算代码 —— 差别只在信号源是「平的」还是「会走 20 点/周的正弦」</text>
<rect x="34.0" y="108.0" width="992.0" height="160.0" rx="10" fill="#f0fdf4" stroke="#bbf7d0" stroke-width="1.2"/>
<text x="46.0" y="128.0" font-size="12.5" font-weight="700" fill="#16a34a">上排 · 直流静态标定(已做)</text>
@@ -46,7 +46,7 @@
<text x="885.0" y="218.0" font-size="10.5" fill="#475569">R² = 0.9999997,斜率</text>
<text x="885.0" y="232.0" font-size="10.5" fill="#475569">差 −0.14 %</text>
<rect x="34.0" y="286.0" width="992.0" height="160.0" rx="10" fill="#fff1f2" stroke="#fecdd3" stroke-width="1.2"/>
<text x="46.0" y="306.0" font-size="12.5" font-weight="700" fill="#e11d48">下排 · 交流正弦验证(本文新增 · 待做)</text>
<text x="46.0" y="306.0" font-size="12.5" font-weight="700" fill="#e11d48">下排 · 交流正弦验证(已做两轮)</text>
<rect x="922.0" y="294.0" width="88.0" height="34.0" rx="6" fill="#ffffff" stroke="#e11d48" stroke-width="1.2"/>
<line x1="926.0" y1="311.0" x2="1006.0" y2="311.0" stroke="#cbd5e1" stroke-width="1" stroke-dasharray="3 3"/>
<polyline points="928.0,311.0 929.3,310.1 930.5,309.1 931.8,308.2 933.1,307.3 934.3,306.5 935.6,305.7 936.9,305.0 938.1,304.3 939.4,303.7 940.7,303.2 941.9,302.8 943.2,302.4 944.5,302.2 945.7,302.0 947.0,302.0 948.3,302.0 949.5,302.2 950.8,302.4 952.1,302.8 953.3,303.2 954.6,303.7 955.9,304.3 957.1,305.0 958.4,305.7 959.7,306.5 960.9,307.3 962.2,308.2 963.5,309.1 964.7,310.1 966.0,311.0 967.3,311.9 968.5,312.9 969.8,313.8 971.1,314.7 972.3,315.5 973.6,316.3 974.9,317.0 976.1,317.7 977.4,318.3 978.7,318.8 979.9,319.2 981.2,319.6 982.5,319.8 983.7,320.0 985.0,320.0 986.3,320.0 987.5,319.8 988.8,319.6 990.1,319.2 991.3,318.8 992.6,318.3 993.9,317.7 995.1,317.0 996.4,316.3 997.7,315.5 998.9,314.7 1000.2,313.8 1001.5,312.9 1002.7,311.9 1004.0,311.0" fill="none" stroke="#e11d48" stroke-width="1.9" stroke-linejoin="round"/>
@@ -73,19 +73,19 @@
<rect x="46.0" y="346.0" width="136.0" height="88.0" rx="8" fill="#ffffff" stroke="#e11d48" stroke-width="1.6"/>
<text x="53.0" y="364.0" font-size="12.5" font-weight="700" fill="#0f172a">信号发生器</text>
<text x="53.0" y="382.0" font-size="10.5" fill="#475569">50 Hz 正弦</text>
<text x="53.0" y="396.0" font-size="10.5" fill="#475569">幅度按峰值算,见底部红</text>
<text x="53.0" y="410.0" font-size="10.5" fill="#475569">线</text>
<text x="53.0" y="396.0" font-size="10.5" fill="#475569">幅度按 Vpp 设定,见底</text>
<text x="53.0" y="410.0" font-size="10.5" fill="#475569">部红线</text>
<path d="M 192.2 386.0 L 201.2 390.0 L 192.2 394.0 Z" fill="#334155"/>
<line x1="184.0" y1="390.0" x2="194.2" y2="390.0" stroke="#334155" stroke-width="1.6"/>
<rect x="212.4" y="346.0" width="136.0" height="88.0" rx="8" fill="#ffffff" stroke="#e11d48" stroke-width="1.6"/>
<text x="219.4" y="364.0" font-size="12.5" font-weight="700" fill="#0f172a">注入点 R31</text>
<text x="219.4" y="382.0" font-size="10.5" fill="#475569">同上排同一个点</text>
<text x="219.4" y="382.0" font-size="10.5" fill="#475569">同一条注入点</text>
<text x="219.4" y="396.0" font-size="10.5" fill="#475569">外串 10 k、与板共地</text>
<path d="M 358.6 386.0 L 367.6 390.0 L 358.6 394.0 Z" fill="#334155"/>
<line x1="350.4" y1="390.0" x2="360.6" y2="390.0" stroke="#334155" stroke-width="1.6"/>
<rect x="378.8" y="346.0" width="136.0" height="88.0" rx="8" fill="#ffffff" stroke="#e11d48" stroke-width="1.6"/>
<text x="385.8" y="364.0" font-size="12.5" font-weight="700" fill="#0f172a">前端 + 转换器</text>
<text x="385.8" y="382.0" font-size="10.5" fill="#475569">同上排同一条链</text>
<text x="385.8" y="382.0" font-size="10.5" fill="#475569">同一套前端</text>
<text x="385.8" y="396.0" font-size="10.5" fill="#475569">STM32 五路负半周必削顶</text>
<path d="M 525.0 386.0 L 534.0 390.0 L 525.0 394.0 Z" fill="#334155"/>
<line x1="516.8" y1="390.0" x2="527.0" y2="390.0" stroke="#334155" stroke-width="1.6"/>
@@ -104,10 +104,9 @@
<line x1="849.6" y1="390.0" x2="859.8" y2="390.0" stroke="#334155" stroke-width="1.6"/>
<rect x="878.0" y="346.0" width="136.0" height="88.0" rx="8" fill="#ffffff" stroke="#e11d48" stroke-width="1.6"/>
<text x="885.0" y="364.0" font-size="12.5" font-weight="700" fill="#0f172a">读数出口</text>
<text x="885.0" y="382.0" font-size="10.5" fill="#475569">meas 200 ms → 104 YC</text>
<text x="885.0" y="396.0" font-size="10.5" fill="#475569"> 0x4011</text>
<text x="885.0" y="410.0" font-size="10.5" fill="#475569">幅值 + 品质 + 频率(或</text>
<text x="885.0" y="424.0" font-size="10.5" fill="#475569"> UI)</text>
<text x="885.0" y="382.0" font-size="10.5" fill="#475569">meas 200 ms + 录波段</text>
<text x="885.0" y="396.0" font-size="10.5" fill="#475569">文件</text>
<text x="885.0" y="410.0" font-size="10.5" fill="#475569">幅值 + 品质 + 频率</text>
<text x="46.0" y="456.0" font-size="12.5" font-weight="700" fill="#2563eb">只有正弦能证的六件事(直流在构造上就证不到)</text>
<rect x="46.0" y="466.0" width="151.3" height="74.0" rx="8" fill="#eff6ff"/>
<line x1="46.0" y1="466.0" x2="46.0" y2="540.0" stroke="#2563eb" stroke-width="3"/>
@@ -140,9 +139,9 @@
<rect x="862.7" y="466.0" width="151.3" height="74.0" rx="8" fill="#eff6ff"/>
<line x1="862.7" y1="466.0" x2="862.7" y2="540.0" stroke="#2563eb" stroke-width="3"/>
<text x="872.7" y="486.0" font-size="12" font-weight="700" fill="#0f172a">谐波实例 C04 / C05</text>
<text x="872.7" y="504.0" font-size="10" fill="#475569">二次 / 五次相量已建但无消</text>
<text x="872.7" y="518.0" font-size="10" fill="#475569">费者:发生器给含谐波信号才</text>
<text x="872.7" y="532.0" font-size="10" fill="#475569">能验</text>
<text x="872.7" y="504.0" font-size="10" fill="#475569">二次 / 五次相量:单注 100</text>
<text x="872.7" y="518.0" font-size="10" fill="#475569"> / 250 Hz 已验各认各的次</text>
<text x="872.7" y="532.0" font-size="10" fill="#475569">,叠加工况待标准源</text>
<rect x="46.0" y="558.0" width="476.0" height="128.0" rx="10" fill="#fff1f2" stroke="#e11d48" stroke-width="1.6"/>
<text x="60.0" y="582.0" font-size="12.5" font-weight="700" fill="#e11d48">安全红线(照抄 ADC通道映射说明 §7)</text>
<text x="60.0" y="604.0" font-size="11" fill="#0f172a">TPAFE 侧只到 ±2 V:正弦看峰值不只看有效值 —— 1 Vrms 的峰值已是 1.41 V,再高</text>
@@ -159,6 +158,6 @@
<text x="552.0" y="657.0" font-size="11" fill="#0f172a">跨转换器相位:UB/UC 与 UA 分属两片转换器、无共同采样触发(V0.1 硬件缺陷),任何</text>
<text x="552.0" y="672.0" font-size="11" fill="#475569">相位比较都不作数。</text>
<line x1="46.0" y1="700.0" x2="1014.0" y2="700.0" stroke="#cbd5e1" stroke-width="1"/>
<text x="46.0" y="722.0" font-size="13" fill="#475569">读数出口现在就有:104 YC(test/host/iec104_master.py,浮点无量化)+ 串口每 10 s 的 phasor(hb) / freq(hb) / meas: 行;但板上没有「把窗里 2</text>
<text x="46.0" y="741.0" font-size="13" fill="#475569">0 个点导出来」的出口,正弦只能靠派生标量证,而 phasor 行是 ×0.1 定点(注 1 V 只剩 10 格)。</text>
<text x="46.0" y="722.0" font-size="13" fill="#475569">读数出口:串口每 10 s 的 phasor(hb) / freq(hb) / meas: 行,加上录波段文件(一次 320 点 / 8 路,PC 侧 wave_read.py 可 dump / fft / shape</text>
<text x="46.0" y="741.0" font-size="13" fill="#475569"> / plot);心跳行是 ×0.1 定点(注 1 V 只剩 10 格),定量判据一律走段文件重算。</text>
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

+8 -9
View File
@@ -1,8 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1060" height="712" viewBox="0 0 1060 712" font-family="Microsoft YaHei, Segoe UI, PingFang SC, sans-serif">
<rect x="0" y="0" width="1060" height="712" fill="#ffffff"/>
<text x="46.0" y="42.0" font-size="21" font-weight="700" fill="#0f172a">「数据可信」是五级台阶 —— 现在踩在第 2 级</text>
<text x="46.0" y="42.0" font-size="21" font-weight="700" fill="#0f172a">「数据可信」是五级台阶 —— 现在踩在第 3 级</text>
<text x="46.0" y="68.0" font-size="13" fill="#64748b">每升一级只多答一个问题:通路活 → 静态读数对 → 动态波形对 → 换算到端子 → 精度达标;台阶的高度差 = 下游能多信多少</text>
<text x="46.0" y="88.0" font-size="13" fill="#64748b">第 3 级不要标准源、也不要往端子加压:一台信号发生器 + 已有的注入点就能做(判据见 docs/任务规划/数据可信.md §4.6)</text>
<text x="46.0" y="88.0" font-size="13" fill="#64748b">第 3 级已台架闭环(2026-11-02 / 11-04 两轮),用的是手边发生器 + 已有的注入点;第 4、5 级在等子板变比与标准源</text>
<rect x="34.0" y="106.0" width="600.0" height="532.0" rx="12" fill="#eff6ff"/>
<rect x="46.0" y="370.0" width="196.0" height="96.0" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="2"/>
<circle cx="70.0" cy="396.0" r="13" fill="#16a34a"/>
@@ -14,11 +14,11 @@
<text x="272.0" y="337.0" font-size="13" text-anchor="middle" font-weight="700" fill="#ffffff">2</text>
<text x="292.0" y="338.0" font-size="14.5" font-weight="700" fill="#0f172a">静态引脚电压</text>
<text x="259.0" y="364.0" font-size="11" font-weight="700" fill="#16a34a">已证 · 2026-10-27</text>
<rect x="450.0" y="242.0" width="196.0" height="224.0" rx="8" fill="#fff1f2" stroke="#e11d48" stroke-width="2"/>
<circle cx="474.0" cy="268.0" r="13" fill="#e11d48"/>
<rect x="450.0" y="242.0" width="196.0" height="224.0" rx="8" fill="#f0fdf4" stroke="#16a34a" stroke-width="2"/>
<circle cx="474.0" cy="268.0" r="13" fill="#16a34a"/>
<text x="474.0" y="273.0" font-size="13" text-anchor="middle" font-weight="700" fill="#ffffff">3</text>
<text x="494.0" y="274.0" font-size="14.5" font-weight="700" fill="#0f172a">动态引脚波形</text>
<text x="461.0" y="300.0" font-size="11" font-weight="700" fill="#e11d48">待做 · 本文新增</text>
<text x="461.0" y="300.0" font-size="11" font-weight="700" fill="#16a34a">已证 · 2026-11-04</text>
<rect x="652.0" y="178.0" width="196.0" height="288.0" rx="8" fill="#fffbeb" stroke="#d97706" stroke-width="2"/>
<circle cx="676.0" cy="204.0" r="13" fill="#d97706"/>
<text x="676.0" y="209.0" font-size="13" text-anchor="middle" font-weight="700" fill="#ffffff">4</text>
@@ -41,10 +41,9 @@
<text x="258.0" y="557.0" font-size="11.5" fill="#64748b">,差 −0.14 %</text>
<text x="460.0" y="490.0" font-size="12.5" font-weight="700" fill="#0f172a">注 1 V 正弦,算出来还是不是</text>
<text x="460.0" y="507.0" font-size="12.5" font-weight="700" fill="#0f172a"> 1 V?</text>
<text x="460.0" y="527.0" font-size="11.5" fill="#64748b">注正弦验全周傅氏幅值 / 相位 /</text>
<text x="460.0" y="542.0" font-size="11.5" fill="#64748b"> 测频 / 削顶 / 谐波抑制。挡路</text>
<text x="460.0" y="557.0" font-size="11.5" fill="#64748b">:FREQ_AMP_MIN = 50 V 在引</text>
<text x="460.0" y="572.0" font-size="11.5" fill="#64748b">脚域恒不过 → 测频只能读到 IV</text>
<text x="460.0" y="527.0" font-size="11.5" fill="#64748b">幅值 / 波形 / 相位 / 测频 / </text>
<text x="460.0" y="542.0" font-size="11.5" fill="#64748b">削顶 / 谐波六轮全跑;测频轮以</text>
<text x="460.0" y="557.0" font-size="11.5" fill="#64748b">「如实报不可测」通过</text>
<text x="662.0" y="490.0" font-size="12.5" font-weight="700" fill="#0f172a">引脚上这 1 V 对应端子侧几 V</text>
<text x="662.0" y="507.0" font-size="12.5" font-weight="700" fill="#0f172a">?</text>
<text x="662.0" y="527.0" font-size="11.5" fill="#64748b">④ 子板 / 端子板变比:仓内无原</text>

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

+1 -1
View File
@@ -86,7 +86,7 @@
1. **完成即删除待办条目**,同时清理其他文档对它的引用;结论和证据写入模块文档,
历史由 `git log` 保留。
2. **当前任务只改 `UI补齐.md`,后续事项只改 `登记簿.md`**;顺序变化才改本文件 §2。
3. `数据可信.md` 的 §2、§4、§7~§10 仍被代码头注释引用为设计依据,不能按“已完成”
3. `数据可信.md` 的 §2、§4、§7 仍被代码头注释引用为设计依据,不能按“已完成”
删掉;其待办只认 §5 的任务卡表(标识列用语义短语,卡片增减不改本条口径)。
4. 专项文档只放**还没闭环的约束**;已落地事项的规格正文归代码头注释或模块文档,
销项即删文件并把引用改指现行出处(先例:`测试与架构专项.md` 已删除 2026-10-28,
+58 -187
View File
@@ -1,15 +1,15 @@
# 数据可信(等待台架与外部资源)
# 数据可信(等外部资源:子板变比与标准源)
> **这篇是什么**:把"采集出来的数到底能不能信"一次讲完——已经证到哪一步、按构造还证不到什么、
> 下一跳怎么跨、哪些必须等外部资源。
> **它同时是设计约束的归属文件**:§2.1 / §2.3 / §2.6 / §4.1~§4.5 / §7 / §8 / §9 / §10 被**代码与测试头注释**
> **它同时是设计约束的归属文件**:§2.1 / §2.3 / §2.6 / §4.1~§4.5 / §7 被**代码与测试头注释**
> 当口径出处引用(`adc_cal.*` / `meas.*` / `cfg_file.*` / `prot_elm` / `protect_task.c` / `ui_data*` /
> `test/host/prot_dim/*`),它们是**现行规范,不是"已完成记录"**。已完成的事项按"完成即销项"只删 §5 表里的行。
> 排序权威只有一处:`docs/任务规划/README.md` §2;后续事项索引在 `docs/任务规划/登记簿.md` §7。
> **最该先知道的一条**:保护判据现在处于**未标定闭锁**态。判据 = `App/algo/adc_cal.c` 的
> `adc_cal_prot_blocked()`——UA / UN / IA 的 `ADC_CAL_F_VALID` **全置位**才放行,`protect_task` 拿它的返回值
> 停走判据(判据已从 `protect_task.c` 搬进 `adc_cal.c`,旧行号引用作废;只有 `DTU_BENCH` 构建旁路,**且只旁路这一处**)。
> 停走判据(只有 `DTU_BENCH` 构建旁路,**且只旁路这一处**)。
> 用户裁定(2026-10-25):**保持闭锁到标准源到位**,不缩短解锁路径(不用万用表走捷径)。
---
@@ -18,7 +18,7 @@
图由 `tools/arch_diagram/gen_data_trust_ladder_svg.py` 生成(改图改脚本重跑,勿手改 SVG)。
![数据可信是五级台阶,现在踩在第 2 级](../images/数据可信台阶.svg)
![数据可信是五级台阶,现在踩在第 3 级](../images/数据可信台阶.svg)
每升一级只多答一个问题,台阶之间的高度差就是"下游能多信多少":
@@ -26,7 +26,7 @@
|---|---|---|
| 1 通路活 | 9 路都在转换、没串道、极性没反? | ✅ 2026-10-27 已证 |
| 2 静态引脚电压 | 注 1 V 直流,读数是不是 1 V? | ✅ 2026-10-27 已证(六项判据全 PASS,§2.6) |
| **3 动态引脚波形** | **注 Vpp 2.828 V 正弦(板上读数 ≈1 V),算出来还是不是 1 V?** | **✅ 2026-11-02 / 11-04 已跑两轮、六轮全部闭合**(削顶 2 Hz 档与复位复核经用户裁定 2026-11-04 关闭;谐波 B 行超差已归因板端前端 RC fc≈796 Hz → §4.6 任务卡;实测结论 `docs/硬件平台/ADC通道映射说明.md` §8.2) |
| **3 动态引脚波形** | **注 Vpp 2.828 V 正弦(板上读数 ≈1 V),算出来还是不是 1 V?** | **✅ 2026-11-02 / 11-04 已跑两轮、六轮全部闭合**(削顶 2 Hz 档与复位复核经用户裁定 2026-11-04 关闭;谐波 B 行超差已归因板端前端 RC fc≈796 Hz → §4.6.2 谐波轮;实测结论 `docs/硬件平台/ADC通道映射说明.md` §8.2) |
| 4 端子二次值 | 引脚上这 1 V 对应端子侧几 V? | 🟡 等子板原理图或实物 |
| 5 精度等级验收 | 额定工况下整条链误差够几级? | 🟡 等标准源 |
@@ -34,9 +34,9 @@
1. **第 1、2 级已闭环**,证据与判据的属主是 `docs/硬件平台/ADC通道映射说明.md` §8.1,执行步骤属主是
`docs/测试说明/专项验证/ADC前端注入验证流程.md`——本文不重抄,只写"证到哪、为什么不能再往外推"。
2. **第 3 级是当前唯一的空白,而且不需要任何外部资源**:一台能出 50 Hz 正弦的交流信号发生器,
2. **第 3 级已于 2026-11-02 / 11-04 台架闭环,全程没用到任何外部资源**:一台能出 50 Hz 正弦的交流信号发生器,
接在**已经验证过的那个注入点**上就行。它比第 4、5 级安全一个量级——只需 ±2 V 以内的正弦,
而端子级验证要上 100 V / 220 V 二次值。**不用烧高压、不用标准源,这是把它排最前的理由**(§4.6)。
而端子级验证要上 100 V / 220 V 二次值。
3. **第 4、5 级在等外部**:④ 子板/端子板变比(仓库里没有原理图)与标准源两点标定,
两者完成前 `eng` 保持 0,本波只承诺"ADC 引脚电压"。
@@ -46,9 +46,9 @@
|---|---|
| 判断现在这些数能信到什么程度 | §1 这张图 + §2.6(静态证到哪)+ §2.7(动态证到哪) |
| 改采集 / 算法 / 品质位相关代码 | §2.1 §2.2 §2.3(口径)+ §4.1~§4.5(设计依据) |
| 上台架做正弦验证 | ✅ 已闭环(2026-11-04);复跑看 §4.6(接法、六轮判据、数字从哪儿读、坑)+ §5 的「信号发生器动态波形验证」卡 |
| 看还差谁、按什么顺序做 | §5 任务卡 + §6 顺序图 |
| 确认某件事是**故意不做**而不是漏了 | §9;有没有踩坑风险看 §8 |
| 复跑六轮交流验证 | §4.6(判据、数字从哪儿读、坑)+ §5 的「信号发生器动态波形验证」卡 |
| 看还差谁、按什么顺序做 | §5 任务卡 |
| 确认某件事是**故意不做**而不是漏了 | §2.7 的「按下游列一遍」表 + §5 任务卡里的未闭合项 |
---
@@ -68,21 +68,21 @@
| IB / IC / IN | STM32 ADC1 | 同上 | 805.66 µV | 同上 | **805.66 µV/码** | ❌ 削顶 |
| TEMP | STM32 ADC1 | 同上 | 805.66 µV | 同上 | 热敏非线性 | — 不纳入线性标定 |
- 通道数 `ADC_SEM_COUNT = 9`(8 电气 + 温度),枚举定义 `App/algo/adc_input.h:38-49`。
- 唯一折算点:`App/task/adc_task.c:382` 的 `frame[s] = adc_cal_apply((adc_semantic_t)s, code)`——
- 通道数 `ADC_SEM_COUNT = 9`(8 电气 + 温度),枚举定义 `App/algo/adc_input.h:38-49`(`adc_semantic_t`)。
- 唯一折算点:`App/task/adc_task.c:425` 的 `frame[s] = adc_cal_apply((adc_semantic_t)s, code)`——
**全仓只有这一处**把码值变成工程量,现单位 = **ADC 引脚电压 V**(`eng = 0`)。
- 端到端链路分四段(① 语义↔网名↔通道、② 引脚电压↔码值、③ `AINn` ↔ 引脚、④ 端子 ↔ `AINn`),
属主 `docs/硬件平台/ADC通道映射说明.md` §7.1:①②③ 已定死(③ 变比 1:1),**只有 ④ 是缺口**。
### 2.2 量纲错配与量纲回归(锚点:`test/host/prot_dim/*`;M4 退出判据⑥)
**这一节为什么必须在**:台架此前"通过",是因为**没有一条判据检查"不该动作时不动作"**。
"码值当工程量"的错配曾让 OC 拿 ~11000 码值去比 10 A 定值 → **恒假动作**。这类错的可怕之处不是
"测不准",而是**每次都跳**,而且三处消费者(判据、104、UI)一起错、一处都不报错。
**没有一条判据检查"不该动作时不动作",台架就会一路"通过"**:"码值当工程量"的错配会让 OC
拿 ~11000 码值去比 10 A 定值 → **恒假动作**。这类错不是"测不准",而是**每次都跳**,且三处消费者
(判据、104、UI)一起错、一处都不报错。
固化它的回归 = `test/host/prot_dim/`:从 **ADC 码值**出发、**显式写出码值↔二次值换算**,走真实的
折算 → 采样环 → 全周傅氏 → 元件判据链;任何一环把量纲弄丢(例如折算点被旁路),断言立刻翻转
(TC-PROTDIM-002 就是反错配对照,专门复现那次历史事故)。它用的是**合成系数 10 mV/码**,
(TC-PROTDIM-002 就是反错配对照,专门复现那次事故)。它用的是**合成系数 10 mV/码**,
不是板上 152.59 / 805.66 µV/码——**它证的是"链条别丢量纲",不证"变比数值对不对"**(后者归 §2.6 与 §4.6)。
| 量纲档 | 怎么进入这个档 | 现在的处置 |
@@ -101,7 +101,7 @@
| 2 | `App/protocol/iec104/iec104_pts.c:69-80` | `k_yc[].deadband` 已按点重定:电压 0.5 V、电流 0.005 A、频率 0.5 Hz(真源在 `run_par`,UI 可改) | ✅ 已重定;④ 变比到手后需再复核一次量纲 |
| 3 | `App/algo/prot_set.c:25-70` | `g_prot_set_meta[]` 定值 = 二次值 A / V(基准 100 V / 1 A):OC1 10 A、OV 120 V、UV 20 V、3U0 15 V… | 🟡 口径对,但**标定前无法在板上验真**;§7 #1 定了精度目标后连同 `min`/`max` 复核 |
### 2.4 / 2.5 —— 2026-10-25 瘦身时删除,编号不复用(防止被重新取走)
### 2.4 / 2.5 已删除,编号不复用
### 2.6 静态验证:已知电压注入已于 2026-10-27 台架闭环(锚点:`adc_cal.*` / `meas.*` / `ui_data*`)
@@ -125,8 +125,7 @@
**这一轮证到的是"一条水平线的高度"**:给定直流电压 → 码值 → 折算,斜率、零点、线性度、极性、
通道对位、节拍全在 ±2 % 内。**直流信号在时间轴上没有形状**,所以相位、频率、波形相关性、真实削顶、谐波
这五类**按构造**不在本节证据范围内——逐条列在 §2.7。另有两项**本轮未覆盖**:
串扰(零点步骤时其余七路浮空本身在漂)与"注入进行中"的节奏(只测了注入前后),口径同
`docs/硬件平台/ADC通道映射说明.md` §8.1 尾注。
串扰(零点步骤时其余七路浮空本身在漂)与"注入进行中"的节奏(只测了注入前后)。
**一个必须记住的区分**:`CLIPPED` 位是**来源派生**(`App/algo/adc_cal.c:291-293`:系数来自 STM32 就置位,
V0.1 恒命中 UB/UC/IB/IC/IN,位图 `0xE6`),它表示"这路不能测交流",**不等于**"这路此刻正在削顶"。真削顶的签名是
@@ -139,32 +138,20 @@ V0.1 恒命中 UB/UC/IB/IC/IN,位图 `0xE6`),它表示"这路不能测交
### 2.7 动态验证:已跑两轮(2026-11-02 / 11-04),六轮实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.2
**一句话**:这一档**不再是空白**——真实交流波形已经台架两轮验证(幅值/波形/相位/测频/谐波/削顶直流档都过了);
本节先留"当时为什么判空白"的证据链,下面按下游的表已按两轮实测更新。
**一句话**:这一档已台架两轮验证(幅值 / 波形 / 相位 / 测频 / 谐波 / 削顶直流档都过了)。
当时的证据(逐条可查,全部是各套件自己的自陈,不是推测——正是它们说明 PC 套件自己闭不了这一档):
| 出处 | 原话要点 |
|---|---|
| `test/host/phasor/run_unit_test.py` | 「板端**无信号源**,无法注入已知幅值/相位/频率的标准波形,因而无法验证"读数 = 设定有效值"」 |
| `test/host/meas/run_unit_test.py` | 「读数与注入源比对类判据仍归台架(实测采样类,本套件不覆盖)」 |
| `test/host/prot_dim/prot_dim_test.c` | 系数是合成覆写的 10 mV/码,非板上 152.59 / 805.66 µV/码 |
| `App/algo/adc_cal.h` | `adc_cal_two_point()`:「实测注入未做(台架待跑),本函数即"公式齐备"的交付物」 |
| `docs/测试说明/专项验证/ADC前端注入验证流程.md` | 「**只验直流**:零点 / 线性 / 通道映射 / 极性。不验交流有效值——台架无信号源」 |
| `App/task/adc_task.c` 心跳块 | `adc:` 是当拍瞬时码值、`meas:` 是 200 ms 快照——**没有一行能给出波形形状** |
按下游列一遍"现在能不能信"(2026-11-04 按台架两轮更新;数只详述在 `docs/硬件平台/ADC通道映射说明.md` §8.2,此处不抄第二份):
按下游列一遍"现在能不能信"(数只详述在 `docs/硬件平台/ADC通道映射说明.md` §8.2,此处不抄第二份):
| 下游 | 现在 | 为什么 |
|---|---|---|
| 基波有效值 | ✅ 过(±2 % 内,三档幅值两点复现) | 台架幅值轮 + 波形轮(基波分量口径)实证;端子二次值仍不归这档(§4.6.5) |
| 相位 | ✅ 同片内过(录波档 ≤2° 判据) | 同段 UA/UN 两路实测(0° 与 90° 两工况);**跨转换器仍禁比**——无同刻性是 V0.1 硬件边界(§9),不是待修缺陷 |
| 基波有效值 | ✅ 过(±2 % 内,三档幅值两点复现) | 台架幅值轮 + 波形轮(基波分量口径)实证;**端子二次值仍不归这一档**——从引脚到端子还隔着 ④ 段变比 |
| 相位 | ✅ 同片内过(录波档 ≤2° 判据) | 同段 UA/UN 两路实测(0° 与 90° 两工况);**跨转换器仍禁比**——两片转换器无共同采样触发,是 V0.1 硬件边界(`docs/硬件平台/ADC通道映射说明.md` §7 通道归属行),不是待修缺陷 |
| 频率 | ✅ 「如实报不可测」成立(这就是现状判据) | 含满幅注入段全不可测、UI 恒 `--`;**45~55 Hz 精度仍未验**——要验须降 `FREQ_AMP_MIN` 单跑一轮 → §7 #8 |
| 削顶 / 品质 | ✅ DC −1.00 V 档锁存 + sticky 实证;2.0 Hz 低频档与复位复核经用户裁定 2026-11-04 关闭 | `[ERR] rail: edge=0x2 sticky=0x2` 唯一一条、撤注恒持;执行见 §4.6 任务卡 |
| 谐波 C04 / C05 | 🟡 选择性轨已证(单注 100/250 Hz 分别只进对应桶、纯基波两桶为 0);**仍无消费者、无处上送** | 250 Hz→`Ia5` 行 −4.4 % **已按板端前端真实衰减关闭(2026-11-04)**:IA 前端差分滤波 C35 = 100 nF + R19/R21 各 1 k 构成一阶低通 fc ≈ 796 Hz,板端读数忠实、工频不受影响;谐波产品化需板改(模型与数据 `docs/硬件平台/ADC通道映射说明.md` §8.2,执行手册谐波记录 B 行);接到哪、给谁用归 §9 的谐波轨立项 |
| 削顶 / 品质 | ✅ DC −1.00 V 档锁存 + sticky 实证;2.0 Hz 低频档与复位复核经用户裁定 2026-11-04 关闭 | `[ERR] rail: edge=0x2 sticky=0x2` 唯一一条、撤注恒持;执行见 §4.6 削顶轮 |
| 谐波 C04 / C05 | 🟡 选择性轨已证(单注 100/250 Hz 分别只进对应桶、纯基波两桶为 0);**仍无消费者、无处上送** | 250 Hz→`Ia5` 行 −4.4 % **已按板端前端真实衰减关闭(2026-11-04)**:IA 前端差分滤波 C35 = 100 nF + R19/R21 各 1 k 构成一阶低通 fc ≈ 796 Hz,板端读数忠实、工频不受影响;谐波产品化需板改(模型与数据 `docs/硬件平台/ADC通道映射说明.md` §8.2,执行手册谐波记录 B 行);这两根轨归谁用,见 `docs/算法/继电保护功能复现规划.md` 的「遥测谐波轨(可选)」 |
| 保护判据 | 🔒 闭锁中 | §4.3 |
→ 两轮已按 **§4.6** 跑完(从**已验证过的那个注入点**灌正弦);六轮全部闭合(谐波 B 行超差已归因板端前端 RC,见 §2.7 谐波行;削顶 2 Hz 低频档与复位复核经用户裁定 2026-11-04 关闭,见 §2.7 削顶行与执行手册削顶卡步 3 行)。
→ 两轮已按 **§4.6** 跑完(从**已验证过的那个注入点**灌正弦);六轮全部闭合(谐波 B 行超差已归因板端前端 RC,削顶 2 Hz 低频档与复位复核经用户裁定 2026-11-04 关闭)。
---
@@ -177,14 +164,14 @@ M4 的六条退出判据(逐条对齐现状,别整格打勾):
| 退出判据 | 状态 | 证据 / 缺口 |
|---|---|---|
| ① 至少 1 路电压通道经已知电压注入验证,斜率与理论 LSB 偏差 ≤2 % | ✅ 2026-10-27 | UA 6544.2 vs 6553.6 码/V(−0.14 %),`docs/硬件平台/ADC通道映射说明.md` §8.1 |
| ② `adc_cal` 折算落地,采样环里是**引脚电压 V** 而非码值 | ✅ | `App/task/adc_task.c:382`(全仓唯一折算点) |
| ② `adc_cal` 折算落地,采样环里是**引脚电压 V** 而非码值 | ✅ | `App/task/adc_task.c:425`(全仓唯一折算点) |
| ③ 8 通道系数 / 零点可落盘,加载失败回退 ROM 默认 | ✅ | `[adc_cal]` / `[adc_cal_ofs]`,见 §4.4 |
| ④ 三处下游常数按工程量重定并注明依据 | ✅(有尾巴) | §2.3;#1 在 `eng=0` 恒失效已记因于 `freq.h:58-60` |
| ⑤ "未标定 → 保护闭锁"生效 | 🟡 软件道 ✅;**"解锁"这半程要等 `VALID` 置位**才能上台架验 | `adc_cal_prot_blocked()` + `App/task/protect_task.c:245` |
| ⑤ "未标定 → 保护闭锁"生效 | 🟡 软件道 ✅;**"解锁"这半程要等 `VALID` 置位**才能上台架验 | `adc_cal_prot_blocked()` + `App/task/protect_task.c:268` |
| ⑥ 量纲回归用例(不该动作时不动作)通过 | ✅ | `test/host/prot_dim/`,见 §2.2 |
**所以 M4 差的是"台架面",而且它分两半**:
**动态这半(§4.6)手边就能做、不要外部资源**;端子与精度那半要等子板与标准源(§5 后两张卡)。
**所以 M4 差的是"台架面",它分两半**:动态这半(§4.6)已于 2026-11-02 / 11-04 台架闭环;
端子与精度那半要等子板与标准源(§5 后两张卡)。
**M5 遥测链 / M6 运行参数与点表**:均已达成,口径沉淀在 `App/algo/meas.h`、`App/algo/run_par.h`
头注释与 §4.5;其中"104 上送值与**工程量**一致"仍挂在变比确认与两点标定上(注入验证只证到引脚电压口径)。
@@ -212,6 +199,9 @@ M4 的六条退出判据(逐条对齐现状,别整格打勾):
两者都占 4 字节,Q16 把"系数定点舍入"这一项从误差预算里直接抹掉。参考项目用 2^10 是因为定点 DSP
乘法成本,本机有 FPU、运行时本来就是 float。int32 上限可表达 32767 µV/码,远够。
- **运行时不走定点**:`k` 预乘成 `float k_f`,逐点只做一次浮点乘——1 kHz × 9 通道 = 9k 次/秒,可忽略。
- **系数合法带**:`adc_cal_set()` / `adc_cal_two_point()` 只接受落在板级 ROM 系数 ×[0.5, 2.0] 内的 `k`。
实测斜率与理论值偏差大时**先查前端**(分压 / 变比 / 焊接),不许用系数把硬件的错凑回来——
那等于把故障固化成"标定值"。零点越 ±`ADC_CAL_B_MAX` 同样直接拒绝(口径在 `App/algo/adc_cal.h`)。
### 4.2 三态可用性:标定 ≠ 可测
@@ -230,16 +220,16 @@ M4 的六条退出判据(逐条对齐现状,别整格打勾):
| TEMP | 0 | 0 | 不参与线性标定,页面显示 `--` |
`adc_cal_flags(sem)` 是三处(UI / 104 / 保护)唯一的可用性查询入口;`adc_cal_apply()` **不返回**可用性,
所以"只看系数不看 flags"这种用法在接口层就被堵掉(对应 §8 的"削顶通道被当成可测"一行)。
所以"只看系数不看 flags"这种用法在接口层就被堵掉(CLIPPED 通道恒报 IV 的单测见 `test/host/prot_dim/`)。
### 4.3 未标定即闭锁(本波唯一的行为变更)
保护判据拿"ADC 引脚电压"跟"二次值定值"比必然误动作,所以 `protect_task` 多一个闭锁源:
**UA / UN / IA 的 `VALID` 未全置位 → 判据停走**(实现已搬进 `App/algo/adc_cal.c` 的
`adc_cal_prot_blocked()`,`App/task/protect_task.c:268-273` 消费并打 INFO + 记 SOE)。
`adc_cal_prot_blocked()`,`App/task/protect_task.c:268` 消费并打 INFO + 记 SOE)。
- 与"自检失败 / 采样故障闭锁"同构(`PROT_HF_LOCK_MASK` 那一套),**不新增机制**。
- 现有台架 `/serial-boot-test` 的期望会因此变化——**这是有意的**,任务卡里同步更新判据。
- 台架 `/serial-boot-test` 的期望与未闭锁构建不同(判据已同步),这是有意为之。
- 台架调试要旁路只能走编译期开关 `DTU_BENCH`,不进 cfg、不进 104。
⚠ **`DTU_BENCH` 只旁路这一处**:它**不**旁路 §2.3 #1 的测频幅值门,也不产生任何新的读数通道。
@@ -256,9 +246,8 @@ M4 的六条退出判据(逐条对齐现状,别整格打勾):
- 系数唯一真源仍是这两段——104 写 k/b 经 `adc_cal_set()` 代理,`run_par` **不存第二份**;
落盘链走 `SYS_EVT_RUN_PAR_SAVE`(iec104Task peek 投递 → defaultTask 整档 save),`p_cb` 依旧未用。
- ⚠ **负零点**:引擎原本只有 `CFG_VAL_UINT`(`strtoul` + 上界校验),负的零点偏移会落成
`4294967291` 这种现场看不懂的数——**这就是补 `CFG_VAL_INT` 的动因**(§7 #3)。
备选"零点存码值 + 32768 偏置的 uint16"已否决:绕开引擎却要每个读点记住减偏置,属于给未来埋坑。
- ⚠ **负零点**:零点偏移是带符号量,引擎只有 `CFG_VAL_UINT`(`strtoul` + 上界校验)时 −5 会落成
`4294967291`。所以 `[adc_cal_ofs]` 走 `CFG_VAL_INT`(定案口径 §7 #3)。
### 4.5 遥测快照:让 104 与 UI 共用一份上游
@@ -279,12 +268,12 @@ typedef struct {
```
- **发布者 = `adc_task`**,在 `phasor_run()` / `freq_run()` 之后按 200 ms 分频发布;生产者在自己上下文里
发布,消费者不组装、不判断新旧。全仓 `meas_tick()` **调用点数 = 1** 是评审判据(§8"快照双写")。
发布,消费者不组装、不判断新旧。全仓 `meas_tick()` **调用点数 = 1** 是评审判据。
- **跨任务读沿用 `phasor` 的双区原子交换**(写侧填非使用区、末尾翻单字节索引;读侧先取索引再整体拷),
**不是新机制**、不引入锁。
- 104 与 UI 都读这份快照 → **同一份数据、两个消费者**;104 侧值与品质整体透传,不做本地判断。
- **200 ms 是上送节拍,不是平均窗**:相量本身已是 1 ms 刷新的基波有效值,再平均只会引入滞后。
⚠ 这条在动态验证里有个可读的后果:注入非整 50 Hz 的正弦时,快照轨会呈现拍频式跳动,**属预期**(§8)。
⚠ 这条在动态验证里有个可读的后果:注入非整 50 Hz 的正弦时,快照轨会呈现拍频式跳动,**属预期**。
### 4.6 动态波形验证:用信号发生器把整条计算链跑一遍
@@ -292,26 +281,22 @@ typedef struct {
![上排直流静态标定、下排交流正弦验证:同一个注入点、同一套前端,两种证法](../images/ADC直流标定与交流验证.svg)
#### 4.6.1 为什么这一跳既不用标准源、也不用烧高压
#### 4.6.1 范围与幅度上限
| 理由 | 依据 |
| 边界 | 口径 |
|---|---|
| 注入点已经验证过,且就在那儿 | `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3 的注入点清单(串联电阻端子侧 = `U5` 排针);③ 段 1:1 已拿到台架证据(§2.6) |
| **不知道 ④ 变比也能验算法** | 注入点在 ④ **之前**,发生器给的电压就是引脚电压,算法链要证的正是"引脚域里算得对不对" |
| 幅度小两个数量级 | 只需 ±2 V 以内的正弦(TPAFE 侧判据上限);端子二次值验证要上 100 V / 220 V,风险与设备都在那一级 |
| 现有静态验证的读数的地方可直接复用 | 串口心跳,零固件改动(§4.6.3) |
| 注入点 | `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3 的注入点清单(串联电阻端子侧 = `U5` 排针);③ 段 1:1 已拿到台架证据(§2.6) |
| 不知道 ④ 变比也能验 | 注入点在 ④ **之前**,发生器给的电压就是引脚电压,这一轮要证的正是"引脚域里算得对不对" |
| 幅度上限 | ±2 V 以内的正弦(TPAFE 侧判据上限);端子二次值验证要上 100 V / 220 V,风险与设备都在那一级 |
| 读数的地方 | 串口心跳,零固件改动(§4.6.3) |
**这一跳证的是功能性**(算得对不对、品质报得实不实、节拍稳不稳),**不是计量**(误差几级)——
发生器不当"标准"的界线见 §4.6.5 与 §7 #9。
**这一轮证的是功能性**(算得对不对、品质报得实不实、节拍稳不稳),**不是计量**(误差几级)——
发生器不当"标准"的界线见 §7 #9。
#### 4.6.2 判据(六轮:幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波)
> **分工**:本节定"验什么、过判据是多少";**期望值的算术、接法细节与执行步骤**在
> `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8(同一轮次的手册,两边于 2026-10-29 已对齐)。
>
> **轮次名一律用语义短语(用户裁定 2026-10-30:清退"字母+数字"判据号)**:D1 → 幅值轮、D2 → 波形轮、
> D3 → 相位轮、D4 → 测频轮、D5 → 削顶轮、D6 → 谐波轮;本族旧号作废不得再取走
> (与二极管位号、网络自愈决策记录、链路延迟缺陷编号只是同形,各不相干)。
> `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8。
>
> **注入幅度一律按峰峰值 Vpp 设定(用户裁定 2026-11-04)**:发生器面板的有效值显示不当设定基准
> (同一个 Vpp 换波形后有效值显示跟着变,切波形瞬间还残留上一波形的值);万用表 AC 档与板上读数
@@ -321,13 +306,10 @@ typedef struct {
|---|---|---|---|---|
| **幅值轮** | 基波幅值计量 | UA(R31 / `AIN1`)注 Vpp 2.828 V(= 峰值 ±1.414 V)、50.000 Hz 正弦 | `meas:` 的 `ua_mv` | 读数 = 万用表 AC 档读数,偏差 ≤2 %(与静态同档)。⚠ 别用 `phasor(hb)` 行比幅值——那是 ×0.1 定点,注 1 V 只剩 10 格(§4.6.3) |
| **波形轮** | 读数是否只跟基波走 | 同幅值改方波、三角 | 同上 | 期望值 = **基波分量有效值**(同峰值下的基波 / 峰值比:方波 ≈ **0.90**,闭式 4/π ÷ √2 = 0.900、20 点整周期 DFT 实算 0.904;三角 ≈ **0.573**,闭式 8/π² ÷ √2 = 0.573、实算 0.578),**不是**真有效值(方波 = 1.000、三角 = 0.583 峰值);偏差 ≤2 %。算术与逐波形对照表见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的波形卡。顺带把"这台仪表读的是基波"这条口径钉进文档——用户拿真有效值表去对会以为差了 10 % |
| **相位轮** | 相位 | UA 与 UN 两路**同片**(都走 TPAFE)注同幅、同相 | **录波档**:录波段文件 `test/host/wave_read.py fft`(浮点重算基波相位;段内表序 `UA` = 0、`UN` = 3);**心跳档**:`phasor(hb)` 各行 `Re=` / `Im=` | **录波档**:同段内两路相位差 ≤2°,把发生器相位改 90° 后差值跟到 ≈90°。**心跳档只判"跟随"**(差值落进 80°~100°)——`phasor` 串口行是 ×0.1 定点,Vpp 2.828 V(板上读数 ≈1000 mV)时每格 0.1 V,角度量化最坏 ≈ atan(0.1 / 0.707) ≈ 8°,判不动 2°(§4.6.3)。⚠ 段与发生器**无绝对相位锁定**(触发瞬间钉在段内点 159),只能比**同段内两路**的相对差,跨段比相位或拿发生器相位当绝对基准都不成立。**只许比同片内**——跨转换器无同刻性(§9),STM32 那五路还有 1 拍乒乓滞后 |
| **测频轮** | 测频 | 同幅值轮的 Vpp 2.828 V / 50 Hz | `freq(hb):` | **预期就是"不出数"**(幅值门 50 V 在引脚域恒不过,§2.3 #1)→ 这条的判据是"如实报不可测"(`freq_valid=0`、UI `Hz` 显示 `--`),**不是**报出一个错误的 50.00。想真验 45~55 Hz 精度(PC 侧判据 0.02 Hz)须临时把 `FREQ_AMP_MIN` 降到引脚域量级(如 0.5 V)单跑一轮 → §7 #8 + §8 风险行 |
| **削顶轮** | 削顶与品质路由(**负向用例**) | 给 UB(R52 / `AIN2`)注 **DC −1.00 V 并保持 ≥5 s**;或 Vpp 2.828 V 而频率 **2.0 Hz** 的正弦——两档都能造出"连续贴同一侧轨带"。⚠ **注 50 Hz 同幅正弦造不出锁存,且这是预期而非故障**:1 kHz 下一个周波只 20 点、正半周必落中带,而 `adc_health_rail_watch()` 任何一拍回中带就把计数清零(`App/algo/adc_health.c`),连续贴底最长 ≈ 209/360 × 20 ≈ 11 拍 < 20。TPAFE 侧在 ±2 V 判据上限内造不出这条(轨带 ±32112 码 ≈ ±4.9 V),只有 STM32 那五路能做 | `cal:` 行的 `rail=` / `edge=`;`rail: edge=…` 的 `[ERR]` 行;录波档另加 `wave_read.py shape` 的三把尺子(`--strict` / 再加 `--clip-superset` / 不带),逐条配法见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的削顶卡 | 负半周钉下轨 → **连续 20 拍同侧后该路贴轨位锁存**(`ADC_RAIL_N_RUN = 20`,`App/algo/adc_health.h:174`)、`edge` 起沿。锁存另有**释放沿前提**:该通道此前须出现过中带样本 → **先上电见基线摆动、再开发生器输出**,开机就注会测出假不通过。撤掉注入后 `rail` 仍非 0 是 sticky 语义(只有 `adc_health_rail_init()` / 复位清)——**复位后仍不清才是 bug**。⚠ 这条会**故意造出 `[ERR]`**,而 `/serial-boot-test` 的 forbidden 标记含 `[ERR]` → 人工判读、排在最后单独一轮(§8 第一行) |
| **谐波轮** | 谐波轨 | 基波 + 20 % 二次 + 20 % 五次(IA 上注)。⚠ 峰值预算:Vpp 2.828 V 基波 + 两个 20 % 分量的最坏对齐峰值 ≈ 1.98 V 已顶 ±2 V 红线 → 基波用 **Vpp 2.263 V**、二次与五次各 Vpp 0.453 V | **录波档**:段文件 `test/host/wave_read.py fft --ch 4 --all`(`IA` = 段内表序 4,直接给基波与 2 / 5 次谐波有效值,单位 mV);**旁证**:UI 交流量页 `Ia2` / `Ia5`(1 mV)与 `phasor(hb) C04-IA-F2` / `C05-IA-F5`(×0.1 定点,只证这根轨不是恒 0) | 谐波轨读数 = 注入分量(**±2 %,走录波档**;心跳档判不动:读数 0.160 V 在 ×0.1 串口行上只有 1~2 格)。⚠ 这两根轨**目前没有任何下游消费者**(`prot_elm.c` 无引用、`meas` 只算 `harm=1`),所以谐波轮只证"算得对",**不证"有人用"**——接到哪、给谁用,归 §9 的谐波轨立项 |
**先做幅值 / 波形 / 削顶三轮**(纯读数、无跨通道约定),相位 / 谐波次之,测频轮视 §7 #8 的裁定。每条的两档跑法(心跳档 /
录波档)与触发动作在 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.4–§8.5 的注入卡里(耗时排布与失败分诊两节已随 2026-11-04 轮次收尾删除,将来复跑照卡自行排程)。
| **相位轮** | 相位 | UA 与 UN 两路**同片**(都走 TPAFE)注同幅、同相 | **录波档**:录波段文件 `test/host/wave_read.py fft`(浮点重算基波相位;段内表序 `UA` = 0、`UN` = 3);**心跳档**:`phasor(hb)` 各行 `Re=` / `Im=` | **录波档**:同段内两路相位差 ≤2°,把发生器相位改 90° 后差值跟到 ≈90°。**心跳档只判"跟随"**(差值落进 80°~100°)——`phasor` 串口行是 ×0.1 定点,Vpp 2.828 V(板上读数 ≈1000 mV)时每格 0.1 V,角度量化最坏 ≈ atan(0.1 / 0.707) ≈ 8°,判不动 2°(§4.6.3)。⚠ 段与发生器**无绝对相位锁定**(触发瞬间钉在段内点 159),只能比**同段内两路**的相对差,跨段比相位或拿发生器相位当绝对基准都不成立。**只许比同片内**——跨转换器两片没有共同采样触发,比相位无意义(见 `docs/硬件平台/ADC通道映射说明.md` §7 通道归属行),STM32 那五路还有 1 拍乒乓滞后 |
| **测频轮** | 测频 | 同幅值轮的 Vpp 2.828 V / 50 Hz | `freq(hb):` | **预期就是"不出数"**(幅值门 50 V 在引脚域恒不过,§2.3 #1)→ 这条的判据是"如实报不可测"(`freq_valid=0`、UI `Hz` 显示 `--`),**不是**报出一个错误的 50.00。想真验 45~55 Hz 精度(PC 侧判据 0.02 Hz)须临时把 `FREQ_AMP_MIN` 降到引脚域量级(如 0.5 V)单跑一轮 → §7 #8 |
| **削顶轮** | 削顶与品质路由(**负向用例**) | 给 UB(R52 / `AIN2`)注 **DC −1.00 V 并保持 ≥5 s**;或 Vpp 2.828 V 而频率 **2.0 Hz** 的正弦——两档都能造出"连续贴同一侧轨带"。⚠ **注 50 Hz 同幅正弦造不出锁存,且这是预期而非故障**:1 kHz 下一个周波只 20 点、正半周必落中带,而 `adc_health_rail_watch()` 任何一拍回中带就把计数清零(`App/algo/adc_health.c`),连续贴底最长 ≈ 209/360 × 20 ≈ 11 拍 < 20。TPAFE 侧在 ±2 V 判据上限内造不出这条(轨带 ±32112 码 ≈ ±4.9 V),只有 STM32 那五路能做 | `cal:` 行的 `rail=` / `edge=`;`rail: edge=…` 的 `[ERR]` 行;录波档另加 `wave_read.py shape` 的三把尺子(`--strict` / 再加 `--clip-superset` / 不带),逐条配法见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8.5 的削顶卡 | 负半周钉下轨 → **连续 20 拍同侧后该路贴轨位锁存**(`ADC_RAIL_N_RUN = 20`,`App/algo/adc_health.h:174`)、`edge` 起沿。锁存另有**释放沿前提**:该通道此前须出现过中带样本 → **先上电见基线摆动、再开发生器输出**,开机就注会测出假不通过。撤掉注入后 `rail` 仍非 0 是 sticky 语义(只有 `adc_health_rail_init()` / 复位清)——**复位后仍不清才是 bug**。⚠ 这条会**故意造出 `[ERR]`**,而 `/serial-boot-test` 的 forbidden 标记含 `[ERR]` → 人工判读、排在最后单独一轮,且这一轮的结论不按 `/serial-boot-test` 判 |
| **谐波轮** | 谐波轨 | 基波 + 20 % 二次 + 20 % 五次(IA 上注)。⚠ 峰值预算:Vpp 2.828 V 基波 + 两个 20 % 分量的最坏对齐峰值 ≈ 1.98 V 已顶 ±2 V 红线 → 基波用 **Vpp 2.263 V**、二次与五次各 Vpp 0.453 V | **录波档**:段文件 `test/host/wave_read.py fft --ch 4 --all`(`IA` = 段内表序 4,直接给基波与 2 / 5 次谐波有效值,单位 mV);**旁证**:UI 交流量页 `Ia2` / `Ia5`(1 mV)与 `phasor(hb) C04-IA-F2` / `C05-IA-F5`(×0.1 定点,只证这根轨不是恒 0) | 谐波轨读数 = 注入分量(**±2 %,走录波档**;心跳档判不动:读数 0.160 V 在 ×0.1 串口行上只有 1~2 格)。⚠ 这两根轨**目前没有任何下游消费者**(`prot_elm.c` 无引用、`meas` 只算 `harm=1`),所以谐波轮只证"算得对",**不证"有人用"**——接到哪、给谁用,归 `docs/算法/继电保护功能复现规划.md` 的「遥测谐波轨(可选)」 |
#### 4.6.3 数字能从哪儿读(零固件改动)
@@ -335,79 +317,22 @@ typedef struct {
|---|---|---|
| 串口每 10 s 心跳(`App/task/adc_task.c` 心跳块) | `adc:`(9 路码值)、`cal:`(三路 mV + `vl`/`cl`/`rail`/`edge` 位图)、`phasor(hb)`(逐实例 `Re` / `Im` / `rms`)、`freq(hb)`、`meas:`(快照轨) | MicroLIB 无 `%f`,全是定点:`phasor` ×0.1(**1 V 注入只剩 10 格**)、`freq` ×0.01 Hz、`cal:` / `meas:` ×1000(1 mV)。10 s 一行的单点瞬时值对 50 Hz 等价于随机相位抽样 |
| UI 交流量页 | `Ua` / `U0` / `Ia` / `Ia2` / `Ia5` / `Hz` / 标定徽标 共 7 行 | 160×160 单色;`--` **同时**表示"没数"和"有数但不可信" → 不能当判据,只能当旁证 |
| **段文件(原始样本,代码侧已落地,2026-10-29)** | 每次触发一段:`/wave/WAVE00.BIN` 起共 100 个号轮转(FTP 根下可见),8 路 × 320 点原始码值加封存瞬间的标定与品质快照;PC 侧 `test/host/wave_read.py` 提供 dump / fft / shape / plot 四个子命令(bench 工具,纯标准库,自带 `--selftest`) | 「比对派生标量」已可升级成「PC 独立重算 vs 板上读数」对表(判据与执行步骤见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §4,格式属主见 `docs/子系统设计/故障录波设计说明.md` §6.2 与 §6.3)。**板级注入对表已随交流六轮跑过两轮**(2026-11-02 / 11-04,注 Vpp 2.828 V / 50 Hz、fft 与 `meas:` 互合,结论 `docs/硬件平台/ADC通道映射说明.md` §8.2;CRC 不符必须拒收的实测更早、2026-10-31 远程半轮已绿),余下板级判据(周波数 / 极性等逐项)见 `docs/子系统设计/故障录波设计说明.md` §10;示波器仍旧只作旁证、不当判据。段内点序:触发瞬间落在段内点 159(预触发 160 点的最后一点),段的绝对相位与发生器无锁定关系,可核对的是相对相位与极性 |
| **仍然没有的(2026-10-29 更新)** | 没有命令控制台、也没有「把窗里 20 / 40 个点导出来」的定点 dump 子命令——**但原始样本这条通道本身已成立**(上一行的段文件:一次 320 点 / 8 路,比原来规划的 20 / 40 点窗更宽) | 现场取回一律走现成 FTP(21 端口),形状就地看回放页单通道、或在 PC 侧用同一脚本出图;示波器只对照发生器、不当判据。**判据已升级为「PC 独立重算 vs 板上读数」对表**,对表的执行轮次待台架(见 `docs/子系统设计/故障录波设计说明.md` §11) |
#### 4.6.4 接法与红线(照抄既有红线,不新发明)
- 注入点:串联电阻的**端子侧**焊盘(`U5` 排针),逐路清单见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3;
引脚侧没有串阻保护,必须外串 **10 k** 限流。
- 幅度按**峰峰值 / 峰值**核,别看有效值数字:Vpp 2.828 V 正弦峰值已 ±1.414 V;TPAFE 侧按判据只到 **±2 V 峰值(= Vpp 4 V)**(满量程 ±5 V),
STM32 那五路是 **0~3.3 V 单极性**——给它们注交流只能是削顶轮那种"故意削顶"的用例,峰值同样不得超 3.3 V。
- 发生器与板**必须共地**(否则量到的是两地之间的差),且不形成地环:优先单点共地、必要时发生器浮地。
- **不许**因为"反正发生器便宜"就往端子侧上额定电压——那是 §5 第二张卡(要变比)与 §9(要标准源)的范围。
#### 4.6.5 这台发生器证不到什么(别让读数长得像证据)
| 证不到 | 为什么 | 归属 |
|---|---|---|
| 端子二次值 | 注入点在 ④ 之前,算出来还是引脚域 | §5「端子/子板变比确认」 |
| 精度等级(0.5 级 / 1 级) | 发生器自己的幅值误差本身就是要被校的量,不能冒充标准源 | §5「两点标定与精度验收」+ §7 #1 |
| 跨转换器相位 / 功率 / 对称分量 | 两片转换器无共同采样触发(V0.1 硬件缺陷)+ STM32 侧 1 拍乒乓滞后;量纲链路口径见通道映射说明的链路分段一节 | §9(本波不做矢量类运算) |
| THD / 谐波方和根 | 固件里只有两根谐波轨,没有合成后的数送出去 | §9(挂谐波轨立项) |
| 温升、EMC、长时间漂移 | 单轮台架不覆盖 | 送检与型式试验 |
---
| **段文件(原始样本)** | 每次触发一段:`/wave/WAVE00.BIN` 起共 100 个号轮转(FTP 根下可见),8 路 × 320 点原始码值加封存瞬间的标定与品质快照;PC 侧 `test/host/wave_read.py` 提供 dump / fft / shape / plot 四个子命令(bench 工具,纯标准库,自带 `--selftest`) | 判据是「PC 独立重算 vs 板上读数」对表(执行步骤见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §4,格式属主见 `docs/子系统设计/故障录波设计说明.md` §6.2 与 §6.3)。**板级注入对表已随交流六轮跑过两轮**(2026-11-02 / 11-04,注 Vpp 2.828 V / 50 Hz、fft 与 `meas:` 互合,结论 `docs/硬件平台/ADC通道映射说明.md` §8.2;CRC 不符必须拒收的判据也在 2026-10-31 远程半轮验过),余下板级判据(周波数 / 极性等逐项)见 `docs/子系统设计/故障录波设计说明.md` §10;示波器只作旁证、不当判据。段内点序:触发瞬间落在段内点 159(预触发 160 点的最后一点),段的绝对相位与发生器无锁定关系,可核对的是相对相位与极性 |
| **没有的** | 没有命令控制台,也没有「把窗里 20 / 40 个点导出来」的定点 dump 子命令——原始样本走上一行的段文件(一次 320 点 / 8 路) | 现场取回一律走现成 FTP(21 端口),形状就地看回放页单通道、或在 PC 侧用同一脚本出图 |
## 5. 任务卡(完成即销项删行;标识列用语义短语,不配编号)
> 资源图例:🔴 台架(COM3 / ST-LINK,`bench.lock` 独占)· 🟡 外部(标准源 / 子板原理图)· 🟢 纯软件。
> 状态:⬜ 未开始 · 🟦 进行中。**已闭环 = 直接删行**。
> 本表**只写判据**;执行步骤在 `docs/测试说明/专项验证/ADC前端注入验证流程.md`,实测结论在
> `docs/硬件平台/ADC通道映射说明.md` §8.1(动态实测结论开在其后)。
> `docs/硬件平台/ADC通道映射说明.md` §8.1(静态)与 §8.2(动态)。
| 标识(任务名)| DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|---|---|---|---|---|---|
| **信号发生器动态波形验证** | 按 §4.6.2 跑完六轮(测频轮允许以"如实报不可测"通过),逐条记实测 / 判据 / 结论;执行步骤与判据表**新增到** `docs/测试说明/专项验证/ADC前端注入验证流程.md`(直流节之后开一节"交流"),实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.1 之后新开一节;证据(串口日志 + 录波段文件)归档 `docs/测试说明/测试数据/boot_log_data/` | 静态注入闭环(✅ 2026-10-27)+ 一台能出 50 Hz 正弦、幅度可调到 Vpp 2.828 V 的交流信号发生器(**不需要标准源、不需要端子加压**) | 🔴 台架 + 手边发生器 | `docs/测试说明/`、`docs/硬件平台/` | ✅ **已验证(2026-11-02 / 11-04 两轮、六轮全部闭合;用户裁定 2026-11-04 打勾保留本行)**:实测已回填执行手册各轮记录表、结论新开 `docs/硬件平台/ADC通道映射说明.md` §8.2、证据已归档 `boot_log_data`。**未闭合项(均已裁定不做或另登记)**:① 谐波叠加工况(基波+二次+五次同段)未跑——发生器无谐波叠加/ARB 功能,属设备缺口;算法侧由 `test/host/phasor/phasor_test.c` TC-PHASOR-006 覆盖,待有谐波功能标准源复跑;② 削顶 2 Hz 低频档与 sticky 复位复核——用户裁定 2026-11-04 关闭;③ 测频"降幅值门证 0.02 Hz 测准"的改码档未做(现状档以如实报不可测通过);④ 谐波 B 行归因一阶低通模型(fc≈796 Hz)未做绝对仪器证伪(预测 250 Hz 额外滞后 ≈17°,示波器到手复核);谐波功能产品化需板改(C35 换小 + 清点各路容值),已登记 `docs/任务规划/登记簿.md` §3 |
| **信号发生器动态波形验证** | 按 §4.6.2 跑完六轮(测频轮允许以"如实报不可测"通过),逐条记实测 / 判据 / 结论;执行步骤与判据表在 `docs/测试说明/专项验证/ADC前端注入验证流程.md` 的交流节,实测结论在 `docs/硬件平台/ADC通道映射说明.md` §8.2;证据(串口日志 + 录波段文件)归档 `docs/测试说明/测试数据/boot_log_data/` | 静态注入闭环(✅ 2026-10-27)+ 一台能出 50 Hz 正弦、幅度可调到 Vpp 2.828 V 的交流信号发生器(**不需要标准源、不需要端子加压**) | 🔴 台架 + 手边发生器 | `docs/测试说明/`、`docs/硬件平台/` | ✅ **已验证(2026-11-02 / 11-04 两轮、六轮全部闭合)**:实测已回填执行手册各轮记录表、结论在 `docs/硬件平台/ADC通道映射说明.md` §8.2、证据已归档 `boot_log_data`。**未闭合项(均已裁定不做或另登记)**:① 谐波叠加工况(基波+二次+五次同段)未跑——发生器无谐波叠加/ARB 功能,属设备缺口;算法侧由 `test/host/phasor/phasor_test.c` TC-PHASOR-006 覆盖,待有谐波功能标准源复跑;② 削顶 2 Hz 低频档与 sticky 复位复核——用户裁定 2026-11-04 关闭;③ 测频"降幅值门证 0.02 Hz 测准"的改码档未做(现状档以如实报不可测通过);④ 谐波 B 行归因一阶低通模型(fc≈796 Hz)未做绝对仪器证伪(预测 250 Hz 额外滞后 ≈17°,示波器到手复核);谐波功能产品化需板改(C35 换小 + 清点各路容值),已登记 `docs/任务规划/登记簿.md` §3 |
| **端子/子板变比确认** | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 `docs/硬件平台/ADC通道映射说明.md`;据此判定 `eng` 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 | 已知电压注入验证(✅);**与动态验证无依赖关系**,可并行 | 🟡 子板实物或原理图 | `docs/硬件平台/` | ⬜ |
| **两点标定与精度验收** | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 `[adc_cal]` 并置 `VALID`;误差 ≤ 目标精度(待定:0.5 级 / 1 级 → §7 #1);证据归档 | 端子/子板变比确认;削顶五路的处置结论(削顶轮) | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/测试数据/boot_log_data/` | ⬜ |
**为什么把动态验证排在第一**(不是因为它最重要,而是因为它把后面两张卡踩实):
1. 它**不依赖任何外部资源**,而另两张卡都在等东西;等待期正好做它。
2. 它复用刚闭环的注入点与读数的地方,**边际成本几乎为零**。
3. 它会先把削顶轮那类"预期内的 `[ERR]`"暴露在台架规程里并写清判读,避免第二、三张卡跑到一半
才发现"自动化测试把这轮读成 FAIL"。
4. 它顺手把"发生器能证 / 不能证"的界线钉住,两点标定开跑时判据不会串档。
---
## 6. 并行与顺序
主干一条道,两处等外部资源(自环 = 等待),动态那一步不阻塞后面的卡:
```mermaid
flowchart TD
S([静态注入 2026-10-27 已闭环]) --> Q1{发生器在手?}
Q1 -- 否 --> W1[等待:发生器到位<br/>不动端子、不烧高压]
W1 --> Q1
Q1 -- 是 --> DYN[信号发生器动态波形验证<br/>幅值 · 波形 · 削顶 三轮先做]
DYN --> WB[回写:测试说明加「交流」一节<br/>通道映射补动态实测节]
WB --> Q2{变比到手?}
Q2 -- 否 --> W2[等待:子板实物或原理图]
W2 --> Q2
Q2 -- 是 --> CAL[两点标定与精度验收<br/>标准源 / 继保测试仪]
CAL --> V[电气 8 路 VALID 全置位]
V --> R[保护自动解卡<br/>闭锁 → 解锁台架验证]
R --> E([标准源送检 + 第三方 104 主站验收])
W1 -. 并行不阻塞 .-> ENG[eng 保持 0<br/>本波只承诺「ADC 引脚电压」]
ENG -.-> E
```
- **实测斜率偏差规则**:实测斜率与理论 LSB 偏差 >2 % 时**先查前端(分压 / 变比 / 焊接)再改系数**——
用系数凑斜率会把硬件的错固化成"标定值"。这条对动态同样成立(幅值轮偏差 >2 % 先查接线与共地)。
- 并行度规则见 `docs/环境与部署/并行任务工作树方案.md` §7.3。
---
## 7. 前置决策
@@ -419,64 +344,10 @@ flowchart TD
|---|---|---|---|---|
| 1 | **精度目标** | 0.5 级 / 1 级 | 决定两点标定的判据。**两点标定开跑前必须定**,否则"误差 ≤ 目标精度"这条 DoD 无法判定。保护判据本身只需 3~5 %,0.5 级是计量口径 | 🟡 开放 |
| 2 | **端子 / 子板变比从哪来** | ① 有子板原理图(直接算)② 只有子板实物(万用表同时量端子与引脚)③ 都没有 | 决定 `eng` 能否置 1。② 同样可行且够用;③ 则本波只交付"ADC 引脚电压",二次值登记为缺口 | 🟡 开放 |
| 3 | **`CFG_VAL_INT`(有符号零点)** | 补引擎值类型 / 零点改 uint16 + 32768 偏置 | 已定案:补值类型(`strtol` + `ERANGE` + 宽度上下界,`s_encode()` 带负号)。偏置方案否决理由见 §4.4 尾注 | ✅ 已定案 |
| 3 | **`CFG_VAL_INT`(有符号零点)** | 补引擎值类型 / 零点改 uint16 + 32768 偏置 | 已定案:补值类型(`strtol` + `ERANGE` + 宽度上下界,`s_encode()` 带负号) | ✅ 已定案 |
| 4 | 未标定即闭锁 | 保持闭锁 / 用万用表走捷径提前解锁 | 已定案:用户裁定 2026-10-25 **保持闭锁到标准源到位**,不缩短解锁路径 | ✅ 已定案 |
| 5 | 遥测快照发布权 | `adc_task` 分频发布 / 消费者各自计时组装 | 已定案:`adc_task` 唯一发布者(§4.5),调用点数 = 1 由评审守 | ✅ 已定案 |
| 6 | 温度是否纳入线性标定 | 纳入 / 不纳入 | 已定案:不纳入,`adc_cal_flags(TEMP)` 恒 0,页面 `--` | ✅ 已定案 |
| 7 | 注入层级与上限 | 引脚侧 / `U5` 排针端子侧 | 已定案:端子侧(③ 段的"端子侧"),≤2 V 直流——`U5` 排针是可安全接触的最低一级,引脚侧要拆子板 | ✅ 已定案 |
| 8 | **`eng = 0` 期间的测频幅值门怎么处置** | A 保持恒失效(现状,UI 恒 `--`)/ B 台架临时把 `FREQ_AMP_MIN` 降到引脚域量级跑一轮测频轮再还原 / C 换成"相对量"门限(如帧内最大值的一定时比例) | 建议 **A 为常态 + B 为一次性台架**,C 需要重新论证别在过渡期改。**跑之前先定**,还原由 §8 风险行盯 | 🟡 开放 |
| 8 | **`eng = 0` 期间的测频幅值门怎么处置** | 保持恒失效(现状,UI 恒 `--`)/ 台架临时把 `FREQ_AMP_MIN` 降到引脚域量级跑一轮测频轮再还原 / 换成"相对量"门限(如帧内最大值的一定时比例) | 建议**常态保持恒失效 + 需要时临时降门跑一轮**,换成相对量门限要先重新论证、别在过渡期改。**跑之前先定**;临时降门会改动产品头文件,收尾必须还原到 `git diff` 为空并重跑 `/keil-build` | 🟡 开放 |
| 9 | **动态验证的基准与发生器要求** | 万用表 AC 档 / 发生器自报刻度 / 借标准源 | 建议:以**万用表 AC 档为基准**,发生器只要求"波形干净、幅度稳定、频率能锁 50.000 Hz",**不拿它的刻度当精度**;判据档沿用静态 ±2 % | 🟡 开放 |
---
## 8. 风险
> 引用本表某一行时**写行名**(例:「削顶通道被当成可测」行),别写「末行 / 第 N 行」——本表会插行。
| 风险 | 触发条件 | 缓解 |
|---|---|---|
| **削顶负向用例被当成固件 bug** | 做削顶轮时 STM32 那五路必然钉下轨 → `rail: edge=…` 是 `[ERR]` 行,而 `/serial-boot-test` 的 forbidden 标记含 `[ERR]` → 整轮被判 FAIL | 判读规则写进流程文档:"做削顶轮的这一轮 `[ERR] rail:` 属预期,只人工判读、不计入 `/serial-boot-test` 结论",或把这五路排在最后单独一轮并事先声明。同时别忘 `cl=0xE6` 是**来源派生**(§2.6),不是本轮新削出来的 |
| **拿发生器的精度当标准用** | 用发生器自报的有效值数字当基准值去比 | 基准 = 万用表 AC 档实测(§7 #9);发生器只当"波形干净、频率可锁"的信号源,它自己的幅值误差正是要被校的量 |
| **临时改了 `FREQ_AMP_MIN` 忘了还原** | 走 §7 #8 的 B 方案 | 改动落在产品头文件里、会编进固件。单列一条收尾判据:还原后 `/keil-build` 0 错误 0 警告 + `git diff` 里 `App/algo/freq.h` 必须为空;并在 §7 #8 那行留一句"本轮台架已还原" |
| **峰值当成有效值,顶到量程外** | 只看面板有效值数字:正弦有效值 1.000 V = Vpp 2.828 V,峰值已 ±1.414 V | 接线前按**峰值**核一遍:TPAFE 侧 ≤±2 V、STM32 侧峰值必须 <3.3 V(且负半周本就钉轨,只作削顶轮用) |
| **发生器与板不共地 / 地环** | 两台设备各自接电网地 | 单点共地,必要时发生器浮地;读数漂或出现与幅度无关的偏置先查这里 |
| **非整 50 Hz 注入被当成 `meas` 抖动 bug** | 注 49.5 / 50.5 Hz | `meas` 是**瞬时基波有效值透传、200 ms 是上送节拍不是平均窗**(§4.5)→ 快照轨会有拍频式周期间跳动,属预期。测频腿要扫频时读 `freq(hb)`,别读 `meas:` |
| **`cfg` 键数顶格** | 后续给 `[adc_cal]` 加键 | 已按 8+1 / 8 拆段;加键前先看 `CFG_FILE_MAX_KEYS`,必要时再拆 |
| **标定值把保护"调坏"** | 两点标定写入错误系数 | `adc_cal_set()` 校验范围(`k` 必须在板级系数 ×[0.5, 2.0] 内)+ 写入后回读校验;越界拒绝并留 `[ERR]` |
| **削顶通道被当成可测** | 消费者只看 `k` 不看 `flags` | `adc_cal_flags()` 是唯一查询入口,`adc_cal_apply()` 不返回可用性;单测覆盖"CLIPPED 通道 104 恒 IV" |
| **快照双写** | 104 或 UI 侧也加一个 200 ms 计时器 | 设计约定"唯一发布者 = `adc_task`";评审时数 `meas_tick()` 调用点 = 1 |
| **加压烧板** | 变比未确认就往端子加额定电压 | **端子级上额定值必须在变比确认之后**,且先量"端子对地通断"确认无直流通路。动态验证只在 `U5` 排针侧 ≤±2 V 做,正就是为了绕开这条风险 |
---
## 9. 范围边界(本波不做)
| 不做 | 理由 / 归属 |
|---|---|
| THD / 谐波方和根真有效值、快照 4 点平均 | 挂 `docs/算法/继电保护功能复现规划.md` 的「遥测谐波轨(可选)」一起做;快照保持"基波有效值 + 直取相量"口径(§4.5) |
| **谐波轨被谁消费**(C04 / C05 目前无人消费) | 谐波轮只证"算得对";接线到判据或上送属谐波轨立项范围,本波不动 |
| 端子级额定电压、绝缘耐压、温升 | 要标准源 / 型式试验条件;本波所有注入都在 `U5` 排针侧 ±2 V 以内 |
| 录波(原始码值段文件) | **已交付代码面**(2026-10-29 立项并当日落地;判据属主 `docs/子系统设计/故障录波设计说明.md` §10,原卡片登记簿 2026-10-30 销项并入)本卡「动态波形验证」的原始样本**已**由录波段文件承担(§4.6.3 读数地点表已改),排序也随之调整(`docs/子系统设计/故障录波设计说明.md` §11);**没跑的是板级那一轮**(§10) |
| 104 文件传输(规约侧读文件) | 仍独立待排;现场与台架取回一律走现成 FTP(21 端口),规约侧文件服务等送检或第三方交接需求再议 |
| 等周波调频 | 与标定正交、无标准源时判据不可达,见 `docs/算法/继电保护功能复现规划.md` §3.1 |
| 功率 / 相位跨相比较 / 功率因数 / 对称分量 | **V0.1 硬件禁止**:跨转换器无同一时刻性,`docs/硬件平台/ADC通道映射说明.md` §7 通道归属行 |
| PT 断线判据 | 需要 `flags` 与遥信配合,而 V0.1 **无开入硬件** → 归开入波次 |
| 开入 / 开出固件 | 固件里**完全没有**这两类代码(`docs/问题记录/采集与数据处理短板评测.md` 登记),是另一个波次的量级 |
| 温度非线性折算 | §7 已定案行"温度不纳入线性标定" |
| 端子二次值(一次/二次变比换算) | **条件项**:变比确认拿到变比才做;拿不到则本波只到"ADC 引脚电压",`eng` 保持 0,缺口登记进 `docs/任务规划/登记簿.md` |
| UI 页面(含交流量回炉) | 归「UI 补齐」;本波只保证 `meas_snap_t` 与 `adc_cal_flags()` 可被其消费 |
---
## 10. 与其它工作的关系
| 工作 / 文档 | 关系 |
|---|---|
| **`docs/测试说明/专项验证/ADC前端注入验证流程.md`** | **执行步骤的属主**。本文只写"证到哪、判据是什么、为什么这么排";怎么接表笔、读哪一行、填哪张表一律在那篇里。动态验证的**步骤**同样落那篇(新开"交流"节),本文 §4.6 只留判据 |
| **通道映射说明** | `docs/硬件平台/ADC通道映射说明.md` §7.1(①②③④ 链路分段)与 §8.1(静态六项实测)是**量纲与实测记录的属主**;本文 §2.1 / §2.6 是它的**消费者**,不另立口径,动态实测结论也回写该文件 |
| **`docs/子系统设计/故障录波设计说明.md`** | 录波段文件是本卡「动态波形验证」的**原始样本来源**,数据面代码侧已落地(2026-10-29:环与段格式在 `App/algo/wave_ring.c` / `App/algo/wave_store.c`,PC 侧 `test/host/wave_read.py`);判据从「比对派生标量」升级为「PC 独立重算 vs 板上读数」对表的**执行轮次待台架**,动态验证的排序已因此让位给录波数据面(用户裁定 2026-10-29,理由与三处口径变更见 docs/子系统设计/故障录波设计说明.md §11) |
| **`docs/算法/采集与算法层设计说明.md`** | 算法与判据正文(全周傅氏、测频、保护元件);本文只规定"这些算法的信度到什么程度" |
| **`docs/子系统设计/IEC104上行设计说明.md`** | 104 上行协议本体(点表 `0x4011`~`0x4018` + `0x401D`、品质位绑定)——送检与验收的参照;**不是本验证轮的读数通道**;送检验收索引在 `docs/任务规划/登记簿.md` §7 |
| **送检验收** | 标准源送检依赖本文「两点标定与精度验收」;顺序不可倒(先变比 → 再标定 → 才解卡 → 才送检,§6) |
| **UI 补齐** | 已交付的 `meas_snap_t` + `adc_cal_flags()` 供 `ui_data_rt_t` 填 `eng`:现为 0 = 引脚电压,变比确认拿到变比后才升 1 = 二次值。**UI 不必等本文任何一张卡** |
| **双转换器无共同采样触发(V0.2 硬件改版)** | 本波的 `CLIPPED` 位就是这条硬件缺陷在软件里的可见形态;V0.2 改版后该位恒 0,页面与 104 绑定零改动 |
@@ -47,10 +47,10 @@ dhara 失败类 +84;RO 另 +208,全是该失败类名表)→ `ER_IROM1`
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 |
|---|---|---|---|
| ER_IROM1 | 285,716 B (279.02 KB) | 1,048,576 B (1024 KB) | 27.2% |
| ER_IROM1 | 285,156 B (278.47 KB) | 1,048,576 B (1024 KB) | 27.2% |
| RW_IRAM1 | 94,752 B (92.53 KB) | 131,072 B (128 KB) | 72.3% |
| RW_CCM | 57,376 B (56.03 KB) | 65,280 B (64 KB) | 87.9% |
| **Flash (ROM 合计)** | **287,788 B (281.0 KB)** | 1,048,576 B (1024 KB) | **27.4%** |
| **Flash (ROM 合计)** | **287,228 B (280.5 KB)** | 1,048,576 B (1024 KB) | **27.4%** |
<!-- MEM_SNAPSHOT:END -->
各区的容量与常量来源:
+1 -1
View File
@@ -15,7 +15,7 @@
<!-- MEM_BUDGET:BEGIN generated by scripts/ram_baseline.py -->
| 区域 | 用量 | 容量 | 占比 | 门禁(≤92%) |
|---|---|---|---|---|
| ER_IROM1 (Flash) | 285,716 B | 1,048,576 B | 27.2% | 参考 |
| ER_IROM1 (Flash) | 285,156 B | 1,048,576 B | 27.2% | 参考 |
| RW_CCM | 57,376 B | 65,280 B | 87.9% | PASS |
| UNINIT_CCM | 48 B | 256 B | 18.8% | 参考 |
| RW_IRAM1 | 94,752 B | 131,072 B | 72.3% | PASS |
@@ -49,7 +49,8 @@
折算层 2026-10-25 落地;二次值等两点标定置 VALID)。槽位值/品质整体透传,本层
**不再自行判新旧**(快照 `seq` 仅供 COV 去重)。
- 品质映射:快照 `MEAS_QDS_*` 低字节与线上 QDS 同值直传;**CLIPPED → IV**(「削顶通道
恒 IV」口径不变、改由品质驱动,docs/任务规划/数据可信.md §8 风险表「削顶通道被当成可测」行的单测要求);
恒 IV」口径不变、改由品质驱动,`docs/任务规划/数据可信.md` §4.2 三态可用性表 +
`test/host/prot_dim/` 的「CLIPPED 通道恒 IV」单测);
快照从未发布(开机 <200 ms)→ IV|NT;判定顺序 IV 优先于 NT。
- 死区(104 改读快照):从「越死区即报」改为**连续 2 个新测量点越限才确认**——板端测量点 =
快照换帧(100 ms 轮询 vs 200 ms 快照按 `seq` 去重,防同一帧把单点噪声重复计满 2 点;
@@ -233,7 +233,7 @@ flowchart TD
1. `flags_seq` 的 V0.1 真值一度被写成 `0x27`:那是把「按来源派生的 CLIPPED」当成了 VALID。按 `App/algo/adc_cal.c` 280 到 298 行,未标定态就是 `0x00`(见上面真值表第一行)。凡引用这个数字的地方一律以真值表为准。
2. 一版互验夹具写成 `eng` = 0 而 `flags_seq` = `0xFF`——违反上面的 eng 派生式,是一串**真机写不出来**的字节。已改为按派生式自洽,并在 `test/host/wave_store` 那套单测里加了夹具自洽断言防复发。教训一句话:**互验夹具的资格来自「真机能写出这串字节」**,一份不可能状态的字节只能验证两个读者对幻觉的一致反应,正好掩盖真分歧。
3. 顺带钉一条因果,免得后文写反:PC 侧早期一次 `shape` 子命令在 `--strict` 下 rc=1,与品质位**无关**,那是「实测触轨路数 vs 段头 `clip_mask`」对表不符(合成夹具的波形本来就没真触轨)。那条对表是 `docs/任务规划/数据可信.md` §4.6 与本文 §10 板级判据的本职,不是解码器的判废扩展。
3. 顺带钉一条因果,免得后文写反:PC 侧早期一次 `shape` 子命令在 `--strict` 下 rc=1,与品质位**无关**,那是「实测触轨路数 vs 段头 `clip_mask`」对表不符(合成夹具的波形本来就没真触轨)。那条对表是 `docs/任务规划/数据可信.md` §4.6.2 削顶轮与 `docs/子系统设计/故障录波设计说明.md` §10 板级判据的本职,不是解码器的判废扩展。
---
@@ -459,7 +459,7 @@ bench 锁全程持有;三次烧录(埋点 / 诊断加强 / 根因修复)
| 风险 | 后果 | 处置 |
|---|---|---|
| 削顶五路被读成「系统有零序 / 有谐波」 | 现场误判 | 头里 `clip_mask` + 页面「削」徽标 + 空态不许画直线(§8.1) |
| 有人把 U 与 I 两段叠图比相位 | 得出**没有物理意义**的相位差 | 回放不做多路叠加;头里写明来源转换器;与 `docs/任务规划/数据可信.md` §9 的 V0.1 禁止行同源 |
| 有人把 U 与 I 两段叠图比相位 | 得出**没有物理意义**的相位差 | 回放不做多路叠加;头里写明来源转换器;与 `docs/硬件平台/ADC通道映射说明.md` §7 通道归属行的 V0.1 禁止行同源 |
| 落盘把 defaultTask 拖住 | 日志与配置引擎变慢(defaultTask 是两者唯一写者) | 分次写(256 B 双缓冲)、一次心跳最多一段、`f_write` 前后有耗时观测;不做整段驻留再写 |
| **回放读路径把 uiTask 拖住**(2026-10-29 lead 评审补,此前风险表只有写侧没有读侧) | 一次渲染的实码 I/O(`App/task/ui_task.c` 376 到 398 行):段表刷新 1 次 `f_opendir` + 至多 100 次 `f_readdir`;未缓存段的段头装载 = 1 次 `f_open` + 1 次 128 B 头读 + **20 次 256 B 数据区读并边读边算数据 CRC** + 尾 2 B 一次 = **最坏 22 次小读**;已验过则只剩窗装载 = 1 次 `f_open` + 1 次 `f_lseek` + 1 次 80 B 窗读 + 40 点解码与峰值扫描(**一屏只碰一路通道一个窗,不是 8 路 320 点**)。uiTask 在 IWDG `required_mask` 内、窗 800 ms(口径同 `docs/子系统设计/看门狗设计说明.md` §11.3 的解耦心跳)→ **现象先是 LVGL 停摆与远程推流缺席,不是复位**(心跳与画屏解耦) | 卷锁 try 非阻塞(拿不到就显示「存储忙」,不等)+ 256 B 分次读 + 已验段结果缓存(同段同道不重复验)+ 只在首次进页 / 切段 / 切道时读。**单轮耗时上界未实测**:不新加埋点,用现成的 `task_prof` 读数(板级动作见 §10) |
| 触发风暴 + 轮转覆盖 | 现场唯一一段有效波形被后到的抖动冲掉 | 冷却期 + `ovf` 计数;「最新段号」进快照;分段优先级属二期 |
@@ -1,6 +1,6 @@
# ADC 前端注入验证流程(台架)
> **这篇是什么**:已知电压注入验证的**执行侧**——怎么写表笔、读哪行日志、填哪张表、结果往哪回写。判据与实测记录在属主文档:直流轮 `docs/硬件平台/ADC通道映射说明.md` §8.1、交流轮 `docs/任务规划/数据可信.md` §4.6.2;**本文只写怎么跑**,分叉时判据从属主。证不到什么见 `docs/任务规划/数据可信.md` §4.6.1 与 §4.6.5,本文不重抄。
> **这篇是什么**:已知电压注入验证的**执行侧**——怎么写表笔、读哪行日志、填哪张表、结果往哪回写。判据与实测记录在属主文档:直流轮 `docs/硬件平台/ADC通道映射说明.md` §8.1、交流轮 `docs/任务规划/数据可信.md` §4.6.2;**本文只写怎么跑**,分叉时判据从属主。证不到什么见 `docs/硬件平台/ADC通道映射说明.md` 的 §8.1 结论与「边界」段,本文不重抄。
>
> **两个轮次**:§1~§7 = **直流轮次**(2026-10-27 六项 PASS,只需万用表 + 电位器 + 串口日志);§8 = **交流轮次**(幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波),一台信号发生器接 §3 同一批注入点就能跑,等标准源的只有**精度等级**。V0.1 五路单极性削顶(`UB/UC/IB/IC/IN`)在交流轮次只作"预期削顶"负向用例。
@@ -353,7 +353,7 @@ TPAFE 双极性补码可注负压;STM32 单极性负半周测不了。UA/UN/IA
| 期望(现状固件) | **就是不出数**:幅值门 `FREQ_AMP_MIN 50.0f`(`App/algo/freq.h:62`,`App/algo/freq.c:231` 拿它与基波有效值比)在引脚电压域恒不过 → `valid=0`、`f=0`、UI `Hz` 显 `--` |
| 判据 | **如实报不可测**,而不是报一个看起来对的 50.00。若门限没改却报出 50.00 → 反而是 bug,停下查 `App/algo/freq.c` |
| 另有一档(需先取得同意) | 临时把 `FREQ_AMP_MIN` 由 `50.0f` 降到 `0.5f` → 重编(`/keil-build`,要 build 锁)+ 重烧 → 扫 45.000 / 50.000 / 55.000 Hz 三点,PC 侧判据 0.02 Hz → 跑完**必须还原**(撤销补丁 + 重编 + 重烧,`git diff` 核对干净)。这一档要改固件重烧,动它之前先问过你;不做也不影响上面那条判据成立 |
| 坑 | 非整 50 Hz 时 `meas:` 拍频式跳动属预期 → **扫频读 `freq(hb)` 别读 `meas:`**(`docs/任务规划/数据可信.md` §8 同一条);取源先 `UA`(C02)再退 `IA`(C01)(`App/algo/freq.c:47`)——注 `UA` 走 UA 源;若只注 `IA`,测频跟 IA 走 |
| 坑 | 非整 50 Hz 时 `meas:` 拍频式跳动属预期 → **扫频读 `freq(hb)` 别读 `meas:`**(`docs/任务规划/数据可信.md` §4.5:200 ms 是上送节拍不是平均窗);取源先 `UA`(C02)再退 `IA`(C01)(`App/algo/freq.c:47`)——注 `UA` 走 UA 源;若只注 `IA`,测频跟 IA 走 |
记录表:
@@ -401,7 +401,7 @@ TPAFE 双极性补码可注负压;STM32 单极性负半周测不了。UA/UN/IA
| 期望与判据 | 板上读数(有效值刻度)≈ 各分量 0.160 V(对应设定 Vpp 0.453 V)±2 % |
| 旁证 | `phasor(hb) C04-IA-F2`/`C05-IA-F5` 的 `rms=`:×0.1 只 1~2 格,**只能证"该轨非恒 0"**,判不了 ±2 %(§8.1) |
| 无谐波叠加功能时 | 三次单注:只注 Vpp 0.453 V / 100 Hz → `Ia2` 有数(读数 ≈0.160 V)、`Ia5` 应 ≈0;只注 Vpp 0.453 V / 250 Hz → `Ia5` 有数、`Ia2` 应 ≈0;再注纯基波 Vpp 2.263 V → 两轨都 ≈0。这一档证"两轨各认各的次",**不证叠加工况**,结论里写清 |
| 口径 | 这两轨**当前无下游消费者**(`App/algo/prot_elm.c` 无引用、`meas` 只算基波)→ 谐波轮只证"算得对",不证"有人用";这两轨归谁用,见 `docs/任务规划/数据可信.md` §9 谐波轨立项 |
| 口径 | 这两轨**当前无下游消费者**(`App/algo/prot_elm.c` 无引用、`meas` 只算基波)→ 谐波轮只证"算得对",不证"有人用";这两轨归谁用,见 `docs/算法/继电保护功能复现规划.md` 的「遥测谐波轨(可选)」 |
记录表:
@@ -420,4 +420,4 @@ TPAFE 双极性补码可注负压;STM32 单极性负半周测不了。UA/UN/IA
& '.venv\Scripts\python.exe' test/host/wave_read.py fft WAVE<NN>.BIN --ch 4 --all
```
`fft` 每整周波给基波与 2 次/5 次谐波有效值(mV,浮点重算),±2 % 是定量判据;`--ch` = 段内通道表序,`IA` = 4(`UA UB UC UN IA IB IC IN`,TEMP 不录,`App/algo/wave_ring.h:216`)。UI 目检只是**旁证**(证"板上与脚本算的是同一个东西"),不是替代判据。THD 与根均方不在本轮(`docs/任务规划/数据可信.md` §4.6.5)。
`fft` 每整周波给基波与 2 次/5 次谐波有效值(mV,浮点重算),±2 % 是定量判据;`--ch` = 段内通道表序,`IA` = 4(`UA UB UC UN IA IB IC IN`,TEMP 不录,`App/algo/wave_ring.h:216`)。UI 目检只是**旁证**(证"板上与脚本算的是同一个东西"),不是替代判据。THD 与根均方不在本轮(谐波轨要做 THD 归 `docs/算法/继电保护功能复现规划.md` 的「遥测谐波轨(可选)」)。
+57 -118
View File
@@ -2,11 +2,11 @@
> **一句话结论**:V0.1 共 **17 路**模拟采样——**8 路进 TPAFE5160**(16 位、8 通道同步、**±5 V 满量程 = 10 V 跨度**、LSB ≈ 152.59 µV,板上 RANGE 接 GND,口径见 §7.1)、**9 路进 STM32 内部 ADC**(12 位、顺序采样、0~3.3 V 单极性)。网名 `AINn`、板级网名 `ADCn`、转换器通道号**三套编号互不等价**(V0.1 有 13/17 路被置换),任何代码 / UI 显示 / 自检注入**必须以本表为准,不得假设 `AINn = ADCn`**。
>
> 语义分配由硬件于 **2026-10-09** 确认;网名与电阻对应关系取自 [`V0.1.tel`](V0.1.tel)(第 227~262 行),引脚号取自数据手册 LQFP144 引脚表([`../芯片手册/stm32f405rg.md`](../芯片手册/stm32f405rg.md))。
> 网名与电阻对应关系取自 [`V0.1.tel`](V0.1.tel)(第 227~262 行),引脚号取自 [`../芯片手册/stm32f405rg.md`](../芯片手册/stm32f405rg.md) 的 LQFP144 引脚表。
---
## 1. 语义分配(2026-10-09 硬件确认)
## 1. 语义分配
| 语义 | 网名 | 类别 | 说明 |
|---|---|---|---|
@@ -21,21 +21,21 @@
| **温度** | V_ZL2 | 温度 | 温度检测模拟采样 |
| 备用 | AIN5 / AIN6 / AIN7 / AIN12 / AIN13 / AIN14 / AIN15 / V_ZL1 | — | **未使用**(悬空或不用),软件侧一律标 `RESERVED`,不参与采集与上报 |
**设计口径(重要,2026-10-10 更正)**:本产品的**电能计量在子板(计量模块)完成**,主板 ADC 只做**监视 / 辅助测量**。但**"8 路电气量被分到两片转换器上"(UA/UN/IA 走 TPAFE5160,UB/UC/IB/IC/IN 走 STM32 12 位 ADC)是 V0.1 的硬件缺陷**——建档时(2026-10-09)写的"有意分配、不要按'8 路电气量应全部走 TPAFE'去修正"**说法作废**:该分配**就是需要修正的对象**,已列入下一版硬件(V0.2)改版项(登记簿条目「双转换器无共同采样触发」)。
**设计口径**:本产品的**电能计量在子板(计量模块)完成**,主板 ADC 只做**监视 / 辅助测量**。
**缺陷实质(为什么必须改)**:
**V0.1 硬件缺陷**:8 路电气量被分到两片转换器上——UA/UN/IA 走 TPAFE5160,UB/UC/IB/IC/IN 走 STM32 12 位 ADC。后果三条:
1. **跨转换器通道没有同一时刻性**:TPAFE5160 是 8 通道**同步**采样,STM32 ADC 是**顺序**扫描(9 通道一轮 ≈ 67 µs),且两片转换器**没有共同采样触发**(CONVST 只打 TPAFE;ADC1 由 TIM3 TRGO 触发——见 §7 与 `Src/adc.c:53`,但 TIM3 与 TPAFE 的 CONVST 之间没有硬件耦合,仍不构成「共同采样触发」)。于是 UA↔UB、IA↔IB 这类同族量之间**相位关系不确定**,主板侧任何功率 / 功率因数 / 相角 / 对称分量类运算都不成立。
2. **精度与量程不一致**:TPAFE 16 位 ±5 V **双极性**(LSB ≈ 152.6 µV,满量程 = 10 V 跨度,口径见 §7.1)vs STM32 12 位 0~3.3 V **单极性**(前端无中点偏置,交流量负半周削顶;LSB ≈ 806 µV)。同为相电压,UA 与 UB/UC 满量程码值差 16 倍、可用象限也不同——同一套算法无法统一处理 8 路电气量。
3. **语义与硬件归属交叉**:UA 在 TPAFE、UB 在 STM32,固件映射表 / UI 通道序 / 自检注入都必须逐通道查表绕开这个交叉(本文件 §4、§5 两张表的存在本身就是代价)。
1. **跨转换器没有同一时刻性**:TPAFE5160 是 8 通道**同步**采样,STM32 ADC 是**顺序**扫描(9 通道一轮 ≈ 67 µs),两片**没有共同采样触发**(CONVST 只打 TPAFE,ADC1 由 TIM3 TRGO 触发,见 §7 与 `Src/adc.c:53`)。UA↔UB、IA↔IB 这类同族量之间的**相位关系不确定**,主板侧任何功率 / 功率因数 / 相角 / 对称分量类运算都不成立。
2. **精度与量程不一致**:TPAFE 16 位 ±5 V **双极性**(LSB ≈ 152.6 µV,满量程 10 V 跨度,见 §7.1)vs STM32 12 位 0~3.3 V **单极性**(前端无中点偏置,交流量负半周削顶,LSB ≈ 806 µV)。同为相电压,UA 与 UB/UC 满量程码值差 16 倍、可用象限也不同。
3. **语义与硬件归属交叉**:UA 在 TPAFE、UB 在 STM32,固件映射表 / UI 通道序 / 自检注入都必须逐通道查表(本文件 §4、§5 两张表即为此)。
**下一版硬件(V0.2)改版要求**:**8 路电气量 UA/UB/UC/UN/IA/IB/IC/IN 全部接到 TPAFE5160 的 8 个通道**,备用路与温度(V_ZL2)留给 STM32 ADC。TPAFE 现被 5 条备用路占着(`AIN5`/`AIN13`/`AIN7`/`AIN15`/`AIN12` → ADC1/ADC2/ADC4/ADC5/ADC8),与要迁过来的 5 路(UB/UC/IB/IC/IN)**正好 5 换 5**:只需把这 5 路串联电阻在转换器一侧的目的地对调,**元件数量与料号不变,属走线级改动**。改版后本表 §3 的"转换器 / 代码通道"两列须按 V0.2 网表重出——这也是消费侧**必须按语义取数、不得写死下标**的原因。
**V0.2 改版要求**:**8 路电气量 UA/UB/UC/UN/IA/IB/IC/IN 全部接到 TPAFE5160 的 8 个通道**,备用路与温度(V_ZL2)留给 STM32 ADC。TPAFE 现占着 5 条备用路(`AIN5`/`AIN13`/`AIN7`/`AIN15`/`AIN12` → ADC1/ADC2/ADC4/ADC5/ADC8),与要迁过来的 5 路(UB/UC/IB/IC/IN)**正好 5 换 5**:只需把这 5 路串联电阻在转换器一侧的目的地对调,**元件数量与料号不变,属走线级改动**。改版后 §3 的"转换器 / 代码通道"两列按 V0.2 网表重出(登记簿条目「双转换器无共同采样触发」)——这也是消费侧**必须按语义取数、不得写死下标**的原因。
**V0.1 现板的软件口径**:主板侧只做**逐通道独立监视**(有效值 / 越限 / 温度),**禁止**做跨转换器的同周期相位、功率、功率因数、矢量类运算;确需此类量,取子板计量模块的结果。
**V0.1 现板的软件口径**:主板侧只做**逐通道独立监视**(有效值 / 越限 / 温度),**禁止**跨转换器的同周期相位、功率、功率因数、矢量类运算;确需此类量,取子板计量模块的结果。
---
## 2. 三套编号,别混
## 2. 三套编号互不等价
| 编号族 | 含义 | 出现位置 |
|---|---|---|
@@ -43,7 +43,7 @@
| `ADCn`(n=1~17) | **主板 ADC 输入网名**:电阻另一侧、滤波电容、转换器输入脚 | 电阻 → 滤波器 → U3 / U17 |
| 转换器通道号 | 软件真正要用的编号:TPAFE `ch1~ch8`(= 驱动 `buf[0..7]`)/ STM32 `ADC_CHANNEL_x` | 固件、UI、自检 |
V0.1 相对 V0.0 把 `AINn ↔ ADCn` 的电阻对应关系置换了 13 路(见 [`V0.1_网表详细分析报告.md`](V0.1_网表详细分析报告.md) §6),所以**网名编号完全不能当通道号用**(例:`AIN1`(UA) 实际落在 TPAFE 第 7 通道)。
`AINn ↔ ADCn` 的电阻对应关系有 13 路被置换了(见 [`V0.1_网表详细分析报告.md`](V0.1_网表详细分析报告.md) §6),所以**网名编号完全不能当通道号用**(例:`AIN1`(UA) 实际落在 TPAFE 第 7 通道)。
---
@@ -78,7 +78,7 @@ STM32(U17)为 LQFP144 脚号。
## 4. TPAFE 侧:读出顺序 → 驱动缓冲区下标
`tpafe5160_read_all()` / EXTI 自动读取按 RD 时序连续读 8 次,`FRSTDATA` 标记第一通道,故 **`buf[0..7]` = `ADC1..ADC8` 网名 = TPAFE `ch1..ch8`**:
驱动按 RD 时序连续读 8 次、`FRSTDATA` 标记第一通道,`tpafe5160_snapshot()` 交出的 **`buf[0..7]` = `ADC1..ADC8` 网名 = TPAFE `ch1..ch8`**:
| `buf[i]` | 板级网名 | TPAFE 通道 | 语义 |
|---|---|---|---|
@@ -109,95 +109,59 @@ STM32(U17)为 LQFP144 脚号。
| ADC16 | 43 | PA7 | `ADC_CHANNEL_7` | RESERVED(V_ZL1) |
| **ADC17** | **44** | **PC4** | **`ADC_CHANNEL_14`** | **UB** |
> ⚠️ **`ADC17` 网名 ≠ `ADC_CHANNEL_17`**。PC4 在 F407 上是 `ADC123_IN14`,代码必须写 `ADC_CHANNEL_14`;`ADC_CHANNEL_12` 是 **PC2(pin 30)**,写错就读到另一只脚。
**CubeMX 侧标签(2026-10-09 已写入 `STM32F407-Demo.ioc` 并生成代码,格式 `板级网名_语义`)**:`ADC9_RES` / `ADC10_IC` / `ADC11_IN` / `ADC12_UC` / `ADC13_RES` / `ADC14_TEMP` / `ADC15_IB` / `ADC16_RES` / `ADC17_UB`(9 脚已配到 ADC1 的 IN0..IN7 + IN14,生成代码里对应 `main.h` 的 `ADC9_RES_Pin`…`ADC17_UB_Pin`)。⚠ PA0 标签首次配置时误写成 `AD9_RES`(少个 C),已改回 `ADC9_RES`(`.ioc` + `Inc/main.h` + `Src/adc.c` 三处同步)。
**引脚可用性核查(2026-10-09)**:`STM32F407-Demo.ioc` 中 PA0~PA7、PC4 **此前均未分配**(PC5 = LED1,与 ADC 无关)→ 这 9 路做模拟输入无冲突,现已配给 ADC1。PA4/PA5 兼 `DAC_OUT1/2`,作模拟输入期间须保持 DAC 关闭(当前固件未启用 DAC ✓);PA4/PA5/PA6/PA7 的 SPI1 复用未使用(SPI1 走 PB3/PB4/PB5)✓。
---
## 6. 对既有文档的勘误(2026-10-09,依据 DS8626 引脚表)
1. **PC4 的通道号**:`docs/硬件平台/V0.1_网表详细分析报告.md` §4.6 / §9-3 / §11 与 `docs/硬件平台/V0.0_网表详细分析报告.md` B5 处写的 "PC4 = `ADC12_IN12`、代码用 `ADC_CHANNEL_12`" **有误**——DS8626 引脚表:PC4 = LQFP144 pin 44,附加功能 **`ADC12_IN14`**;`ADC_CHANNEL_12` 对应 **PC2(pin 30)**。正确写法:**`ADC_CHANNEL_14`**。
2. **"PB0 非 ADC 输入脚" 不成立**:PB0 = LQFP144 pin 46 = **`ADC12_IN8`**(PB1 = pin 47 = `ADC12_IN9`)。所以 V0.0 把 `ADC17` 接 pin 46(PB0)**电气上是有效通道**,并非"死通道"。V0.1 改到 pin 44(PC4)的**实际收益是解除与 LED2(PB0)的复用**,不是"救活无效通道"——V0.0 报告 B5 的定性需按此理解。
---
## 7. 实现注意事项(当前固件现状,2026-10-10)
## 7. 实现注意事项
| 项 | 现状 | 影响 |
|---|---|---|
| **通道归属(硬件缺陷)** | 8 路电气量分属两片转换器:UA/UN/IA → TPAFE,UB/UC/IB/IC/IN → STM32 ADC | **V0.1 硬件缺陷**(非有意分配,理由见 §1)→ V0.1 上禁止跨转换器做相位/功率/功率因数/矢量类运算;**V0.2 改版要求 8 路电气量全部走 TPAFE**(登记簿条目「双转换器无共同采样触发」) |
| STM32 ADC 外设 | **已生成(2026-10-09,CubeMX 6.17 + FW_F4)**:`Src/adc.c`/`Inc/adc.h` 已入库并挂进 `MDK-ARM/*.uvprojx`;`Inc/stm32f4xx_hal_conf.h` 的 `HAL_ADC_MODULE_ENABLED` 已生效;HAL `stm32f4xx_hal_adc.c/_ex.c` + `stm32f4xx_ll_adc.h` 已补入仓库(HAL 原本是裁剪子集);`Src/main.c` 里 `MX_ADC1_Init()` 排在 `MX_IWDG_Init()` 之后。生成配置核对无误:9 通道 / Rank 1~9 / 全部 144 cycles / `ScanConvMode=ENABLE` / `ContinuousConvMode=DISABLE` / `ExternalTrigConv=ADC_SOFTWARE_START` + `EDGE_NONE` / `EOCSelection=ADC_EOC_SINGLE_CONV` / `DataAlign=RIGHT` / 12 位;`HAL_ADC_MspInit()` 已把 PA0~PA7+PC4 配成 `GPIO_MODE_ANALOG` | 硬件通路已打通(`hadc1` 可用);**消费者已落地**——`App/algo/adc_input.c` 的 `stm32_take()`(「STM32 ADC1 启动与扫描」,v2.0,2026-10-10):ADC1 由 **TIM3 TRGO 硬件触发**一轮 9 通道 + **DMA2_Stream4 循环搬运**进乒乓双缓冲,任务侧只消费刚完成的半区(零忙等),9 通道一轮 ≈ 67 µs |
| ADC1 上电自校准 | **已补(2026-10-10)**:`Src/adc.c` 的 `USER CODE BEGIN ADC1_Init 2` 调用 `adc1_calibrate()`(实现同文件 `USER CODE BEGIN 1`,按 RM0090 §13.3.6:清 ADON→等生效→置 ADON→置 CAL→等 CAL 由硬件清零)。⚠ **CubeMX 不生成这一步**,且本仓库裁剪版 HAL **没有** `HAL_ADCEx_Calibration_Start`、裁剪版 CMSIS 头**没有** `ADC_CR2_CAL`(bit3,代码里按 RM 自建 `ADC1_CAL_BIT`)→ 属 USER CODE 区手工定制,审计项 `adc1-calibration-call` / `adc1-calibration-impl` 兜底 | 实测有效:校准前后同一拍 STM32 侧 6 路**同向**变化 `UB 898→961`、`UC 978→1038`、`IB 906→922`、`IC 1061→1071`、`IN 1017→1055`、`T 790→846`(+10~+63 LSB ≈ 0.2~1.5 % FS);TPAFE 侧 `UA/UN/IA` 一字不变 → 变化确来自 ADC1 校准。缺这一步不报错,只是**读数带失调** |
| ADC 时钟 | CubeMX 的 F4 ADC 面板**有** Clock Prescaler 一项(此前"面板没有该项、固定 DIV2"的判断有误),已选 **PCLK2/4 → ADCCLK = 21 MHz** ✓。面板里 **DIV2 是灰的、选不到**:DB 里 `FadcConstraint Max=36000000`,APB2 = 84 MHz → DIV2 = 42 MHz 超限,该候选值被 `Action="DISABLE"` 禁掉,超规值进不来 | **不设额外防护(2026-10-09 决定)**:约束已由 CubeMX 把关;`.ioc` 虽不保存 `ADC1.ClockPrescaler` 键,重生成也只会回落到约束允许的值。按 144+12 cycles 算 ≈ 7.4 µs/通道、9 通道一轮 ≈ 67 µs |
| `adc_task` | **已实现(B1,2026-10-10;语义取数与有效性层 v2.3;P1-5 事件驱动消费,2026-10-10)**:`App/task/adc_task.c` 每拍调 `adc_input_poll()`(`App/algo/adc_input.c`)= TPAFE `tpafe5160_snapshot()` 原子快照(8 通道)+ 消费一帧 STM32 ADC1 DMA 乒乓缓冲,**经 `adc_input_raw()` 按语义取数**(不再直接索引驱动缓冲);**消费唤醒由 TIM3 ISR 置位 `ADC_WAKE_FLAG`**(不再 1 ms 轮询);任务在 `Src/freertos.c` 的 `USER CODE` 区创建为 `adcTask`(640 words / **AboveNormal**,`Src/freertos.c:159 .stack_size = 640 * 4`) | 数据路径已通(台架 `/serial-boot-test`:`frames` 严格 1000 Hz 递增、**`idle=0`**、`adc1_rc=0` / `adc1_err=0`) |
| TPAFE 采样触发 | **周期 CONVST 已实现(2026-10-10)**:`Src/main.c` 的 `HAL_TIM_PeriodElapsedCallback` 在 **TIM3 更新事件(1 kHz)** 内调 `tpafe5160_start_conv_irq()`;`app_main_init()` 用 `HAL_TIM_Base_Start_IT(&htim3)` 启动节拍(在 `tpafe5160_init()` 之后)。同一 TIM3 更新事件还经 **TRGO** 硬件触发 ADC1 一轮 9 通道(DMA 搬运),并调 `adc_tick_irq_notify()` **唤醒消费者**(P1-5 方案 a,2026-10-10;内含"消费者就绪"门)→ 两片转换器由同一硬件事件同源对齐 | 连续波形(1 kHz);详见 `docs/子系统设计/ADC采样节拍设计说明.md` §4(DMA 乒乓搬运)与 §6(事件驱动唤醒) |
| 前端偏置 | 每路 1k 串联 + 滤波 C 跨接差分输入;差分负端(`*_GND` 网)经 1k 拴 AGND。**不是对地分压**(2026-10-27 网表追线定死,拓扑图见 §7.1),**无中点偏置** | TPAFE 输入阻抗 **1 MΩ 恒定**(`../芯片手册/TPAFE5160.md` "Analog Input Impedance" 节),故端子对 AGND 的直流通路 = 1k + 1 MΩ + 1k ≈ **1.002 MΩ**,不是 1 kΩ。两侧各 1 kΩ 是手册要求的**源阻抗匹配**(AIN_nP / AIN_nGND 外接源阻抗相等以抵消失调),**不是分压**。STM32 侧只能测 **0~3.3 V 单极性**,交流量负半周被削顶;主板侧只做监视可接受,若要算 RMS/功率需硬件补偏置或明确算法口径 |
| TPAFE 量程(**2026-10-25 量程口径冻结定死**) | 板上 RANGE 接 GND → **±5 V 双极性量程**(芯片手册输入量程表:RANGE = 0 → −5 ~ +5 V),16 位二进制补码,**±5 V 满量程 = 10 V 跨度**,LSB = 10 V / 65536 ≈ **152.59 µV/码(@ 转换器引脚)**。“±10 V” 是芯片的另一可选档(RANGE = HIGH,跨度 20 V、LSB ≈ 305.18 µV),**本板未用**——历史版本曾把本板误标为“±10 V 双极性”,与 §7 本行矛盾、且会让 TPAFE 侧系数差一倍,更正记录见 §9 | 用 `tpafe5160_to_voltage()` 换算;端到端口径见 §7.1 |
| 取数契约(**2026-10-10 已修**,E-44 / E-45 / E-58 闭环) | 旧的 `get_buf` / `data_ready` / `clear_ready` **已删除**(删除前确认全仓库零调用者):`get_buf` 只给指针、任务再拷 → 被 BUSY EXTI 抢占就是**两帧混合**;`s_ready` 电平标志被 `start_conv_irq` 触发前清 0 → **重触发即丢未消费帧**;`read_all` 从不看 FRSTDATA(宏有定义、代码零引用)→ 芯片死亡时返回 OK + 常量垃圾。现口径:**`tpafe5160_snapshot(dst, count)`**(临界区原子拷贝,返回 1/0/-1,**仅任务上下文**)+ **`tpafe5160_frame_seq()`**(帧序号只增不清)+ **`tpafe5160_frstdata_err()`**(无跳变帧计数);`tpafe5160_init()` 增**首帧自检**——一帧读下来 FRSTDATA 无跳变(芯片不驱动并行总线;板上 R24 4.7k 上拉会把它钉死为高)→ 返回 `-3` + `[ERR]` | 消费者**只能**用 `snapshot()` 取数(`AGENTS.md` 已立为铁律);真机实测开机 `[ADC] Init OK` 现只在自检帧通过后才打印 → 判据在本板成立、非空转 |
| **通道归属** | 8 路电气量分属两片转换器:UA/UN/IA → TPAFE,UB/UC/IB/IC/IN → STM32 ADC | **V0.1 硬件缺陷** → 禁止跨转换器做相位/功率/功率因数/矢量类运算;**V0.2 要求 8 路电气量全部走 TPAFE**(缺陷原因与改版要求见 §1) |
| STM32 ADC 外设配置 | 9 通道 / Rank 1~9 / 全部 144 cycles / `ScanConvMode=ENABLE` / `ContinuousConvMode=DISABLE` / `ExternalTrigConv=ADC_SOFTWARE_START` + `EDGE_NONE` / `EOCSelection=ADC_EOC_SINGLE_CONV` / `DataAlign=RIGHT` / 12 位 / ADCCLK = PCLK2/4 = 21 MHz;`HAL_ADC_MspInit()` 把 PA0~PA7+PC4 配成 `GPIO_MODE_ANALOG`。消费者 = `App/algo/adc_input.c` 的 `stm32_take()`:ADC1 由 **TIM3 TRGO 硬件触发**一轮 9 通道 + **DMA2_Stream4 循环搬运**进乒乓双缓冲,任务侧只消费刚完成的半区(零忙等) | 9 通道一轮 ≈ 67 µs(144+12 cycles 约 7.4 µs/通道);`hadc1` 通路可用 |
| ADC1 上电自校准 | `Src/adc.c` 的 `USER CODE BEGIN ADC1_Init 2` 调 `adc1_calibrate()`(实现同文件 `USER CODE BEGIN 1`,按 RM0090 §13.3.6:清 ADON→等生效→置 ADON→置 CAL→等 CAL 由硬件清零)。**CubeMX 不生成这一步**,裁剪版 HAL 没有 `HAL_ADCEx_Calibration_Start`、裁剪版 CMSIS 头没有 `ADC_CR2_CAL`,代码里按 RM 自建 `ADC1_CAL_BIT`;审计项 `adc1-calibration-call` / `adc1-calibration-impl` 兜底 | 缺这一步**不报错,但读数带失调**(实测校准后 STM32 侧六路同向移动 +10~+63 LSB,TPAFE 侧不动) |
| ADC 时钟 | ADCCLK = 21 MHz(PCLK2/4)。CubeMX 里 DIV2 候选被 DB 约束 `FadcConstraint Max=36000000` 禁掉(APB2 84 MHz → 42 MHz 超限),`.ioc` 不保存 `ADC1.ClockPrescaler` 键,重生成只会回落到约束允许的值 | 不额外设防护 |
| `adc_task` | `App/task/adc_task.c` 每拍调 `adc_input_poll()` = TPAFE `tpafe5160_snapshot()` 原子快照(8 通道)+ 消费一帧 STM32 ADC1 DMA 乒乓缓冲,**经 `adc_input_raw()` 按语义取数**;消费唤醒由 TIM3 ISR 置位 `ADC_WAKE_FLAG`;任务在 `Src/freertos.c` 的 `USER CODE` 区创建(640 words / **AboveNormal**,`Src/freertos.c:159 .stack_size = 640 * 4`) | 台架实测 `frames` 严格 1000 Hz 递增、`idle=0`、`adc1_rc=0`、`adc1_err=0` |
| TPAFE 采样触发 | `Src/main.c` 的 `HAL_TIM_PeriodElapsedCallback` 在 **TIM3 更新事件(1 kHz)** 内调 `tpafe5160_start_conv_irq()`;`app_main_init()` 用 `HAL_TIM_Base_Start_IT(&htim3)` 启动节拍(在 `tpafe5160_init()` 之后)。同一 TIM3 更新事件经 **TRGO** 触发 ADC1 一轮 9 通道,并调 `adc_tick_irq_notify()` **唤醒消费者**(内含"消费者就绪"门) | 两片转换器由同一硬件事件同源对齐,连续波形 1 kHz;详见 `docs/子系统设计/ADC采样节拍设计说明.md` §4(DMA 乒乓搬运)与 §6(事件驱动唤醒) |
| 前端偏置 | 每路 1k 串联 + 滤波 C 跨接差分输入;差分负端(`*_GND` 网)经 1k 拴 AGND,**不是对地分压**(拓扑图见 §7.1),**无中点偏置** | TPAFE 输入阻抗 **1 MΩ 恒定**(`../芯片手册/TPAFE5160.md` "Analog Input Impedance" 节),端子对 AGND 的直流通路 = 1k + 1 MΩ + 1k ≈ **1.002 MΩ**,不是 1 kΩ;两侧各 1 kΩ 是手册要求的**源阻抗匹配**,不是分压。STM32 侧只能测 **0~3.3 V 单极性**,交流量负半周被削顶;主板侧只做监视可接受,若算 RMS/功率需硬件补偏置或另定算法口径 |
| TPAFE 量程 | 板上 RANGE 接 GND → **±5 V 双极性量程**(芯片手册输入量程表:RANGE = 0 → −5 ~ +5 V),16 位二进制补码,**±5 V 满量程 = 10 V 跨度**,LSB = 10 V / 65536 ≈ **152.59 µV/码(@ 转换器引脚)**。RANGE = HIGH 的 ±10 V 档(跨度 20 V、LSB ≈ 305.18 µV)是芯片另一可选档,**本板未用**;305.18 只属该档的 LSB,**不是本板系数** | 用 `tpafe5160_to_voltage()` 换算;端到端口径见 §7.1 |
| 取数契约 | 消费者**只能**用 **`tpafe5160_snapshot(dst, count)`**(临界区原子拷贝,返回 1=有新帧 / 0=无新帧 / -1=参数错,**仅任务上下文**)+ **`tpafe5160_frame_seq()`**(帧序号只增不清)+ **`tpafe5160_frstdata_err()`**(无跳变帧计数)。`tpafe5160_init()` 含**首帧自检**:一帧读下来 FRSTDATA 无跳变(芯片不驱动并行总线,板上 R24 4.7k 上拉会把它钉死为高)→ 返回 `-3` + `[ERR]` | `AGENTS.md` 已立为铁律;开机 `[ADC] Init OK` 只在自检帧通过后才打印 |
### 7.1 端到端量纲链路口径(网名 AINn → 端子 → 变比 → 码值 → 满量程,2026-10-25 量程口径冻结定死)
### 7.1 从端子到码值:链路四段口径
> 出处:`docs/任务规划/数据可信.md` §2.1(量程口径冻结)。本节把 **语义端子(二次侧)→ 子板/端子板 → 网名 `AINn` → 主板电阻网络 → 板级网名 `ADCn` → 转换器引脚 → 码值 → 满量程** 的链路**逐段**定口径。
> ③ 段(`AINn` ↔ 转换器引脚)已有台架实测数值——变比 **1:1**,斜率实测见 §8.1;④ 段(语义端子 ↔ `AINn` 的子板/
> 端子板变比)仓库内没有任何数据,只给口径与判据。
要把「端子上的电压」换算成「屏上的读数」,得先知道这条链路上**哪一段会改数值**。这里把链路切成四段(一段 = 信号经过的一节),逐段给口径与状态;**下表是本节主表**,后面的内容按同样的段名展开。
**芯片级口径(定死,与前端网络无关)**:
| 段 | 这一段在问什么 | 关系 | 状态 |
|---|---|---|---|
| ① 语义 ↔ 网名 ↔ 板级网名 ↔ 转换器代码通道 | “UA 到底是哪个通道号” | §2/§3/§4/§5 的 17 路映射表 | **定死**(本文件为唯一权威) |
| ② 转换器引脚电压 ↔ 码值 | “脚上是 1 V,读出来几个码” | TPAFE `U_pin = code × 152.59 µV`(code 带符号);STM32 `U_pin = code × 805.66 µV` | **定死**(纯转换器事实,见下表) |
| ③ `AINn` ↔ `ADCn` / 转换器引脚(板内串联电阻那一节) | “串在中间的电阻有没有把电压分掉” | **变比 = 1:1**:`ADCn` 节点只有 {串阻.2, 滤波 C, 转换器引脚},无对地元件 | **定死**(网表 + 台架实测,见 §8.1:端子侧注入斜率 6544.2 码/V vs 引脚侧理论 6553.6,差 0.14 %,不存在分压) |
| ④ 语义端子(二次端子)↔ `AINn`(子板/端子板那一节) | “端子上的电压,进到板内还是同一个数值吗” | 子板/端子板变比:仓库内**无数据**(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图) | **缺口**——待「端子/子板变比确认」实测;拿不到变比则“端子二次值”不成立、`eng` 保持 0 |
**芯片级口径**(② 段,与前端网络无关):
| 项 | 口径 | 依据 |
|---|---|---|
| TPAFE5160 量程档 | 板上 RANGE(U3 pin8)接 GND → **±5 V 双极性**(−5 ~ +5 V);RANGE = HIGH 的 ±10 V 档本板未用 | [`V0.0_网表详细分析报告.md`](V0.0_网表详细分析报告.md) §4.5“模式配置全对:RANGE(pin8)=GND → ±5V” + [`../芯片手册/TPAFE5160.md`](../芯片手册/TPAFE5160.md) 输入量程表(RANGE = 0 → −5 ~ +5;RANGE = 1 → −10 ~ +10) |
| TPAFE 码值格式 | 16 位二进制补码(−32768 ~ +32767,全量程 65536 码 = 10 V 跨度) | 芯片手册 DC Accuracy(16 bit / NO missing code);`Drivers/BSP/TPAFE5160/tpafe5160.c` 的 `tpafe5160_to_voltage()` 注释 |
| TPAFE LSB(@ 引脚) | 10 V / 65536 ≈ **152.59 µV/码**(≈6553 码/V) | 由上两行推得;与 §7“TPAFE 量程”行、驱动注释一致 |
| STM32 ADC1 LSB(@ 引脚) | 12 位单极性 0 ~ 3.3 V:3.3 V / 4096 ≈ **805.66 µV/码**(≈1241 码/V) | §7 生成配置行;`docs/任务规划/数据可信.md` §2.1 同口径 |
| TPAFE5160 量程档 | 板上 RANGE(U3 pin8)接 GND → **±5 V 双极性**(−5 ~ +5 V);RANGE = HIGH 的 ±10 V 档本板未用 | [`V0.0_网表详细分析报告.md`](V0.0_网表详细分析报告.md) §4.5 + [`../芯片手册/TPAFE5160.md`](../芯片手册/TPAFE5160.md) 输入量程表(RANGE = 0 → −5 ~ +5;RANGE = 1 → −10 ~ +10) |
| TPAFE 码值格式 | 16 位二进制补码(−32768 ~ +32767,全量程 65536 码 = 10 V 跨度) | 芯片手册 DC Accuracy(16 bit / NO missing code);`Drivers/BSP/TPAFE5160/tpafe5160.c` 的 `tpafe5160_to_voltage()` |
| TPAFE LSB(@ 引脚) | 10 V / 65536 ≈ **152.59 µV/码**(≈6553 码/V) | 由上两行推得;与 §7「TPAFE 量程」行一致 |
| STM32 ADC1 LSB(@ 引脚) | 12 位单极性 0 ~ 3.3 V:3.3 V / 4096 ≈ **805.66 µV/码**(≈1241 码/V) | §7 配置行;`docs/任务规划/数据可信.md` §2.1 同口径 |
“±10 V”只允许出现在“芯片可选档”语境。本文件 2026-10-09 建档时曾把文首摘要写成“TPAFE … ±10 V 双极性”,与 §7 的 ±5 V 档矛盾、**TPAFE 侧系数因此会差一倍**——2026-10-23 `docs/任务规划/数据可信.md` §2.1 挂账该冲突并要求量程口径冻结定死;现**定死为“±5 V 满量程 = 10 V 跨度、LSB 152.59 µV”**,文首摘要与 §7 已按此更正。全仓其余“±10 V”字样仅剩芯片手册转写与 `tpafe5160.h` 中 RANGE 枚举可选档注释(均为芯片能力描述,非本板配置口径),不构成歧义。
**③ 段的实际拓扑**(2026-10-27 按 `V0.1.tel` 逐通道追线,UA 为例;图由
`tools/arch_diagram/gen_adc_frontend_svg.py` 生成,改图请改脚本重跑,勿手改 SVG):
**③ 段(板内串联电阻那一节)实际接了什么**(UA 为例,按 [`V0.1.tel`](V0.1.tel) 逐通道追线;图由 `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 三样(网表第 241 行),**没有对地元件**——所以 ③ 段
不是分压器,变比 **= 1:1**。C44 / R32 那一串接在 `ADC7_GND`(= TPAFE 负输入 `AIN_7GND`)上,
是差分滤波,不在信号通路上。STM32 侧同构且更简(图 B:`C111` 直落 AGND,连接地串阻都没有)。
`ADC7` 节点上**只有** R31、C44、U3.61 三样(网表第 241 行),**没有对地元件**,所以这一串不是分压器,从 `AIN1` 到转换器引脚电压不变(变比 **= 1:1**)。C44 / R32 那一串接在 `ADC7_GND`(= TPAFE 负输入 `AIN_7GND`)上,是差分滤波,不在信号通路上。STM32 侧同构且更简(`C111` 直落 AGND,无接地串阻)。
**链路分段口径**:
**口径要点**:
| 段 | 关系 | 状态 |
|---|---|---|
| ① 语义 ↔ 网名 ↔ 板级网名 ↔ 转换器代码通道 | §2/§3/§4/§5 的 17 路映射表 | **定死**(本文件为唯一权威) |
| ② 转换器引脚电压 ↔ 码值 | TPAFE `U_pin = code × 152.59 µV`(code 带符号);STM32 `U_pin = code × 805.66 µV` | **定死**(纯转换器事实,上表) |
| ③ `AINn`(串联电阻子板侧)↔ `ADCn`/转换器引脚 | **变比 = 1:1(2026-10-27 定死)**:`ADCn` 节点只有 {串阻.2, 滤波 C, 转换器引脚},无对地元件(拓扑图见上)。旧"读法 A(2:1 分压 → 305.18 / 1611.3 µV/码)"**作废**——它是把接在差分负端的 1k 误读成对地分压 | **定死**(网表级结论 + **2026-10-27 台架实测确认**,见 §8.1:端子侧注入斜率 6544.2 码/V,与引脚侧理论 6553.6 差 0.14 %,不存在 2:1 分压)。已知电压注入验证已闭环 |
| ④ 语义端子(二次端子)↔ `AINn` | 子板/端子板变比:仓库内**无任何文档**(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图;§8 步骤 4) | **缺口**——待「端子/子板变比确认」实测确认;拿不到变比则"端子二次值"不成立、`eng` 保持 0 |
**可评审结论**:
1. **ROM 默认系数按 ② 引脚口径冻结**:TPAFE 通道 `k = 152.59 µV/码`、STM32 通道 `k = 805.66 µV/码`;标定折算的输出单位 = **ADC 引脚电压 V**(`eng = 0`)。该口径**不依赖** ③④ 两个未决项,自本节点死即成立——这就是 M4 承诺边界止于“引脚电压”的依据(`docs/任务规划/数据可信.md` §2.6)。
2. `docs/任务规划/数据可信.md` §2.1 旧表的“板级系数(输入侧)305.18 / 1611.3 µV/码”**已随 ③ 段定死而删除**(2026-10-27):该值按 2:1 分压折算,而网表证明 `ADCn` 节点无对地元件。板级系数 = 引脚侧系数(152.59 / 805.66);305.18 / 1611.3 今后只允许出现在“±10 V 档 LSB”语境(芯片手册口径),不得再当本板系数。
3. **满量程必须写明参考点**:TPAFE 通道满量程 = ±5 V **@ 引脚**(跨度 10 V);③ 已定 1:1、④ 仍未知,故端子侧满量程只允许写“引脚侧数值 × ④ 比”,**严禁**把“码 × 152.59 µV”当端子二次值写进代码/文档(那是引脚电压)。
4. **已知电压注入验证已于 2026-10-27 闭环**(六项判据全 PASS,实测见 §8.1):③ 段 1:1 由台架直接证实,
② 引脚侧 LSB 与实测斜率差 0.14 %,逐通道映射与极性均已验。**仍待实测的是 ④**(端子→引脚
变比,即端子/子板变比确认)与两点标定;两者完成前 `eng` 保持 0、输出单位仍是 ADC 引脚电压。
实测斜率与 ② 理论值偏差 >2 % 时**先查前端**(分压/变比/焊接),不得用系数凑错斜率
(`docs/任务规划/数据可信.md` §8 风险表)。
1. **ROM 默认系数按 ② 段(引脚电压 ↔ 码值)冻结**:TPAFE 通道 `k = 152.59 µV/码`、STM32 通道 `k = 805.66 µV/码`;标定折算的输出单位 = **ADC 引脚电压 V**(`eng = 0`)。该口径不依赖 ③④ 两段,自本节点死即成立——这是 M4 承诺边界止于“引脚电压”的依据(`docs/任务规划/数据可信.md` §2.6)。
2. **板级系数 = 引脚侧系数**(152.59 / 805.66)。305.18 / 1611.3 µV/码 只属 ±10 V 档的 LSB(芯片手册口径),**不是本板系数**,不得当板级系数用。
3. **满量程必须写明参考点**:TPAFE 通道满量程 = ±5 V **@ 引脚**(跨度 10 V);③ 段已定 1:1、④ 段仍未知,故端子侧满量程只允许写“引脚侧数值 × ④ 段变比”,**严禁**把“码 × 152.59 µV”当端子二次值写进代码/文档。
4. **仍待实测的是 ④ 段**(端子→引脚的变比)与两点标定;两者完成前 `eng` 保持 0、输出单位仍是 ADC 引脚电压。实测斜率与 ② 段理论值偏差 >2 % 时**先查前端**(分压/变比/焊接),**不得用系数凑错斜率**——那会把硬件的错固化成"标定值"。
---
## 8. 逐通道验证方法(上板自检口径)
### 8.1 静态注入实测记录
1. **TPAFE 侧**:对目标 `AIN` 注入 1 V DC → 观察对应 `buf[i]` 变化(UA→`buf[6]`、UN→`buf[5]`、IA→`buf[2]`),同时 U3.14 `BUSY` 有脉冲;**语义与下标不符即映射错**。✅ **2026-10-27 已执行**(原 2026-10-23 挂账的"无执行记录"已消除;`docs/硬件平台/V0.0_网表详细分析报告.md` §5.1 第 6 条的同一验证随之关闭)。判据按已知电压注入验证的**不需要示波器**口径执行:① "`BUSY` 有脉冲"改用固件帧计数——注入前后 `tpafe5160_frame_seq()` 仍严格 1000 Hz 递增即等价;② 幅值判据改用万用表读注入点实际电压 + 同时读 `adc_input_raw()` 码值,三点线性拟合(R² ≥ 0.999)。
2. **STM32 侧**:对目标引脚(如 PC4=UB)注入 0.5 V → 读 `ADC_CHANNEL_14` 应变化;若不变而相邻通道变化 → 通道宏写错(见 §5 警告)。✅ **2026-10-27 已执行**(原 2026-10-10 的"尚未执行"已消除;当时台架只验证了"9 通道全部转换成功 + 零超时 + 互异非饱和 + 跨次开机读数不同",台架无信号源);映射的**代码侧**一致性有两道保证:① `App/algo/adc_input.c` 的 `k_adc_map[]` 与 CubeMX 标签(`ADC17_UB`=PC4 等)逐条对齐;② 开机自检 `adc_input_init()` 校验每个 STM32 语义通道都落在 `k_stm32_rank_ch[]` 扫描序列内(挡"映射到不扫描的通道 → 恒读陈旧值")。
3. **备用通道**:RESERVED 路不接入任何语义,UI 与上报里不得出现;若实测有读数漂移,只记录不消费。
4. **端子侧变比(2026-10-23 补,2026-10-27 收窄)**:上面 1/2 两条都只到 **ADC 引脚**。③ 段(`AINn` ↔ 转换器引脚)已由网表追线定死为 **1:1**(`ADCn` 节点无对地元件,拓扑图见 §7.1),**板内不再有未知比值**;剩下的未知量只有 ④ **子板/端子板变比**——它在仓库里没有任何文档给出(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图)。故**不得**用"2:1 分压"换算出二次值;该变比由「端子/子板变比确认」实测确认。
### 8.1 2026-10-27 实测记录(首次执行,六项判据全 PASS)
**注入点在端子侧**(`U5.x` 连接器焊盘,见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3),
未碰 LQFP 引脚——有 1k 串阻护着,且 ③ 段已定 1:1,端子侧斜率即引脚侧斜率。
完整步骤、现场记录表与逐项判据见该文档 §5/§6,此处只留结论。
注入点在**端子侧**(`U5.x` 连接器焊盘,见 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §3),未碰 LQFP 引脚——有 1k 串阻护着,且板内串阻不分压(③ 段 1:1),端子侧斜率即引脚侧斜率。完整步骤与现场记录见该文档 §5/§6,此处只留结论。
| 项 | 实测 | 判据 | 结论 |
|---|---|---|---|
@@ -208,50 +172,25 @@ STM32(U17)为 LQFP144 脚号。
| 极性(TPAFE 三路) | −6566 / −6568 / −6566,对称性 ≤0.34 % | 落在 −6554 附近且 ≤2 % | PASS |
| 节奏 | 注入前/后 Δ9998 码 / 10 s ≈ 1000 Hz,`idle=0`、`adc1_err=0` | 注入前后仍 1000 Hz | PASS |
**由此确认的三件事**:
**结论**:③ 段变比 1:1 有台架直接证据(端子侧斜率 6544.2 与引脚侧理论 6553.6 差 0.14 %;若存在 2:1 分压,实测会是约 3277);8 路语义 ↔ 物理端子一一对应,`k_adc_map[]` 与 §3/§5 无误;TPAFE 补码符号位解释正确(−1.0 V 点码值为负、幅值与 +1.0 V 点对称)。
1. **③ 段变比 = 1:1 得到台架直接证据**(原为网表追线的推断)。端子侧注入斜率 6544.2 码/V,
与引脚侧理论 6553.6 差 0.14 %——若存在 2:1 分压,斜率会是理论值的一半(约 3277),实测不存在。
旧"板级系数 305.18 / 1611.3 µV/码"据此**第二次**被否(第一次是网表拓扑)。
2. **8 路语义 ↔ 物理端子一一对应**,`k_adc_map[]` 与 §3/§5 映射表无误。
3. **TPAFE 补码符号位解释正确**:−1.0 V 点码值为负、幅值与 +1.0 V 点对称。
**未覆盖**:串扰未单独证(零点步骤时其余七路浮空、本身在漂);节奏只测了注入前后、没测注入进行中。
**两项残留口径**(不影响本轮 PASS,但别当成已验证):**串扰**未单独证(零点步骤时其余七路浮空、
本身在漂,小幅串扰看不出来);**节奏**只测了注入前后、没测注入进行中。
### 8.2 交流(正弦)动态验证实测记录
(澄清一句:本节标题里的"六项"= 上表六个**静态**判据项,与 §8.2 交流**动态六轮**不是同一套数。)
### 8.2 交流(正弦)动态验证实测记录(2026-11-02 台架首轮 + 2026-11-04 补测轮)
**执行手册与逐轮记录表**在 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8;证据归档
`docs/测试说明/测试数据/boot_log_data/20261104_ac_*`(含录波段原件与 `wave_read.py` 输出)。
两轮固件分别为 `fw build: Nov 2 2026 14:21:24` 与 `fw build: Nov 4 2026 19:05:57`(均产品构建、
未标定 `eng=0`)——**以下全部是引脚域电压口径,不是端子二次值**。发生器 VICTOR 2026H(设定一律
Vpp,端接高阻),万用表 FNIRST-DMT-99(判为真有效值档,判别依据见执行手册设备表)。
执行手册与逐轮记录表在 `docs/测试说明/专项验证/ADC前端注入验证流程.md` §8;证据归档 `docs/测试说明/测试数据/boot_log_data/20261104_ac_*`(含录波段原件与 `wave_read.py` 输出)。固件为产品构建、未标定(`eng=0`)——**以下全部是引脚域电压口径,不是端子二次值**。
| 轮 | 实测结论 | 关键数 |
|---|---|---|
| 幅值 | **过**:三档幅值两点复现全落 ±2 % | −0.20 % / −0.20 % / +0.40 %(996 : 498 : 249 ≈ 4:2:1,无隐藏触底) |
| 幅值 | **过**:三档幅值全落 ±2 % | −0.20 % / −0.20 % / +0.40 %(996 : 498 : 249 ≈ 4:2:1,无隐藏触底) |
| 波形 | **过**:非正弦也能读对,证数条是真有效值档 | 方波 −0.70 %、三角 −1.22 %;反推峰值两波形互合(1404 / 1410 mV vs 设定 1414 mV) |
| 相位 | **过(录波档 ≤2°)**:同段 `UA`(表序 0)vs `UN`(表序 3),同片 TPAFE 内比 | 0°/0° 段 Δφ = **0.07°**(WAVE06,11-02);0°/90° 段 Δφ = **90.05°**、偏差 0.05°、逐周波漂移 ≤0.01°(WAVE09,11-04,16 整周波全过);段与发生器无绝对相位锁,只比同段相对差 |
| 测频 | **如实报不可测成立**(现状判据就是不出数) | 两轮合计 561 行 `freq(hb)` 全部 `f=0 valid=0`(含满幅注入段);幅值门 `FREQ_AMP_MIN=50.0f`(`App/algo/freq.h:62`)在引脚域恒不过——标定态或改门限前测频轮不出数是**预期** |
| 削顶 | **直流档锁存成立、sticky 实证**;低频档与复位复核按裁定关闭 | UB 注 DC −1.00 V:`rail=0x002 edge=0x002`、唯一 `[ERR] rail: edge=0x2 sticky=0x2`、`adc: UB` 钉 0 码;撤注后恒持 ≥30 min(sticky 只有 `adc_health_rail_init()` 清,即复位)。50 Hz 同幅不锁存=预期(≈11 拍<20)。2.0 Hz 低频档与"复位清 sticky"复核**用户裁定 2026-11-04 不做**(判据链已被直流档闭合) |
| 谐波 | **选择性两轮成立**;幅值 A/C 过、B 已归因板端前端 RC 并关闭 | 单注 100 Hz → `Ia2` −1.25 %;纯基波 → `Ia` 0.0 %(复测)/ −0.6 %(初测)、两谐波桶=0;单注 250 Hz → `Ia5` **−4.4 %**(两轮复现 −4 ~ −5 %)——归因:差分滤波 C35 = 100 nF(用户确认)+ R19/R21 各 1 k(`docs/硬件平台/V0.1.tel`:49;拓扑 = 1 k 串联 + 1 k 接差分负端、不分压,`docs/产品需求/产品需求设计文档.md` FR-ADC-5)→ IA 差分传递 = 一阶低通 **fc ≈ 796 Hz**,该 −4.4 % 是前端在此频点的**真实衰减,板端读数忠实**;工频 50 Hz 仅 −0.2 %,不受影响(模型与数据见下段) |
| 相位 | **过(≤2°)**:同段 `UA`(表序 0)vs `UN`(表序 3),同片 TPAFE 内比 | 0°/0° 段 Δφ = **0.07°**;0°/90° 段 Δφ = **90.05°**(偏差 0.05°,逐周波漂移 ≤0.01°)。段与发生器无绝对相位锁,只比同段相对差 |
| 测频 | **如实报不可测成立**(现状判据就是不出数) | `freq(hb)` 全部 `f=0 valid=0`(含满幅注入段);幅值门 `FREQ_AMP_MIN=50.0f`(`App/algo/freq.h:62`)在引脚域恒不过——标定态或改门限前不出数是**预期** |
| 削顶 | **直流档锁存成立、sticky 实证**;低频档与复位复核按裁定关闭 | UB 注 DC −1.00 V:`rail=0x002 edge=0x002`、唯一 `[ERR] rail: edge=0x2 sticky=0x2`、`adc: UB` 钉 0 码;撤注后恒持(sticky 只有 `adc_health_rail_init()` 清,即复位)。50 Hz 同幅不锁存=预期(≈11 拍 < `ADC_RAIL_N_RUN`=20)。2.0 Hz 低频档与复位复核**用户裁定不做**(判据链已被直流档闭合) |
| 谐波 | **选择性成立**;幅值全过,250 Hz 端的 −4.4 % 已归因板端前端 RC | 单注 100 Hz → `Ia2` −1.25 %;纯基波 → `Ia` 0.0 %/−0.6 %、两谐波桶 = 0;单注 250 Hz → `Ia5` **−4.4 %**(见下段归因) |
**观察项(都判读过、非缺陷)**:TPAFE 输入浮空读数钉在 ≈1743/1747 mV 静态(撤线后 UA/IA 出现——
读 `meas:` 时先确认接线);未接线的 STM32 侧引脚码值随环境缓漂(UC/IC/IN/T),不消费即可;
录波触发后 `drop` 涨一截是 SEALED 窗口设计内(`App/algo/wave_ring.c:50`,涨完冻结,判失败只看
`err`/`ovf`);采集链健康两轮全程 Δ9998/10 s、`idle=0`、`adc1_err=0`(前置门 8 条全过)。
**观察项(都判读过、非缺陷)**:TPAFE 输入浮空读数钉在 ≈1743/1747 mV 静态(撤线后 UA/IA 出现——读 `meas:` 时先确认接线);未接线的 STM32 侧引脚码值随环境缓漂(UC/IC/IN/T),不消费即可;录波触发后 `drop` 涨一截是 SEALED 窗口设计内(`App/algo/wave_ring.c:50`,涨完冻结,判失败只看 `err`/`ovf`);采集链全程 Δ9998/10 s、`idle=0`、`adc1_err=0`(前置门 8 条全过)。
**IA 前端差分滤波 = 低通 fc ≈ 796 Hz(2026-11-04,谐波 B 行定量归因)**:工频测量够用、
谐波测量不够用——同拓扑外推 5 次 ≈ −4.6 %(出 ±2 % 判据)、7 次 −8.5 %、9 次 −13.0 %、11 次
−17.7 %、13 次 −22.6 %、15 次 −27.2 %、21 次(1050 Hz)−39.6 %;C35 若改 10 nF 则 fc ≈ 8 kHz,
21 次仅 −0.9 %。谐波功能产品化的硬件前置 = 板改小 C35 + 清点其余各路差分滤波电容容值(已登记
`docs/任务规划/登记簿.md` §3)。**为什么改板而不是软件逐阶修正**:修正系数依赖这颗电容的实际容值,
而电容有容差、随温度漂,每块板、每个温度都不一样,修正表跟不上;二次谐波制动这类"拿某次谐波幅值
与基波比值"的判据,比值被前端畸变后判定就不可信。换 10 nF 后测量带内是平的,板端读数直接可信,
不需要修正。证伪条件(将来有示波器再复核):该低通预测 250 Hz 差分分量额外滞后
≈17°;模型与三点拟合 `docs/测试说明/测试数据/boot_log_data/20261104_ac_ia_rc_model.txt`。
**IA 前端差分滤波 = 低通 fc ≈ 796 Hz**:C35 = 100 nF 跨接差分对,与 R19/R21 各 1 k([`V0.1.tel`](V0.1.tel):49)构成一阶低通;拓扑为 1 k 串联 + 1 k 接差分负端、不分压(`docs/产品需求/产品需求设计文档.md` FR-ADC-5)。**250 Hz 的 −4.4 % 就是这颗电容在该频点的真实衰减,板端读数忠实**,工频 50 Hz 仅 −0.2 % 不受影响。谐波测量不够用——同拓扑外推:5 次 ≈ −4.6 %(出 ±2 % 判据)、7 次 −8.5 %、9 次 −13.0 %、11 次 −17.7 %、13 次 −22.6 %、15 次 −27.2 %、21 次(1050 Hz)−39.6 %;C35 改 10 nF 则 fc ≈ 8 kHz、21 次仅 −0.9 %。**谐波功能产品化的硬件前置 = 板改小 C35 + 清点其余各路差分滤波电容容值**(登记 `docs/任务规划/登记簿.md` §3)。**为什么改板而不是软件逐阶修正**:修正系数依赖这颗电容的实际容值,而它有容差、随温度漂,每块板、每个温度都不一样,修正表跟不上;二次谐波制动这类“拿某次谐波幅值与基波比值”的判据,比值被前端畸变后判定就不可信。换 10 nF 后测量带内是平的,板端读数直接可信。证伪条件(有示波器再复核):该低通预测 250 Hz 差分分量额外滞后 ≈17°;模型与三点拟合 `docs/测试说明/测试数据/boot_log_data/20261104_ac_ia_rc_model.txt`。
**边界**:本节不证端子二次值 / 精度等级 / 跨转换器相位(V0.1 硬件缺陷)/ THD——见
`docs/任务规划/数据可信.md` §4.6.5。
**边界**:本节不证端子二次值(④ 段变比未知,见 §7.1)/ 精度等级(要标准源)/ 跨转换器相位(V0.1 硬件缺陷)/ THD。
+12 -13
View File
@@ -1,12 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""生成 docs/images/ADC直流标定与交流验证.svg —— 上下两条泳道讲清"同一个针脚、两种证法":
上排 = 已做完的直流静态标定(一条水平线的高度),下排 = 本文新增的交流正弦验证
上排 = 直流静态标定(一条水平线的高度),下排 = 交流正弦验证
(整条时间轴的形状与节拍),底部 = 只有正弦能证的六件事 + 安全红线(纯标准库)。
为什么不用 Mermaid:本图要的是"两条流水线一一对齐 + 波形示意",Mermaid 画不出
20 点/周的正弦采样点,也无法把上下一一对齐。谁挡谁的顺序拓扑仍是 Mermaid,
见 docs/任务规划/数据可信.md §6。
20 点/周的正弦采样点,也无法把上下一一对齐。
用法(仓库根目录,任意 python3):
python tools/arch_diagram/gen_data_trust_dc_ac_svg.py
@@ -67,13 +66,13 @@ BG_AMBER = "#fffbeb"
# ----------------------------- 数据(改这里)-----------------------------
TITLE = "同一个针脚,两种证法 —— 直流只证「高度」,正弦才证「形状与节拍」"
SUB1 = ("上排已做完(2026-10-27 静态注入六项判据全 PASS);下排一次也没做过:正弦波从没进过这条链,"
"所以后面的相量、测频、削顶、谐波对不对,现在无人能答")
SUB1 = ("上排 2026-10-27 静态注入六项判据全 PASS;下排 2026-11-02 / 11-04 台架两轮跑完六轮,"
"幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波全部闭合")
SUB2 = ("两排共用同一个注入点、同一套前端、同一份折算代码 —— 差别只在信号源是「平的」还是「会走 20 点/周的正弦」")
LANE_A_LABEL = "上排 · 直流静态标定(已做)"
LANE_A_GLYPH = "flat"
LANE_B_LABEL = "下排 · 交流正弦验证(本文新增 · 待做)"
LANE_B_LABEL = "下排 · 交流正弦验证(已做两轮)"
LANE_B_GLYPH = "sine"
# 每条泳道 6 个环节:(标题, 说明 1, 说明 2)
@@ -86,12 +85,12 @@ BOXES_A = [
("三点线性拟合", "0 / 0.5 / 1.0 V", "R² = 0.9999997,斜率差 −0.14 %"),
]
BOXES_B = [
("信号发生器", "50 Hz 正弦", "幅度按峰值算,见底部红线"),
("注入点 R31", "同上排同一个点", "外串 10 k、与板共地"),
("前端 + 转换器", "同上排同一条链", "STM32 五路负半周必削顶"),
("信号发生器", "50 Hz 正弦", "幅度按 Vpp 设定,见底部红线"),
("注入点 R31", "同一条注入点", "外串 10 k、与板共地"),
("前端 + 转换器", "同一套前端", "STM32 五路负半周必削顶"),
("1 kHz 采样点", "TIM3 TRGO 同时触发", "50 Hz → 20 点/整周"),
("全周傅氏", "phasor_run():√2/N 预乘", "直接得有效值与相位"),
("读数出口", "meas 200 ms → 104 YC 0x4011", "幅值 + 品质 + 频率(或 UI)"),
("读数出口", "meas 200 ms + 录波段文件", "幅值 + 品质 + 频率"),
]
CHIPS_TITLE = "只有正弦能证的六件事(直流在构造上就证不到)"
@@ -101,7 +100,7 @@ CHIPS = [
("相位", "φ = atan2(fIm, fRe) 全靠正弦才有意义"),
("测频 freq_run", "共轭乘积取相位增量;直流相位不前进 → 恒无效"),
("削顶路由 CLIPPED", "UB/UC/IB/IC/IN 单极性 0~3.3 V,负半周必削顶 → 该报 IV 就得报 IV"),
("谐波实例 C04 / C05", "二次 / 五次相量已建但无消费者:发生器给含谐波信号才能验"),
("谐波实例 C04 / C05", "二次 / 五次相量:单注 100 / 250 Hz 已验各认各的次,叠加工况待标准源"),
]
NOTES = [
@@ -115,8 +114,8 @@ NOTES = [
"跨转换器相位:UB/UC 与 UA 分属两片转换器、无共同采样触发(V0.1 硬件缺陷),任何相位比较都不作数。"]),
]
FOOTNOTE = ("读数出口现在就有:104 YC(test/host/iec104_master.py,浮点无量化)+ 串口每 10 s 的 phasor(hb) / freq(hb) / meas: 行;"
"但板上没有「把窗里 20 个点导出来」的出口,正弦只能靠派生标量证,而 phasor 行是 ×0.1 定点(注 1 V 只剩 10 格)。")
FOOTNOTE = ("读数出口:串口每 10 s 的 phasor(hb) / freq(hb) / meas: 行,加上录波段文件(一次 320 点 / 8 路,PC 侧 wave_read.py 可 dump / fft / shape / plot);"
"心跳行是 ×0.1 定点(注 1 V 只剩 10 格),定量判据一律走段文件重算。")
# ----------------------------- 布局 -----------------------------
LANE_TOP_A = 108
@@ -1,11 +1,10 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""生成 docs/images/数据可信台阶.svg —— 「数据可信」的五级台阶:现在踩在第 2 级,
第 3 级(动态正弦波形)用手边设备就能跨(纯标准库)。
"""生成 docs/images/数据可信台阶.svg —— 「数据可信」的五级台阶:现在踩在第 3 级,
第 4、5 级(端子二次值 / 精度验收)在等外部资源(纯标准库)。
为什么不用 Mermaid:本图要读的是"台阶的高度差 + 每一级踩没踩上去"——Mermaid 会把
五级压成同一高度,"还差一级"这件事就看不出来了。谁挡谁的顺序拓扑另有一张 Mermaid
图,在 docs/任务规划/数据可信.md §6(本图刻意不重复那张的语义)。
五级压成同一高度,"还差一级"这件事就看不出来了。
用法(仓库根目录,任意 python3):
python tools/arch_diagram/gen_data_trust_ladder_svg.py
@@ -60,11 +59,11 @@ C_BLUE = "#2563eb"
BG_BLUE = "#eff6ff"
# ----------------------------- 数据(改这里) -----------------------------
TITLE = "「数据可信」是五级台阶 —— 现在踩在第 2 级"
TITLE = "「数据可信」是五级台阶 —— 现在踩在第 3 级"
SUB1 = ("每升一级只多答一个问题:通路活 → 静态读数对 → 动态波形对 → 换算到端子 → 精度达标;"
"台阶的高度差 = 下游能多信多少")
SUB2 = ("第 3 级不要标准源、也不要往端子加压:一台信号发生器 + 已有的注入点就能做"
"(判据见 docs/任务规划/数据可信.md §4.6)")
SUB2 = ("第 3 级已台架闭环(2026-11-02 / 11-04 两轮),用的是手边发生器 + 已有的注入点;"
"第 4、5 级在等子板变比与标准源")
# 每列:(编号, 台阶名, 状态, 主色, 底色, 这一级多答的问题, 用什么证 / 什么挡路)
STEPS = [
@@ -74,10 +73,9 @@ STEPS = [
("2", "静态引脚电压", "已证 · 2026-10-27", C_GREEN, BG_GREEN,
"注 1 V 直流,读数是不是 1 V?",
"万用表 + 电位器三点线性:斜率 6544.2 vs 理论 6553.6 码/V,差 −0.14 %"),
("3", "动态引脚波形", "待做 · 本文新增", C_ROSE, BG_ROSE,
("3", "动态引脚波形", "已证 · 2026-11-04", C_GREEN, BG_GREEN,
"注 1 V 正弦,算出来还是不是 1 V?",
"注正弦验全周傅氏幅值 / 相位 / 测频 / 削顶 / 谐波抑制。"
"挡路:FREQ_AMP_MIN = 50 V 在引脚域恒不过 → 测频只能读到 IV"),
"幅值 / 波形 / 相位 / 测频 / 削顶 / 谐波六轮全跑;测频轮以「如实报不可测」通过"),
("4", "端子二次值", "等外部资源", C_AMBER, BG_AMBER,
"引脚上这 1 V 对应端子侧几 V?",
"④ 子板 / 端子板变比:仓内无原理图,须拿图纸或万用表实测"),