docs(任务规划): 立项 W8 数据可信,补 ADC 注入验证两卡,新增并行分道方案

- W8 数据可信:通道标定 → 遥测链 → 运行参数,14 张任务卡。
- 补卡:核查确认 ADC 从未采过已知电压(只验过通路活),新增
  "已知电压注入验证"(只需万用表)与"端子变比确认"两卡;M4 的承诺
  边界改为"ADC 引脚电压",二次值降为依赖变比的条件项。
- 撤销"1k+1k 即 2:1 分压"的换算用法:该网络被定性为源阻抗匹配,
  且端子→引脚变比仓库内无文档。
- 并行分道方案:全部待办归入 8 条道 / 8 个写域,给批次与合并次序。
This commit is contained in:
2026-10-23 23:37:10 +08:00
parent c0ccd777ae
commit 49a257b34c
5 changed files with 756 additions and 5 deletions
+6 -2
View File
@@ -11,7 +11,7 @@
``` ```
docs/ docs/
├── README.md 本索引(阅读顺序 + 全量清单) ├── README.md 本索引(阅读顺序 + 全量清单)
├── 任务规划/ 统一待办登记簿(README 排序权威 + 6 个拆分文件) ├── 任务规划/ 统一待办登记簿(README 排序权威 + 8 个拆分文件)
├── 产品需求/ 产品需求设计文档(面向产品的需求基线) ├── 产品需求/ 产品需求设计文档(面向产品的需求基线)
├── 架构设计/ 全局架构与设计方法论 ├── 架构设计/ 全局架构与设计方法论
├── 子系统设计/ 各功能子系统的设计说明 ├── 子系统设计/ 各功能子系统的设计说明
@@ -192,6 +192,7 @@ docs/
| [`CH395F_Trap_Records.md`](问题记录/CH395F_Trap_Records.md) | CH395F 以太网控制器陷阱台账 | | [`CH395F_Trap_Records.md`](问题记录/CH395F_Trap_Records.md) | CH395F 以太网控制器陷阱台账 |
| [`GD5F2GQ5UE_Trap_Records.md`](问题记录/GD5F2GQ5UE_Trap_Records.md) | GD5F2GQ5UE SPI NAND 陷阱台账 | | [`GD5F2GQ5UE_Trap_Records.md`](问题记录/GD5F2GQ5UE_Trap_Records.md) | GD5F2GQ5UE SPI NAND 陷阱台账 |
| [`SD2506_Trap_Records.md`](问题记录/SD2506_Trap_Records.md) | SD2506 RTC 陷阱台账 | | [`SD2506_Trap_Records.md`](问题记录/SD2506_Trap_Records.md) | SD2506 RTC 陷阱台账 |
| [`采集与数据处理短板评测.md`](问题记录/采集与数据处理短板评测.md) | 对照参考项目评测采集/遥测/录波/开入开出的完成度与缺口,给出补齐顺序(2026-10-23) |
--- ---
@@ -207,6 +208,9 @@ docs/
| [`UI_自动化测试流程.md`](UI设计/UI_自动化测试流程.md) | UI 模拟器像素回归(ui-verify 五步) | | [`UI_自动化测试流程.md`](UI设计/UI_自动化测试流程.md) | UI 模拟器像素回归(ui-verify 五步) |
| [`LVGL模拟器部署与使用说明.md`](UI设计/LVGL模拟器部署与使用说明.md) | PC 端 LVGL 模拟器部署与使用 | | [`LVGL模拟器部署与使用说明.md`](UI设计/LVGL模拟器部署与使用说明.md) | PC 端 LVGL 模拟器部署与使用 |
| [`RemoDispBus协议与接收设计说明.md`](UI设计/RemoDispBus协议与接收设计说明.md) | 远端显示总线协议与接收设计 | | [`RemoDispBus协议与接收设计说明.md`](UI设计/RemoDispBus协议与接收设计说明.md) | 远端显示总线协议与接收设计 |
| [`页面补齐规划.md`](UI设计/页面补齐规划.md) | 27 个空叶子页面的归并、前置能力(数据快照层/数值编辑)与分批顺序(2026-10-23) |
| [`UI_数据供给设计说明.md`](UI设计/UI_数据供给设计说明.md) | 页面实时数据的高内聚低耦合方案:快照推送(rt/par 双通道)、写路径、记录 reader 注入(2026-10-23) |
| [`页面扩充详细方案.md`](UI设计/页面扩充详细方案.md) | 27 个空叶子 + 3 页回炉的逐页方案:行表、数据源、组件、分批与预算(2026-10-23) |
| `mockups/` | 各页面参考图与说明 | | `mockups/` | 各页面参考图与说明 |
--- ---
@@ -231,7 +235,7 @@ docs/
| 位置 | 内容 | | 位置 | 内容 |
|---|---| |---|---|
| [`任务规划/`](任务规划/README.md) | **统一待办登记簿(文件夹)**——`README.md` = 排序权威(波次 W1~W7)+ 编号空间 + 维护约定;`W1-采集保护收尾.md` = 当前波次任务卡(里程碑 × 并行道 × 五字段);`登记簿.md` = N/S/T-x 长期观察;`排期详述.md` / `暂缓-RS485.md` / `测试与架构专项.md` / `基线与待确认.md` = 波内详表 / 冻结簇 / 专项 / 基线;只保留未闭环项,完成即删 | | [`任务规划/`](任务规划/README.md) | **统一待办登记簿(文件夹)**——`README.md` = 排序权威(波次 W1~W8)+ 编号空间 + 维护约定;`W1-采集保护收尾.md` = 当前波次任务卡(里程碑 × 并行道 × 五字段);`W8-数据可信.md` = 下一波次(通道标定 → 遥测链 → 运行参数,2026-10-23 定项);`登记簿.md` = N/S/T-x 长期观察;`排期详述.md` / `暂缓-RS485.md` / `测试与架构专项.md` / `基线与待确认.md` = 波内详表 / 冻结簇 / 专项 / 基线;**`并行分道方案.md` = 待办横向归道(写域 域1~域8 + 道A~道H + 批次 + 合并次序)**;只保留未闭环项,完成即删 |
| `硬件平台/` | 网表详细分析报告与语义图(V0.0 / V0.1);**[`ADC通道映射说明.md`](硬件平台/ADC通道映射说明.md)——V0.1 十七路 ADC 语义/网名/通道号权威映射表(固件取数、UI 显示、自检注入以此为准)** | | `硬件平台/` | 网表详细分析报告与语义图(V0.0 / V0.1);**[`ADC通道映射说明.md`](硬件平台/ADC通道映射说明.md)——V0.1 十七路 ADC 语义/网名/通道号权威映射表(固件取数、UI 显示、自检注入以此为准)** |
| `芯片手册/` | 外部芯片数据手册转录(CH395F / GD5F2GQ5UE / SD2506 / TPAFE5160 / RTL8305NBI 等) | | `芯片手册/` | 外部芯片数据手册转录(CH395F / GD5F2GQ5UE / SD2506 / TPAFE5160 / RTL8305NBI 等) |
| `images/` | 文档技术配图(`.svg` 产物,由 `tools/arch_diagram/`、`tools/refgraph/` 生成) | | `images/` | 文档技术配图(`.svg` 产物,由 `tools/arch_diagram/`、`tools/refgraph/` 生成) |
+11 -2
View File
@@ -9,7 +9,9 @@
> |---|---|---| > |---|---|---|
> | `README.md`(本文件) | 编号空间(§0)· 未闭环一览(§1)· **推进顺序权威(§2)** · 维护约定(§3) | 低频;仅主工作树 | > | `README.md`(本文件) | 编号空间(§0)· 未闭环一览(§1)· **推进顺序权威(§2)** · 维护约定(§3) | 低频;仅主工作树 |
> | `W1-采集保护收尾.md` | 当前波次:里程碑 / 并行道 / 任务卡(DoD·依赖·资源·写范围·状态) | **高频**——状态流转只改它;Lead 在 claim/完成时更新 | > | `W1-采集保护收尾.md` | 当前波次:里程碑 / 并行道 / 任务卡(DoD·依赖·资源·写范围·状态) | **高频**——状态流转只改它;Lead 在 claim/完成时更新 |
> | `W8-数据可信.md` | **下一波次(2026-10-23 用户定项)**:通道标定 → 遥测链 → 运行参数段;含事实基线、折算模型、**14 张任务卡**(含"已知电压注入验证"与"端子变比确认"两卡)、前置决策 | **高频**——开工后状态流转只改它 |
> | `排期详述.md` | W4 结构债 / W5 验证常态 波内详表 | 低频 | > | `排期详述.md` | W4 结构债 / W5 验证常态 波内详表 | 低频 |
> | `并行分道方案.md` | **待办横向归道**:文件级写域(域1~域8)· 八条道(道A~道H)· 批次与合并次序 · 不能并行的事项 | 低频——分道或批次变化时改;**明细不复制**,只做归道 |
> | `暂缓-RS485.md` | B2 RS-485 整簇冻结清单(用户决定) | 极少 | > | `暂缓-RS485.md` | B2 RS-485 整簇冻结清单(用户决定) | 极少 |
> | `登记簿.md` | N-x / S-x / T-x 长期登记(网络 / 存储 / 硬件 / 测试 / 报告并轨) | 中频——新发现进对应表 | > | `登记簿.md` | N-x / S-x / T-x 长期登记(网络 / 存储 / 硬件 / 测试 / 报告并轨) | 中频——新发现进对应表 |
> | `测试与架构专项.md` | P1-10 收尾 + S1x / A-x 专项 | 低频 | > | `测试与架构专项.md` | P1-10 收尾 + S1x / A-x 专项 | 低频 |
@@ -31,7 +33,9 @@
> **2026-10-12 B4/B5 销项——W1 功能主线代码侧全部完成**; > **2026-10-12 B4/B5 销项——W1 功能主线代码侧全部完成**;
> **2026-10-12 用户决定:新 W1 = ADC 采集 + 保护相关功能收尾闭环(B6~B10 + N-33),W2~W7 顺延**, > **2026-10-12 用户决定:新 W1 = ADC 采集 + 保护相关功能收尾闭环(B6~B10 + N-33),W2~W7 顺延**,
> 波次切换为「里程碑 × 并行道 × 任务卡(五字段)」模式(方法论 → `../环境与部署/并行任务工作树方案.md` §7.3); > 波次切换为「里程碑 × 并行道 × 任务卡(五字段)」模式(方法论 → `../环境与部署/并行任务工作树方案.md` §7.3);
> **2026-10-12 解耦为 `docs/任务规划/` 文件夹**(README 索引 + 6 个职责单一文件;编号空间与 §2 排序权威不变)。 > **2026-10-12 解耦为 `docs/任务规划/` 文件夹**(README 索引 + 6 个职责单一文件;编号空间与 §2 排序权威不变);
> **2026-10-23 新增 W8「数据可信」**(用户定项:通道标定先于 UI 页面与结构债;14 张卡见 `W8-数据可信.md`),
> 执行序紧随 W1、排在 W3/W4 之前(W2/W3 槽位保留不复用的规则不变)。
--- ---
@@ -72,6 +76,7 @@
| 测试 / 基础设施 | 6 | T-7(CI runner + 推送闭环 + 第二机交叉验证)· S12(断言宏)· S1-c(可选单测)· A-4(采集链路测试约束,RS485 侧随 B2 暂缓)· A-5 残余(CI 体积门禁盲区)· D7(串口助手 A6/A7 待 CH340) | | 测试 / 基础设施 | 6 | T-7(CI runner + 推送闭环 + 第二机交叉验证)· S12(断言宏)· S1-c(可选单测)· A-4(采集链路测试约束,RS485 侧随 B2 暂缓)· A-5 残余(CI 体积门禁盲区)· D7(串口助手 A6/A7 待 CH340) |
| UI | 1 簇 | U 簇(27 页标准化,**本轮不排期**) | | UI | 1 簇 | U 簇(27 页标准化,**本轮不排期**) |
| **暂缓** | 2 簇 | **B2 RS-485 整簇**(2026-10-12 用户决定,`暂缓-RS485.md`)· **N-27 内存优化簇剩余部分**(2026-10-15 用户裁定:R-2 后半 / R-3 / R-4 / R-6 不排期,理由与重开条件见 `../问题记录/项目审查与优化建议报告.md` §5.3;**已落地的 R-9 与 `mem-budget` 门禁、台账、趋势、观测不回退也不暂缓**) | | **暂缓** | 2 簇 | **B2 RS-485 整簇**(2026-10-12 用户决定,`暂缓-RS485.md`)· **N-27 内存优化簇剩余部分**(2026-10-15 用户裁定:R-2 后半 / R-3 / R-4 / R-6 不排期,理由与重开条件见 `../问题记录/项目审查与优化建议报告.md` §5.3;**已落地的 R-9 与 `mem-budget` 门禁、台账、趋势、观测不回退也不暂缓**) |
| **数据可信(W8)** | 1 簇 · **14 张卡** | 已知电压注入验证 · 端子变比确认 · 通道标定系数与折算 · 标定落盘 · 未标定即闭锁 · 下游三常数重定 · 量纲回归 · 遥测快照 200 ms · 运行参数段 · 频率点绑定(详表 `W8-数据可信.md`) |
> **网络侧 E-xx 存量项**(历史编号族,属主文档已于 2026-10-15 删除,编号冻结见 > **网络侧 E-xx 存量项**(历史编号族,属主文档已于 2026-10-15 删除,编号冻结见
> `docs/编号规范.md` §4.3):E-25 / E-27 / E-28 挂 C1(net 层跨上下文收口,见 `排期详述.md` §1); > `docs/编号规范.md` §4.3):E-25 / E-27 / E-28 挂 C1(net 层跨上下文收口,见 `排期详述.md` §1);
@@ -100,10 +105,11 @@
| 波次 | 内容 | 为什么在这 | | 波次 | 内容 | 为什么在这 |
|---|---|---| |---|---|---|
| **W1 采集+保护收尾** | **里程碑制 + 并行道**:M1 台架闭环 ✅ 达成(B6 ✅→N-33 ✅)∥ M2 功能面(代码道 B7 ✅→{B8∥B9})→ M3 送检(B10,Fixed Date)——任务卡/判据/写范围见 `W1-采集保护收尾.md` | **用户决定(2026-10-12):先把 ADC 采集、保护等相关功能完成**。B4/B5 代码已落地但未台架闭环、功能面不完整(定值不落盘 / 无频率保护 / 无动作记录 / 栈两处 FAIL)——本波收口到"可用 + 可验收";真约束只有**台架**与**送检窗口**两个稀缺资源,其余任务按写范围切分并行 | | **W1 采集+保护收尾** | **里程碑制 + 并行道**:M1 台架闭环 ✅ 达成(B6 ✅→N-33 ✅)∥ M2 功能面(代码道 B7 ✅→{B8∥B9})→ M3 送检(B10,Fixed Date)——任务卡/判据/写范围见 `W1-采集保护收尾.md` | **用户决定(2026-10-12):先把 ADC 采集、保护等相关功能完成**。B4/B5 代码已落地但未台架闭环、功能面不完整(定值不落盘 / 无频率保护 / 无动作记录 / 栈两处 FAIL)——本波收口到"可用 + 可验收";真约束只有**台架**与**送检窗口**两个稀缺资源,其余任务按写范围切分并行 |
| **W8 数据可信** | **通道标定 → 遥测链 → 运行参数**:M4 系数与量纲 / M5 遥测链 / M6 运行参数与点表;14 张卡与事实基线见 `W8-数据可信.md` | **用户决定(2026-10-23):下一步做通道标定,先于 UI 页面与结构债**。它是唯一"改一处、全链受益"的入口(`App/task/adc_task.c:335` 是码值→工程量的唯一位置),也是 W6 页面与 104 遥测的共同前置——先做页面则 `ui_data_feed` 组装的码值帧要返工。**编号是分配序,执行序以本表从上到下为准**:本波紧随 W1,排在 W3/W4 之前。⚠ 2026-10-23 补记:ADC 至今**从未采过已知电压**(连极性都没验过,见 `W8-数据可信.md` §2.6),故第一张卡是"已知电压注入验证"——只需一块万用表,不需要信号源/示波器,是开工的第一刀 |
| **W3 预算与内存** | ⏸ **整簇暂缓**(用户裁定 2026-10-15):~~缩堆 56→32 KB → R-2 后半(29.5 KB→CCM)→ R-3 / R-4 / R-6 逐项评估~~。本簇已落地的只有 **R-9 ✅(2026-10-15)**;R-5 已判定不可行 | **不再排期**:没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测。**W3 槽位保留、不重编号**(避免全库改 W4~W7 引用)。重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3 | | **W3 预算与内存** | ⏸ **整簇暂缓**(用户裁定 2026-10-15):~~缩堆 56→32 KB → R-2 后半(29.5 KB→CCM)→ R-3 / R-4 / R-6 逐项评估~~。本簇已落地的只有 **R-9 ✅(2026-10-15)**;R-5 已判定不可行 | **不再排期**:没有功能在等这块预算,而搬迁要动 scatter、要逐条过 DMA 可达性清单、缩堆还要上板复测。**W3 槽位保留、不重编号**(避免全库改 W4~W7 引用)。重开条件 → `../问题记录/项目审查与优化建议报告.md` §5.3 |
| **W4 结构债** | **C6(S-3)→ C3(N-2)→ C1 net 层跨上下文收口 → C5(含 N-23 残余)→ N-22/N-25/N-28**(详表 `排期详述.md` §1) | 无紧急,按性价比排:C6 灭 IWDG 误复位机制根源;C1 消化 E-25/E-27/E-28(原 ACCEPT+SEND pending 化已收口),体量大、验证重,放后(N-23 钩子已落地 2026-10-12,残余并入 C5)。⚠ 原挂 C3 的 **N-24(日志逐条开关)已于 2026-10-15 单独修复销项**,C3 只剩 N-2 观察项 | | **W4 结构债** | **C6(S-3)→ C3(N-2)→ C1 net 层跨上下文收口 → C5(含 N-23 残余)→ N-22/N-25/N-28**(详表 `排期详述.md` §1) | 无紧急,按性价比排:C6 灭 IWDG 误复位机制根源;C1 消化 E-25/E-27/E-28(原 ACCEPT+SEND pending 化已收口),体量大、验证重,放后(N-23 钩子已落地 2026-10-12,残余并入 C5)。⚠ 原挂 C3 的 **N-24(日志逐条开关)已于 2026-10-15 单独修复销项**,C3 只剩 N-2 观察项 |
| **W5 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · D7 串口助手 · S12 · S1-c · A-5(详表 `排期详述.md` §2) | 窗口性,逢机顺带,不单独排期 | | **W5 验证常态** | P1-10 收尾 · T-7 CI · D2 N-3 · D5 N-16 · D6 N-17 · D7 串口助手 · S12 · S1-c · A-5(详表 `排期详述.md` §2) | 窗口性,逢机顺带,不单独排期 |
| **W6 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5)。**2026-10-15 用户裁定启动**(覆盖 2026-10-11 的「本轮不排期」):已开智能体团队,第一波 **U1 令牌层 ∥ U4 门禁补强** 并行进行中;U3 为地基串行段(独占注册文件),U2/U5 排在 U3 之后 ⚠ **U5 暂缓(2026-10-20 用户裁定)**:剩余页面**尚未规划**,本轮不补页 —— 现存 7 个 `ui_page_*.c` 即当前全部内容,报告"27 页"是目标数不可当差集清单。U1–U4 已全部落地,故 U5 未来开工时是纯增量活(实测新增一页 = 3 处人工 + 1 条生成器命令,且 `ui-golden` 已在提交门禁兜像素)。 | **W6 UI 扩展** | U4 残余(golden + 字符集差集挂门禁)→ U1 令牌层 → U2/U3 → **27 页**落地 | 产品驱动、体量大,需单独立项(顺序按 `docs/问题记录/项目审查与优化建议报告.md` §6.5)。**2026-10-15 用户裁定启动**(覆盖 2026-10-11 的「本轮不排期」):已开智能体团队,第一波 **U1 令牌层 ∥ U4 门禁补强** 并行进行中;U3 为地基串行段(独占注册文件),U2/U5 排在 U3 之后 ⚠ **U5 暂缓(2026-10-20 用户裁定)**:剩余页面**已出规划(`docs/UI设计/页面补齐规划.md`,2026-10-23:27 个空叶子归并为 7 模块 + 2 项前置能力),但仍未排期**,本轮不补页 —— 现存 7 个 `ui_page_*.c` 即当前全部内容,报告"27 页"是目标数不可当差集清单。U1–U4 已全部落地,故 U5 未来开工时是纯增量活(实测新增一页 = 3 处人工 + 1 条生成器命令,且 `ui-golden` 已在提交门禁兜像素)。**2026-10-23 补充**:U5 的 `ui_data` / `ui_data_feed` 需要真数据才有意义,故 **U5 最早在 W8 的 M4 之后开工**(依据见 `W8-数据可信.md` §10) |
| **W7 仓库决策** | **N-29** `.git` **235 MB** + 图片 36.3 MB | **已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(`git filter-repo` 历史重写影响未推送提交与协作者) | | **W7 仓库决策** | **N-29** `.git` **235 MB** + 图片 36.3 MB | **已决策(2026-10-11):暂不处理、登记观察**——推送/协作前重评(`git filter-repo` 历史重写影响未推送提交与协作者) |
| **暂缓** | **B2 RS-485 整簇**(`暂缓-RS485.md`) | **用户决定(2026-10-12):当前不处理 RS-485** | | **暂缓** | **B2 RS-485 整簇**(`暂缓-RS485.md`) | **用户决定(2026-10-12):当前不处理 RS-485** |
| **硬件改版** | N-18 8 路电气量全接 TPAFE(V0.2) | 下一版硬件;固件侧已用语义映射隔离,改版只动映射表 | | **硬件改版** | N-18 8 路电气量全接 TPAFE(V0.2) | 下一版硬件;固件侧已用语义映射隔离,改版只动映射表 |
@@ -116,6 +122,9 @@
W1 收尾 台架道: B6✅→N-33✅(M1 ✅ 2026-10-12) ∥ 代码道: B7✅→B8✅→B9✅(M2 ✅ 2026-10-12) → B10 送检(M3, Fixed Date) 详表 W1-采集保护收尾.md W1 收尾 台架道: B6✅→N-33✅(M1 ✅ 2026-10-12) ∥ 代码道: B7✅→B8✅→B9✅(M2 ✅ 2026-10-12) → B10 送检(M3, Fixed Date) 详表 W1-采集保护收尾.md
(B4 IEC104 ✅ / B5 protectTask ✅ / B6 台架复测 ✅ / B7 定值持久化+软压板 ✅ / N-33 栈收口 ✅ / B8 频率保护 ✅ / B9 SOE 动作记录 ✅ 2026-10-12 均已销项;台账三件套 ✅) (B4 IEC104 ✅ / B5 protectTask ✅ / B6 台架复测 ✅ / B7 定值持久化+软压板 ✅ / N-33 栈收口 ✅ / B8 频率保护 ✅ / B9 SOE 动作记录 ✅ 2026-10-12 均已销项;台账三件套 ✅)
↓ ↓
W8 数据可信 通道标定 → 遥测链 → 运行参数(M4 系数与量纲 → M5 遥测链 → M6 运行参数与点表) 详表 W8-数据可信.md
关键路径: 量程口径 → 标定模块 → 落盘 → 未标定即闭锁 → 量纲回归;W6 可在 M4 后开工
↓
W3 预算 ⏸ 整簇暂缓(2026-10-15 用户裁定);R-9 池瘦身 ✅ 已落地不回退 W3 预算 ⏸ 整簇暂缓(2026-10-15 用户裁定);R-9 池瘦身 ✅ 已落地不回退
↓ ↓
W4 结构 C6(S-3) → C3(N-2) → C1 net 层跨上下文收口 → C5(含 N-23 残余) → N-22/25/28 W4 结构 C6(S-3) → C3(N-2) → C1 net 层跨上下文收口 → C5(含 N-23 残余) → N-22/25/28
+388
View File
@@ -0,0 +1,388 @@
# W8 数据可信(通道标定 → 遥测链 → 运行参数)
> **一句话结论**:全项目现在唯一"改一处、全链受益"的入口是 `App/task/adc_task.c:335` 的
> `frame[s] = (float)code;`——它是码值变成工程量的**唯一**位置。本波把它拆成三段:
> 系数可信(M4)→ 遥测可信(M5)→ 整定可信(M6)。做完之后保护定值、104 遥测、
> UI 交流量才第一次有名副其实的数值。
>
> **本文定位**:W8 波次的任务卡与验收判据。**排序权威在 `docs/任务规划/README.md` §2**;
> 本文只写"这一波做什么、按什么判据算做完"。上游分析见
> `docs/问题记录/采集与数据处理短板评测.md`(四类短板的成因与分档)。
>
> **修订**:2026-10-23 建档(用户决定:下一步做通道标定,先于 UI 页面与结构债)。
> 2026-10-23 补卡:用户指出"ADC 还没采过真实电压"——经核查成立且更严重(连极性都没验过,
> 见 §2.6),故新增"已知电压注入验证"与"端子变比确认"两卡,并把 M4 的承诺边界改为
> "引脚电压"(`eng=0`),"端子二次值"降为依赖变比的条件项。
---
## 1. 为什么是这一波
### 1.1 唯一插入点
```c
/* App/task/adc_task.c:333-335 */
/* ⚠ L1-5 通道标定尚未实现(缺标准源)→ 暂以**原始码值**充作工程量(系数 = 1)。 */
frame[s] = (float)code;
```
采样环、相量、保护、频率、104、UI 全部在这行下游。改它,下游一次性获得工程量含义;
不改,每一层都在给码值编自己的故事。
### 1.2 三层各自记着"系数 = 1"
| 层 | 位置 | 原文口径 |
|---|---|---|
| 保护判据 | `App/algo/prot_elm.h:25` | "工程量↔码值换算系数暂为 1(L1-5 标定未实现,同 phasor 层口径)" |
| 104 上送 | `docs/子系统设计/IEC104上行设计说明.md` §4 | "现读数为**原始码值**(L1-5 标定未实现,系数=1 口径与之一致)" |
| 相量 / 频率 | `docs/算法/采集与算法层设计说明.md` §11 | "现以原始码值……标定未实现" |
三条独立记录指向同一个根。**这不是三个问题,是一个问题的三种表现。**
### 1.3 为什么排在 UI 与结构债之前
| 候选 | 判据 |
|---|---|
| **W8 数据可信(本波)** | 它是 W6 页面与 104 遥测的**共同前置**:先做页面,`ui_data_feed` 组装出的是码值帧,标定落地后组装逻辑要重写一遍 = 纯返工 |
| W6 剩余 27 页 | 依赖 W8 的产出(`ui_data_rt_t.eng` 才能填 1);现在做只能继续塞占位值 |
| W4 结构债 | 无人在等;C1 net 层收口体量大、验证重 |
| 录波 + 104 文件传输 | 独立立项,且依赖工程量(录波通道必须有物理量含义) |
**代价对比**:本波 S 段约 200 行(系数表 + 折算 + 落盘),W6 那 30 页次是几千行。
---
## 2. 事实基线(2026-10-23 代码级核对)
> 本节所有结论都可在代码里逐条复查,行号为核对时快照。**不依赖任何文档转述。**
### 2.1 通道与量纲
| 语义通道 | 转换器 | 码值格式 | LSB | 前端 | 板级系数(输入侧) | 交流可用性 |
|---|---|---|---|---|---|---|
| UA | TPAFE5160 | 16 位双极性 ±5 V | 152.59 µV | 1k 串 + 1k 到地(2:1) | **305.18 µV/码** | ✅ 可用 |
| UN | TPAFE5160 | 同上 | 152.59 µV | 同上 | **305.18 µV/码** | ✅ 可用 |
| IA | TPAFE5160 | 同上 | 152.59 µV | 同上 | **305.18 µV/码** | ✅ 可用(缺 A/V 变比) |
| UB / UC | STM32 ADC1 | 12 位单极性 0~3.3 V | 805.66 µV | 同上 | **1611.3 µV/码** | ❌ 削顶(无中点偏置) |
| IB / IC / IN | STM32 ADC1 | 同上 | 805.66 µV | 同上 | **1611.3 µV/码** | ❌ 削顶 |
| TEMP | STM32 ADC1 | 同上 | 805.66 µV | 同上 | 热敏非线性 | — 不纳入线性标定 |
- 通道数:`ADC_SEM_COUNT = 9`(8 电气 + 温度),定义见 `App/algo/adc_input.h`。
- 分压比出处:`docs/硬件平台/ADC通道映射说明.md` §7"前端偏置"行(每路 1k 串联 + 1k 到 `*_GND`)。
- ⚠ **两处文档口径冲突,落地前必须定死**:`docs/硬件平台/ADC通道映射说明.md` §1 写 TPAFE "±10 V",
§7 写"默认 ±5 V(RANGE 接 GND)、LSB 152.59 µV"。按 LSB × 65536 = 10 V **跨度**反推 §7 正确,
§1 的"±10V"应理解为跨度而非正负范围。**这个不定死,TPAFE 侧系数差一倍。**
- ⚠ **上表的"板级系数"只到 ADC 引脚,不到端子**(2026-10-23 补充):1k 串 + 1k 到地这组网络,
`docs/硬件平台/V0.0_网表详细分析报告.md` §4.7 定性为"**源阻抗匹配(手册推荐做法,非分压)**";
端子到引脚之间还有一级子板/端子板的变比,而**仓库里没有任何文档给出该变比**
(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图)。故
"端子二次值 = 码 × 上表系数"**不成立**,详见 §2.6 与卡 0。
### 2.2 保护判据的量纲错配(本波要修的核心)
`App/algo/prot_elm.c` 的 `prot_elm_run()` 把相量有效值原样送进判据:
```c
meas[i] = p.fAmSQ; /* fAmSQ = 原始码值的有效值 */
...
m = meas[i]; /* 判据侧 */
set = prot_set_get_f(cfg->set_id); /* 定值侧,单位 A / V(二次值) */
```
而 `App/algo/prot_set.c` 的默认值是工程单位:`OC1 电流定值 = 10.0 A`(`0x8858`)、
`过压 = 120.0 V`(`0x8029`)。**码值量级远大于这些定值上限(100 A / 200 V)**——TPAFE 侧
台架开机实测 `UA=11429 / UN=11454 / IA=11452`(16 位),STM32 侧 `UB=1018 / IC=1069`(12 位),
两侧都比定值上限高 1~2 个数量级。故"过流/过压元件一旦投退即恒动作"不是推测,是量纲决定的必然结果。
> 台架此前"通过"是因为没有一条判据检查"**不该动作时不动作**"。本波的任务卡把这条固化成回归用例。
### 2.3 三个必须同步重定的下游常数
| # | 位置 | 现值 | 语义 | 标定后必须做什么 |
|---|---|---|---|---|
| 1 | `App/algo/freq.h:55` | `FREQ_AMP_MIN 50.0f` | 现在是"50 个码值"(几乎恒成立,等于没有幅值门) | 改为二次值口径并重新论证(对 100 V PT,50 V 是合理的"无波形"门限——但结论要写清依据,不能靠巧合) |
| 2 | `App/protocol/iec104/iec104_pts.c:23` `k_yc[].deadband` | 9 点全 10.0(freq 0.5) | 注释写"工程量绝对值",实际是码值 | 按各点工程量重定(建议规则:额定值的 0.5%) |
| 3 | `App/algo/prot_set.c` `g_prot_set_meta[]` | 10 A / 120 V / 15 V … | 现在是"跟码值比"的工程单位 | 复核默认值与 `min`/`max` 范围;**标定后它们才名副其实**,此前一直是错的 |
### 2.4 点表与数据源现状
`App/protocol/iec104/iec104_pts.c` 的 `k_yc[]`(9 点):
| IOA | 绑定 | 说明 |
|---|---|---|
| `0x4011` 1Ua | `ADC_SEM_UA` | ✅ 有源 |
| `0x4012` 1Ub / `0x4013` 1Uc | `-1` | 削顶 → 恒 IV(**故意不绑**,不是遗漏) |
| `0x4014` 1U0 | `ADC_SEM_UN` | ✅ 有源 |
| `0x4015` 1Ia | `ADC_SEM_IA` | ✅ 有源 |
| `0x4016`/`0x4017`/`0x4018` 1Ib/1Ic/1I0 | `-1` | 削顶 → 恒 IV |
| `0x401D` 1f | `-1` | 注释"L1-7 未实现"——**已过时**:B8 已落地自适应窗测频(`freq_get()` 可用),本波把它接上 |
### 2.5 配置引擎的硬约束(决定落盘方案)
`App/cfg/cfg_file.h`:
| 宏 | 值 | 对本波的含义 |
|---|---|---|
| `CFG_FILE_MAX_NAME_LEN` | 15 | 段名/键名须 ≤15 字符(超长注册被拒) |
| `CFG_FILE_MAX_KEYS` | 16 | **单段键数上限 16** → 8 通道 ×(k + b)= 16 正好顶格,再加一个就爆 |
| `CFG_FILE_MAX_SECTIONS` | 8 | 已用 2(`network` / `ftp`),余 6 |
| 回调约束 | `data_size ≤ 64` 才可挂 `p_cb` | 若把 9 通道 × 8 B 塞一段 = 72 B 会超;拆两段后各 33 B / 32 B(**但本波不需要回调**——RAM 副本即生效值) |
| 值类型 | 仅 `UINT` / `IP4` / `MAC` / `STR` | `s_decode_uint()` 用 `strtoul` 且校验 `v > max_v` → **负的零点偏移无法干净表达** |
---
### 2.6 验证现状:ADC 从未采过已知电压
这是本波**最大的隐藏前提**,也是排期需要补卡的原因(2026-10-23 用户提出)。
| 证据 | 说明 |
|---|---|
| L1-3 台架判据(2026-10-10) | 只验了"9 通道全部转换成功 + 零超时 + 互异非饱和 + 跨次开机读数不同"——证明**通路活**,不证明**读数对**,连极性都没证 |
| `docs/硬件平台/ADC通道映射说明.md` §8 | 步骤 2(STM32 引脚注 0.5 V)**明标"尚未执行"**;步骤 1(TPAFE 注 1 V DC)**无执行记录**。两项挂账自 2026-10-09 |
| `docs/硬件平台/V0.0_网表详细分析报告.md` §5.1 第 6 条 | "AIN1 注入 1 V 直流 → UI ADC1 值变化 + U3.14 BUSY 脉冲(**首次功能级 ADC 验证**)"——**无执行记录**(该清单整体未跑) |
| 台架设备 | 无信号源、无示波器(`docs/测试说明/相量层单元测试说明.md` 已写明板端无信号源) |
**后果**:§2.1 的 `k` 是"从网表推的",不是"从实测来的"。而网表只覆盖主板电阻网络,
所以推出来的只能是"**µV/码 @ ADC 引脚**",推不出"**V/A @ 端子**"。
> 这不否定本波价值——"码值 → 引脚电压"本身就是巨大进步(保护判据从"跟码值比"
> 变成"跟电压比")。但它决定 M4 的**承诺边界**:M4 承诺到"引脚电压",
> "端子二次值"要等卡 0b 拿到变比。
>
> 另一个必须查清的现象:2026-10-10 首帧读数 TPAFE 侧 `UA=11429 / UN=11454 / IA=11452`、
> STM32 侧 `UB=1018 / UC=1044 / IB=943 / IC=1069 / IN=1052`——**同片各通道几乎相同**,
> 而"1k 到地"在无输入时本应把节点拉到 0 V。首帧本就不是稳态值,不能据此定论,
> 但也不能当成"已正常"。卡 0 的零点判据专门查这一条。
---
## 3. 目标与里程碑
**波次目标**:把"数"从原始码值推进到**有物理含义、有品质、有死区、能上送**的工程量。
| 里程碑 | 退出判据(全部满足才算完成) | 服务分类 |
|---|---|---|
| **M4 系数与量纲** | ① **至少 1 路电压通道经已知电压注入验证**(卡 0),斜率与理论 LSB 偏差 ≤2 %;② `adc_cal` 折算落地,采样环里是**引脚电压 V**而非码值(`eng=0`;若卡 0b 已给变比则直接到二次值 `eng=1`);③ 8 通道系数/零点可落盘、上电加载失败回退 ROM 默认;④ 三处下游常数按工程量重定并注明依据;⑤ "未标定 → 保护闭锁"生效;⑥ 量纲回归用例(不该动作时不动作)通过 | Standard |
| **M5 遥测链** | ① 200 ms 遥测快照模块产出值 + 品质;② 104 与 UI 共用同一份快照(不再各自取相量);③ 死区从编译期常量改为运行参数;④ 104 上送值与工程量一致(PC 主站读回核对) | Standard |
| **M6 运行参数与点表** | ① 运行参数段 `0x8020~0x8058` 可读写并持久化;② `0x401D` 频率点绑 `freq_get()`,品质位正确;③ 总召/周期/变位三种上送路径均取新值 | Standard |
---
## 4. 设计要点
### 4.1 折算模型:板级事实进 ROM,现场标定进 cfg
```
工程量[V 或 A] = (code + b) × k_f
k_f = k[µV/码] × 1e-6 (float,init/load 时算一次)
```
| 符号 | 含义 | 存哪 | 定标 |
|---|---|---|---|
| `k` | µV/码(通道灵敏度) | cfg 段,int32 **Q16**(µV/码 × 65536) | 默认 = 板级理论系数(见 §2.1 表) |
| `b` | 零点偏移(码值) | cfg 段,int32 | 默认 0 |
| `k_f` | V/码(运行时) | RAM,`adc_cal_init/load` 时由 `k` 派生 | 不落盘 |
**为什么存 µV 而不是直接存 V/码**:`k` 在 V/码 量级是 3×10⁻⁴,Q16 只有 20 个刻度(5 % 分辨率);
换成 µV/码 后是 305,Q16 有 2000 万个刻度。**单位选择本身就是精度决策**,不是记账方式。
**为什么 Q16 而不是参考项目的 Q10**:TPAFE 通道 `k = 305.18 µV/码`,Q10 只能表达
312(+0.16 %);Q16 表达 ≈2.0×10⁷(误差 < 0.001 %)。两者都占 4 字节,
Q16 把"系数定点舍入"这一项从误差预算里直接抹掉——没有理由不选它。
(参考项目用 2^10 是因为定点 DSP 乘法成本;本机有 FPU,运行时本来就是 float。)
int32 上限 2.15×10⁹,`k` 最大可表达 32767 µV/码,远大于实际需要。
**运行时不走定点**:`adc_cal_init/load` 时把 `k` 预乘成 `float k_f = k_uv × 1e-6f`,
逐点只做 `frame[s] = (float)(code + b) * k_f`。1 kHz × 9 通道 = 9k 次浮点乘/秒,可忽略。
### 4.2 三态可用性:标定 ≠ 可测
`k` 默认值是**板级理论系数**,此时工程量单位是"**端子电压**",不是二次值——因为还缺
互感器/子板变比。所以通道状态必须能区分三档,不能让消费者把端子电压当二次值:
```c
#define ADC_CAL_F_VALID 0x01u /* 该通道 k 已按变比标定 → 工程量为二次值 */
#define ADC_CAL_F_CLIPPED 0x02u /* 硬件削顶(单极性无偏置)→ 交流量不可信 */
```
| 通道 | `VALID` | `CLIPPED` | 消费者应如何对待 |
|---|---|---|---|
| UA / UN / IA | 标定后置位 | 0 | 可用于保护、计量、上送 |
| UB / UC / IB / IC / IN | 永不置位(V0.2 硬件改版前) | 1 | 只作码值监视;104 恒 IV(维持 `k_yc[]` 现有 `-1` 绑定) |
| TEMP | 0 | 0 | 不参与线性标定,页面显示 `--` |
`adc_cal_flags(sem)` 供 UI / 104 / 保护三处共用,映射到各自的品质位(104 的 `IV`/`OV`、
UI 快照的 `qds`)。
### 4.3 未标定即闭锁(本波唯一的行为变更)
保护判据拿"端子电压"跟"二次值定值"比,必然误动作。所以 M4 必须让
`protect_task` 多一个闭锁源:**UA/UN/IA 的 `VALID` 位未全置位 → 判据停走**。
- 与 L5-4 采样故障闭锁同构(`PROT_HF_LOCK_MASK` 那一套),不新增机制。
- 现有台架 `@test` 的期望会因此变化——**这是有意的**,需要在任务卡里同步更新判据。
- 台架调试需要旁路时,走编译期开关(仅 `DTU_BENCH` 构建),不进 cfg、不进 104。
### 4.4 落盘:拆两段,不碰引擎
`CFG_FILE_MAX_KEYS = 16`,8 通道 × (k + b) = 16 正好顶格,将来加一个键就爆。故拆成两段:
| 段名 | 键 | 字节 | 回调 |
|---|---|---|---|
| `[adc_cal]` | `k_ua` `k_un` `k_ia` `k_ub` `k_uc` `k_ib` `k_ic` `k_in` + `valid`(uint8 位图) | 8×4 + 1 = 33 | 不挂(RAM 副本即生效值,无需"立即应用") |
| `[adc_cal_ofs]` | `b_ua` … `b_in` | 8×4 = 32 | 不挂 |
段名 7 / 11 字符,键名 4 字符,均在 15 字符上限内。段数 2 → 总计 4/8,未逼近上限。
⚠ **负零点**:`cfg_file` 只有 `CFG_VAL_UINT`,`s_decode_uint()` 用 `strtoul` 并校验上界,
负值落盘会变成 `4294967291` 这种现场看不懂的数。两条路:
- **推荐**:给引擎补 `CFG_VAL_INT`(`strtol` + 有符号输出 + 上界按 `INT32_MIN/MAX` 校验),
约 30 行,两个 switch 各加一个分支。运行参数段(死区、系数)后面也要有符号值,一次做完。
- 备选:零点存"码值 + 32768 偏置"的 uint16——绕开引擎但要每个读点记住减偏置,属于给未来埋坑。
### 4.5 遥测快照:让 104 与 UI 共用一份上游
现在 104 的 `s_src_yc_read()` 自己遍历相量,UI 将来也要一份。两处各取 = 两处各自决定
"什么时候算新值""品质怎么判",迟早不一致。
本波引入 `App/algo/meas.c`:每 **200 ms** 从相量使用区取一次,产出
```c
typedef struct {
uint32_t seq; /* 只增;消费者据此判断是否换帧 */
uint32_t tick_ms;
uint8_t valid; /* 整帧有效 */
uint8_t rsv[3];
float yc[9]; /* 工程量(二次值或端子电压,由 flags 决定) */
uint16_t qds[9]; /* 每点品质:IV / NT / OV / CLIPPED */
uint8_t freq_valid;
float freq_hz;
} meas_snap_t;
```
- **发布者 = `adc_task`**:在 `phasor_run()` / `freq_run()` 之后按 200 ms 分频发布。生产者在
自己的上下文发布,与 `ui_data_feed` 同理——消费者不组装、不判断新旧。
- **跨任务读取 → 沿用 `phasor` 双区原子交换**:写侧填计算区、末尾翻转单字节活跃索引;
读侧先读索引再拷该区。`phasor` 已经是"adcTask 写 / protectTask 读"的同一形态,
**不是新机制**,不引入锁。
- 104 的 `s_src_yc_read()` 改为读快照(不再自己遍历相量)。
- W6 的 `ui_data_feed` 也读快照 → **同一份数据,两个消费者**,这是"高内聚"的具体落点。
- 200 ms 是**上送节拍**,不是平均窗:相量本身已经是 1 ms 刷新的有效值,再平均会引入滞后。
---
## 5. 任务卡(五字段;完成即销项删行)
> 资源图例:🔴 台架(COM6/ST-LINK,`bench.lock` 独占)· 🟡 外部(标准源 / 子板原理图)· 🟢 纯软件。
> 状态:⬜ 未开始 · 🟦 进行中。**新条目一律用语义标识,不新增字母+数字编号**
> (规则见 `docs/任务规划/README.md` §0)。
> **2026-10-23 新增"已知电压注入验证"与"端子变比确认"两卡**(序栏 0 / 0b 只为阅读顺序):
> 补的是 §2.6「ADC 从未采过已知电压」这一前置验证,不改动既有 1~12 的编号与引用。
| 序 | 任务 | DoD(可验证验收判据) | 硬依赖 | 资源 | 写范围 | 状态 |
|---|---|---|---|---|---|---|
| **0** | **已知电压注入验证(首次功能级 ADC 验证)** | 在**可安全接触的最低一级**(ADC 引脚侧或端子侧,二选一并在证据里写明注入点)用板载 3.3 V 轨经电位器注入 **3 个直流点**(≈0.3 / 1.0 / 2.0 V),每点**同时**用万用表读注入点实际电压 + 读 `adc_input_raw()` 码值:① 三点线性拟合 **R² ≥ 0.999**;② 注入点在引脚侧时,斜率须与 §2.1 理论值(TPAFE 6553 码/V、STM32 1241 码/V)偏差 **≤2 %**;在端子侧时把斜率记为**实测变比**;③ 注入 0 V(短接 AGND)零点 \|码\| ≤ 10(TPAFE)/ ≤ 5(STM32),并解释首帧 ~1000 码的来源;④ **逐通道映射确认**:8 路电气量逐个注入,确认"注入哪一路、哪一路语义变化",语义与下标不符即映射错;⑤ TPAFE 侧原"BUSY 有脉冲"判据**改用固件帧计数**(注入前后 `tpafe5160_frame_seq()` 仍严格 1000 Hz 递增)——不需要示波器;⑥ 结论写回 `docs/硬件平台/ADC通道映射说明.md` §8,把"尚未执行"改为实测值 + 日期 | 1 | 🔴 + 万用表(**不需信号源 / 示波器**) | `docs/硬件平台/ADC通道映射说明.md`、`docs/测试说明/boot_log_data/` | ⬜ |
| **0b** | **端子 / 子板变比确认** | 给出"端子电压 → ADC 引脚电压"的比值(万用表同时量端子与引脚,或查子板原理图后实测核对),写入 `docs/硬件平台/ADC通道映射说明.md`;据此判定 `eng` 能否置 1;数据缺失则本波只交付引脚电压并登记缺口 | 0 | 🟡 子板实物或原理图 | `docs/硬件平台/` | ⬜ |
| **1** | **TPAFE 量程口径定死并更正文档** | `docs/硬件平台/ADC通道映射说明.md` §1 与 §7 统一为"±5 V 满量程 = 10 V 跨度、LSB 152.59 µV",§1 的"±10 V"改为"10 V 跨度"或加括注;全仓搜 `±10 V` 无遗留歧义 | 无 | 🟢 | `docs/硬件平台/ADC通道映射说明.md` | ⬜ |
| **2** | **通道标定模块与折算函数** | 新增 `App/algo/adc_cal.c/h`:`adc_cal_init()` / `adc_cal_apply(sem, code)` / `adc_cal_flags(sem)` / `adc_cal_k_uv(sem)`;`adc_task.c:335` 改为调用折算,**输出单位 = ADC 引脚电压 V**(`eng=0`;端子变比由卡 0b 另存,不在本卡内混算);主机单测覆盖 8 通道 × 3 个码值点,期望值由 LSB 常数独立算得(不是抄实现);`@build` 0 错 0 警 | 1 | 🟢 | `App/algo/adc_cal.*`(新)、`App/task/adc_task.c`、`test/host/` | ⬜ |
| **3** | **`cfg_file` 补有符号整型值类型** | 新增 `CFG_VAL_INT`:`s_decode` 分支用 `strtol` + 范围校验,`s_gen_document` 输出带负号;主机单测覆盖 `-1` / `INT32_MIN` / 越界拒绝 / 往返一致;既有 `network`/`ftp` 段回归不变 | 无 | 🟢 | `App/cfg/cfg_file.c/.h`、`test/host/` | ⬜ |
| **4** | **标定系数落盘与整定入口** | 注册 `[adc_cal]` / `[adc_cal_ofs]` 两段(§4.4 布局);上电加载:段缺失/损坏/键非法 → 回退 ROM 理论系数 + `[ERR]` 留痕;`adc_cal_set()` 写值并置 `VALID`;主机单测覆盖"段损坏 → 回退默认且 flags 无 VALID" | 2、3 | 🟢 | `App/algo/adc_cal.*`、`App/cfg/` | ⬜ |
| **5** | **未标定即闭锁** | `protect_task.c` 新增闭锁源:UA/UN/IA 的 `VALID` 未全置位 → `prot_elm` 复位且本拍不 eval;边沿日志区分"未标定闭锁"与"采样故障闭锁";台架 `@test` 判据同步更新(默认构建下保护不动作是**期望行为**) | 2 | 🟢 + 🔴 | `App/task/protect_task.c`、`App/algo/prot_elm.*`、`test/` | ⬜ |
| **6** | **下游三常数按工程量重定** | ① `FREQ_AMP_MIN` 改为二次值口径并在注释里写清判据来源(对 100 V PT 为何取该值);② `k_yc[].deadband` 9 点按"额定 0.5 %"规则重定并注明;③ `g_prot_set_meta[]` 的 A/V 默认值与 `min`/`max` 复核,与二次值量程自洽;三处注释都指向同一份换算依据 | 2 | 🟢 | `App/algo/freq.h`、`App/protocol/iec104/iec104_pts.c`、`App/algo/prot_set.c` | ⬜ |
| **7** | **量纲回归用例(不该动作时不动作)** | 主机单测:给定定值 + 标定后的码值序列 → 断言"低于定值不动作 / 高于定值按延时动作 / 返回系数滞回正确";**用例里显式写出码值→二次值的换算**,使"码值当工程量"这个错配一旦复发立即 FAIL;覆盖 OC1/OC2/OC3/OL/OV/UV/3U0 七类 | 2、5、6 | 🟢 | `test/host/` | ⬜ |
| **8** | **遥测快照模块(200 ms)** | 新增 `App/algo/meas.c/h`:`meas_snap_t`(§4.5 布局)、`meas_tick()`(由 `adc_task` 200 ms 分频调用)、`meas_get()`、`meas_seq()`;并发沿用 `phasor` 双区 + 单字节索引翻转,读者无锁;主机单测覆盖 seq 递增、双区切换无撕裂、品质汇总(任一点 CLIPPED → 该点 `qds` 置位);RAM 增量 = 2×72 B ≈ 144 B | 2 | 🟢 | `App/algo/meas.*`(新)、`App/task/adc_task.c` | ⬜ |
| **9** | **104 遥测改读快照 + 死区改运行参数** | `s_src_yc_read()` 改为读 `meas_get()`;`k_yc[].deadband` 从编译期常量改为运行时取值(先读 ROM 默认,M6 后读运行参数段);PC 主站总召读回值与工程量一致(记录到 `docs/测试说明/boot_log_data/`) | 6、8 | 🟢 + 🔴 | `App/protocol/iec104/iec104_pts.c` | ⬜ |
| **10** | **运行参数段 `0x8020~0x8058`** | 新增 `App/algo/run_par.c/h`:至少含遥测死区(9 点)+ 通道系数覆盖;cfg 段持久化(键数受 16 限制,必要时再拆段);104 段读写映射(`C_RD`/`C_SE`);主机单测覆盖读写往返 + 越界拒绝 | 4、9 | 🟢 | `App/algo/run_par.*`(新)、`App/protocol/iec104/`、`App/cfg/` | ⬜ |
| **11** | **频率点 `0x401D` 绑定** | `k_yc[]` 的 `0x401D` 从 `-1` 改为频率源(YC 表加 `src` 类型区分 phasor / freq);`freq_valid()==0` 时品质 IV;PC 主站读回频率与 `freq_get()` 一致(±0.01 Hz) | 6 | 🟢 + 🔴 | `App/protocol/iec104/iec104_pts.c` | ⬜ |
| **12** | **8 通道两点标定与精度验收** | 电压 4 路(UA/UB/UC/UN)+ 电流 4 路(IA/IB/IC/IN)各做两点标定(零点 + 满度,温度不纳入),写入 `[adc_cal]` 并置 `VALID`;误差 ≤ 目标精度(待定:0.5 级 / 1 级);证据归档 | 0、0b、4 | 🟡 标准源 / 继保测试仪 | `docs/算法/`、`docs/测试说明/boot_log_data/` | ⬜ |
> **两张 🟡 外部依赖卡**:卡 0b(子板变比)与卡 12(标准源)。二者都**不阻塞** M4~M6 的软件道——
> M4 用板级 LSB 常数即可退出(`eng=0`),但"二次值"真正成立要靠 0b 的变比、`VALID` 置位要靠 12。
> 卡 0(引脚侧注入)**没有外部依赖**,只需一块万用表,是今天就能做的第一步。
---
## 6. 并行与顺序
```
① 事实与地基(可并行) 1 量程口径 ∥ 3 CFG_VAL_INT
1 ─→ 0 已知电压注入(🔴 台架 + 万用表)
↓(ROM 默认系数冻结须等 0 的结论)
② 核心折算(关键路径起点) 2 标定模块
↓
③ 三条分支(可并行)
├─ 4 落盘 ─→ 5 未标定闭锁 ─┐
├─ 6 三常数重定 ───────────┼─→ 7 量纲回归
└─ 8 遥测快照 ─→ 9 104 读快照 ─→ 10 运行参数段
6 ─→ 11 频率点绑定
台架道(🔴,串行):0 注入验证 → 5 闭锁验证 → 9 主站读回 → 11 频率核对
外部道(🟡,与软件道并行):0b 变比确认 → 12 标准源两点标定(本波末)
```
- **卡 0 与卡 2 可并行**(代码不依赖实测值),但**卡 4 的 ROM 默认系数必须等卡 0 的结论**;
若卡 0 实测斜率与理论值偏差 >2 %,**先查前端(分压/变比/焊接)再改系数**——用系数去凑
一个错误的斜率,会把硬件的错固化成"标定值"。
- **关键路径**:`2 → 4 → 5`(M4 退出条件全在这条线上)。卡 1 是它的前置事实输入,必须先做。
- **卡 3 可完全并行**:它只碰 `cfg_file.c`,与标定模块零交集。
- **卡 6 与卡 4 无依赖**(改的是三个常数的值,不依赖落盘),但**必须在卡 7 之前**完成,
否则回归用例断言的是错的期望。
- **WIP ≤ 2**:代码道最多 2 个并行(台架道 1 个),沿用 `docs/环境与部署/并行任务工作树方案.md` §7.3。
- **写范围冲突预警**:卡 2 / 4 都改 `App/algo/adc_cal.*`,必须同一分支顺序做;
卡 9 / 11 都改 `iec104_pts.c`,同上。
---
## 7. 前置决策(需用户拍板)
| # | 问题 | 备选 | 建议 |
|---|---|---|---|
| 1 | **未标定时保护是否闭锁** | ① 闭锁(安全)② 照常动作(现状,但量纲错配)③ 编译期开关 | **①**。拿端子电压比二次值定值等于保护瞎动作;现有台架期望要跟着改 |
| 2 | **精度目标** | 0.5 级 / 1 级 | 决定卡 12 的判据;也决定 `k` 是否需要 Q16(建议直接 Q16,成本为零) |
| 3 | **`CFG_VAL_INT` 是否本波做** | ① 补引擎类型(30 行)② 零点加偏置绕开 | **①**。运行参数段的死区/系数后面也要有符号值,一次做完;绕开的偏置约定是给未来埋坑 |
| 4 | **遥测快照由谁驱动 200 ms** | ① `adc_task` 分频(生产者发布)② `protect_task` 分频 ③ 独立软定时/新任务 | **①**。快照是"数据层",应由生产者在自己的上下文发布(与 `ui_data_feed` 同理);放协议任务会让 UI 在 104 未连接时拿不到新值,新任务则白占栈 |
| 5 | **温度通道是否纳入** | ① 不纳入(`flags=0`)② 补热敏曲线 | **①**。V0.1 温度只是机箱监视,非线性折算没有精度要求;纳入会拖长本波 |
| 6 | **端子 / 子板变比从哪来** | ① 有子板原理图(直接算)② 只有子板实物(万用表同时量端子与引脚)③ 都没有 | 决定 `eng` 能否置 1。②同样可行且够用;③则本波只交付"ADC 引脚电压",二次值登记为缺口 |
| 7 | **首次注入在哪一级** | ① ADC 引脚侧(验 LSB,排除前端)② 端子侧(验全链,但需先确认耐压) | **①**。引脚侧加 ≤2 V 不会烧任何东西;端子侧在变比未知前也只允许 ≤2 V 直流,**严禁直接上 100 V / 220 V** |
---
## 8. 风险
| 风险 | 触发条件 | 缓解 |
|---|---|---|
| **量程口径定错** | 卡 1 未做就开卡 2 | 卡 1 设为硬前置;系数差一倍时台架量级核对会立刻暴露(市电 220 V 量级对不上) |
| **`@test` 大面积红** | 卡 5 的闭锁改变默认行为 | 卡 5 与判据更新**同一提交**;先跑 A/B(`git stash` 对照)确认红的原因就是闭锁,不是新回归 |
| **`cfg` 键数顶格** | 后续给 `[adc_cal]` 加键 | 已按 8+1 / 8 拆段;加键前先看 `CFG_FILE_MAX_KEYS`,必要时再拆 |
| **标定值把保护"调坏"** | 卡 12 写入错误系数 | `adc_cal_set()` 校验范围(`k` 必须在板级系数 × [0.5, 2.0] 内)+ 写入后回读校验;越界拒绝并留 `[ERR]` |
| **削顶通道被当成可测** | 消费者只看 `k` 不看 `flags` | `adc_cal_flags()` 是唯一查询入口,`adc_cal_apply()` 不返回可用性;单测覆盖"CLIPPED 通道 104 恒 IV" |
| **快照双写** | 104 或 UI 侧也加一个 200 ms 计时器 | 卡 8 明确"唯一发布者 = `adc_task`";其余侧只读,评审时看 `meas_tick()` 的调用点数量 = 1 |
| **未验证的系数被当成定论** | 跳过卡 0 直接冻结 ROM 默认系数 | 卡 0 设为卡 4 的硬前置;实测斜率偏差 >2 % 时**先查前端**(分压/变比/焊接),不用系数去凑 |
| **加压烧板** | 变比未确认就往端子加额定电压 | 卡 0 只加 ≤2 V 直流;端子级上额定值必须在卡 0b 之后,且先量"端子对地通断"确认无直流通路 |
---
## 9. 范围边界(本波不做)
| 不做 | 理由 / 归属 |
|---|---|
| 录波 + 104 文件传输 | 独立立项;且录波通道必须先有工程量,排在本波之后 |
| 等周波调频(`docs/算法/继电保护功能复现规划.md` §3.1 的 L1-7) | 与标定正交;无标准源时判据不可达 |
| 功率 / 相位 / 功率因数 | **V0.1 硬件禁止**(`docs/硬件平台/ADC通道映射说明.md` §7 通道归属行:跨转换器无同一时刻性) |
| PT 断线判据 | 需要 `flags` 与遥信配合,排在 M5 之后单独评估 |
| 开入 / 开出固件 | 固件里**完全没有**这两类代码(`docs/问题记录/采集与数据处理短板评测.md` 登记),是另一个波次的量级 |
| 温度非线性折算 | 见 §7 决策 5 |
| 端子二次值(一次/二次变比换算) | **条件项**:卡 0b 拿到变比才做;拿不到则本波只到"ADC 引脚电压",`eng` 保持 0,缺口登记进 `docs/任务规划/登记簿.md` |
| UI 页面(含交流量回炉) | 归 W6;本波只保证 `meas_snap_t` 可供其消费 |
---
## 10. 与其它波次的关系
| 波次 | 关系 |
|---|---|
| **W1(收尾)** | W1 的 B10 送检卡里"L1-5 标定复核"依赖本波卡 12;本波是 B10 的前置 |
| **W6(UI)** | 本波交付 `meas_snap_t` + `adc_cal_flags()` → W6 的 `ui_data_rt_t` 才能填 `eng`(M4 后为 0 = 引脚电压,卡 0b 之后为 1 = 二次值),交流量页第 7 行"标定状态"才有真值。**W6 应在本波 M4 之后开工**,不必等 M6 |
| **W4(结构债)** | 无交集 |
| **N-18(V0.2 硬件改版)** | 本波的 `CLIPPED` 位就是 N-18 在软件里的可见形态;V0.2 改版后该位恒 0,页面与 104 绑定零改动 |
+348
View File
@@ -0,0 +1,348 @@
# 并行分道方案(待办归道 · 写域 · 合并次序)
> **本文只做三件事**:把未闭环待办**归到道**、划**文件级写域**、定**合并次序**。
> **明细不复制**——DoD / 硬依赖 / 验收判据仍在 `docs/任务规划/登记簿.md`、
> `docs/任务规划/W8-数据可信.md`、`docs/任务规划/W1-采集保护收尾.md`、
> `docs/算法/继电保护功能复现规划.md`。机制(worktree / 两把锁 / `done` 流程)见
> `docs/环境与部署/并行任务工作树方案.md`。
>
> **为什么需要它**:待办分散在 5 个文件、编号体系有 6 套,但"能不能并行"只取决于一件事——
> **写域是否相交**。这个判断原先只散在每条任务卡的"写范围"列里,没有人横向拉通看过一遍。
>
> 修订:2026-10-23 建档(用户要求:把保护、ADC、UI、结构债的全部待办做并行分工)。
---
## 1. 一句话结论
```
批 0 回收在途分支(cov,已领先 10 提交) ← 必须先做,它占着一个工作树位
↓
批 1 道A 标定与量纲 ∥ 道B UI 组件层 ∥ 道C 工具链与验证
↓
批 2 道D 遥测链 ∥ 道E UI 页面 ∥ 道F 结构债与网络
↓
C6 独占一轮(USART1 TX-only,CubeMX 重生成,不能与任何分支并存)
↓
批 3 道G 保护元件 ∥ 道H 采集增强 ∥ 台架/外部窗口(卡 12、N-16、N-3、B10)
```
**道名对照**(全文只用这 8 个标签):
| 道 | 名称 | 批 | 写域 |
|---|---|---|---|
| **道A** | 标定与量纲(W8 M4,关键路径) | 1 | 域1+域2+域3+域4 |
| **道B** | UI 组件层(等数据时先做的活) | 1 | 域5 |
| **道C** | 工具链与验证(单测/门禁/断言) | 1 | 域8 |
| **道D** | 遥测链(W8 M5/M6) | 2 | 域1+域4+域2 |
| **道E** | UI 页面(27 叶 + 3 页回炉) | 2 | 域5 |
| **道F** | 结构债与网络(C1/C3/N-17/N-22) | 2 | 域6+域7 |
| **道G** | 保护元件扩展 | 3 | 域3+域2 |
| **道H** | 采集增强(等周波/零序/谐波轨) | 3 | 域1+域3 |
**关键判断**:用户最关心的"保护待做"**大部分不能与标定并行**——因为保护元件的判据全是
"与定值比",而定值是工程单位(10 A / 120 V),标定没落地时新元件写出来就是"码值比二次值",
和现在 `prot_elm` 的错配是同一个病。真正能提前的只有**比值类判据**(涌流制动、CT 断线、
突变量启动),但它们要往 `prot_set` 里加定值项 → 改 `PS_ID_COUNT` 与 blob VER → 与 W8 的
落盘/闭锁卡互斥。**所以保护整簇排在 W8 M4 之后**,逐项归道见 §4.2。
---
## 2. 硬约束(决定"最多能切多细")
| # | 约束 | 出处 | 对分道的含义 |
|---|---|---|---|
| 1 | **同时最多 3 棵工作树** | `docs/环境与部署/并行任务工作树方案.md` §4 | 并发上限 3,不是想切几条切几条 |
| 2 | **`@build` 必须串行**(UV4 不能两个实例同时 `-b`) | `并行任务工作树方案.md` §7.2 | 三条道能**同时编码**,构建排队;增量 4~5 s,不是瓶颈 |
| 3 | **台架必须串行**(COM6 / ST-LINK / 192.168.1.100 各一份) | `并行任务工作树方案.md` §7.1 | 真正的瓶颈。台架道单列,见 §5.4 |
| 4 | **单写者文件**:`docs/任务规划/**`、`AGENTS.md` 任务表块、`MDK-ARM/*.uvprojx`、`.pre-commit-config.yaml`、内存快照 | `并行任务工作树方案.md` §6.1 | 任务分支不碰登记簿;uvprojx 手工并;内存数字合并后重生成 |
| 5 | **分支存活 ≤2 天、绿即合** | `并行任务工作树方案.md` §7.3 规则 3 | 一条道不是一条长分支,是**连续若干个短分支** |
| 6 | **`done` 只能在主工作树、必须串行** | `.dsh/skills/task-worktree/SKILL.md` 铁律 1 | 合并不是并行的,只能排队 |
| 7 | **CubeMX 重生成会打回手工定制**(需跑 `check_cubemx_survival.py`) | `docs/任务规划/排期详述.md` §1 C6 | C6 **独占**,不能与任何分支并存 |
| 8 | **`check_layer_deps.py` 基线只减不增** | `scripts/check_layer_deps.py` | 谁减基线谁写这个文件——只能有一条道写 |
> 约束 1 与 3 合起来给出真正的并行度:**3 条编码道 + 1 条台架道**,台架道跑在主工作树里,
> 不额外占工作树名额(它验证的是已合入的镜像)。
---
## 3. 写域划分(域1~域8)
> 划道的唯一依据。**同一域同时只能有一条道在写**;跨域任务必须拆成两张卡或声明合并次序。
| 域 | 文件(glob) | 典型归属 |
|---|---|---|
| **域1 采集与算法** | `App/algo/*`(`adc_cal.*` / `meas.*` 新增)、`App/task/adc_task.c`、`test/host/adc_*/` | 标定、遥测快照、采集增强 |
| **域2 定值与配置** | `App/algo/prot_set.*`、`App/algo/run_par.*`(新增)、`App/cfg/*`、`test/host/cfg_file/` | 定值表、配置引擎、运行参数段 |
| **域3 保护元件与出口** | `App/algo/prot_elm.*`、`App/algo/freq.*`、`App/task/protect_task.c`、`App/algo/prot_do.*`(新增) | 保护判据、出口、闭锁 |
| **域4 104 上行** | `App/protocol/iec104/*`、`App/task/iec104_serv.c`、`test/host/iec104/` | 点表、死区、频率点、运行参数映射 |
| **域5 UI** | `Drivers/BSP/UI/*`、`ui_menu_tree.txt`、`tools/menu_gen/*`、`tools/font_gen/*`、`ui_cn_chars.txt`、`App/app/ui_data_feed.*`(新增) | 页面、组件、数据供给、字库 |
| **域6 存储与日志** | `App/log/*`、`App/fs/*`、`Lib/dhara/*` | 写回 flush、日志管线、卷锁 |
| **域7 网络** | `Drivers/BSP/NET/*`、`Drivers/BSP/NETCFG/*`、`App/task/net_task.c`、`App/sync/*` | net 收口、探针缺口、PHY |
| **域8 工具链与门禁** | `test/host/**`(各道新增子目录除外)、`scripts/*`、`.gitea/*`、`.pre-commit-config.yaml` | 单测、CI、断言宏、门禁 |
**跨域但必须独占的两个文件**:
| 文件 | 为什么独占 | 处理 |
|---|---|---|
| `MDK-ARM/STM32F407-Demo.uvprojx` | 每条新增 `.c` 都要注册,UV4 构建时还会自动改写 | 任务分支照常加 `<File>`,`done` 时**手工并条目** → 跑 `registration-check` → `@build` |
| `docs/内存管理/RAM使用分析与优化方案.md` | `mem-numbers` 快照 | **绝不手工合数字**;每次 `done` 后 `scripts/check_mem_numbers.py --write` 重生成 |
---
## 4. 全量待办归道
> 覆盖 `docs/任务规划/` 全部未闭环项 + 保护复现规划 L 项 + UI 两篇规划。
> "批"列 = 第几轮开工;`—` = 现在不排(理由见 §9)。
### 4.1 W8 数据可信(14 卡)
| 条目 | 写域 | 道 | 批 |
|---|---|---|---|
| 卡 1 TPAFE 量程口径定死 | 文档(`docs/硬件平台/`) | **道A 标定** | 1 |
| 卡 3 `cfg_file` 补 `CFG_VAL_INT` | 域2 | **道A 标定** | 1 |
| 卡 2 通道标定模块与折算 | 域1 | **道A 标定** | 1 |
| 卡 4 标定系数落盘 | 域1 + 域2 | **道A 标定** | 1 |
| 卡 5 未标定即闭锁 | 域3 | **道A 标定** | 1 |
| 卡 6 下游三常数重定 | 域3 + 域4 + 域2 | **道A 标定** | 1 |
| 卡 7 量纲回归用例 | `test/host/` | **道A 标定** | 1 |
| 卡 0 已知电压注入验证 | 台架 + 文档 | **台架道** | 1 |
| 卡 0b 端子/子板变比确认 | 台架 + 文档(🟡 外部) | **台架道** | 1~2 |
| 卡 8 遥测快照 200 ms | 域1 | **道D 遥测** | 2 |
| 卡 9 104 读快照 + 死区 | 域4 | **道D 遥测** | 2 |
| 卡 10 运行参数段 `0x8020~0x8058` | 域2 + 域4 | **道D 遥测** | 2 |
| 卡 11 频率点 `0x401D` | 域4 | **道D 遥测** | 2 |
| 卡 12 8 通道两点标定 | 台架(🟡 标准源) | **台架道** | 3+ |
### 4.2 保护待做(L 项)
| 条目 | 判据是否依赖工程量 | 写域 | 道 | 批 |
|---|---|---|---|---|
| L1-5 通道标定 | — | 域1 | = 卡 2/4 | 1 |
| L5-2 码值越界检出(残余) | 否(越界门限可用 FS 百分比) | 域1(`adc_health`) | **道A 标定** | 1 |
| L3-7 涌流制动(二次谐波占比) | **否**(比值) | 域3 + 域2(加定值) | **道G 保护** | 3 |
| L3-9 CT 断线(电流不平衡) | **否**(比值) | 域3 + 域2 | **道G 保护** | 3 |
| L3-11 故障启动(突变量) | **否**(相对量) | 域3 + 域2 + 新 `prot_start.*` | **道G 保护** | 3 |
| L3-8 PT 断线 | **是**(电压阈值) | 域3 + 域2 | **道G 保护** | 3 |
| L3-12 无压/无流闭锁 | **是** | 域3 + 域2 | **道G 保护** | 3 |
| L3-10 母线接地告警 | **是** | 域3 + 域2 | **道G 保护** | 3 |
| L5-1 残余(元件级校验和常量表) | 否 | 域2 + 域3 | **道G 保护** | 3 |
| L5-3 硬件自检 | 否(但需出口硬件) | 域3 | **道G 保护** | 3 |
| L4-1 跳闸出口 / L4-2 告警出口 / L4-3 出口自检 | 否 | 新模块 `prot_do.*` | **独立立项** | — |
| L1-7 等周波调频 | 是(依赖标定后幅值) | 域1 + 域3 | **道H 采集增强** | 3 |
| L1-8 零序通道接入 | 是 | 域1 | **道H 采集增强** | 3 |
| L2-8 遥测谐波轨 | 是 | 域1(`phasor`) | **道H 采集增强** | 3 |
| L3-2 零序过流 / L2-5 线·负序·零序合成 | — | 域1 + 域3 | **V0.2 硬件** | — |
| L4-6 故障录波 | — | 新子系统 | **独立立项** | — |
> **为什么 L4-1~L4-3 是独立立项而不是一条道**:固件里**完全没有开入/开出代码**
> (`docs/问题记录/采集与数据处理短板评测.md` 登记),出口要驱动 U18 桥 + 继电器,
> 是一整个模块(GPIO 安全默认电平 + 出口保持/脉冲 + 回读自检),量级与"加一个元件"不同。
### 4.3 UI(两篇规划)
| 条目 | 写域 | 道 | 批 |
|---|---|---|---|
| 字库扩充(约 25 字:段/投/延/零/频/荷/闸/跳/低/过/Ⅰ/Ⅱ/Ⅲ…) | `ui_cn_chars.txt` + `tools/font_gen/` + `ui_font_cn_12.c`(生成物) | **道B UI** | 1 |
| `ui_w_editor` 数值编辑器 | 域5(新增) | **道B UI** | 1 |
| `ui_w_setlist` 定值表组件 | 域5(新增) | **道B UI** | 1 |
| `ui_page_action` 动作确认页 | 域5(新增) | **道B UI** | 1 |
| 记录 reader 注入(削 3 条分层基线) | 域5 + `scripts/check_layer_deps.py` | **道B UI** | 1 |
| `ui_data` 快照层 + `ui_data_feed` | 域5 + `App/app/` | **道E UI 页面** | 2 |
| 27 个空叶子 + 3 页回炉(30 页次) | 域5 + `ui_menu_tree.txt` + 生成物 | **道E UI 页面** | 2 |
> **`ui_data` 为什么排在批 2 而不是批 1**:`ui_data_feed` 组装的 `eng` 字段要等 W8 M4 的结论
> (`docs/任务规划/W8-数据可信.md` §2.6 与 §10)。组件层(编辑器/定值表/记录 reader)
> 与标定无关,所以单独提到批 1——**这是本次分道最大的收益点**:让 UI 在等标定的同时有活干。
### 4.4 结构债、验证与其它
| 条目 | 写域 | 道 | 批 |
|---|---|---|---|
| C6 / S-3 USART1 TX-only 结构根治 | `.ioc` + `Src/*`(重生成) | **独占** | 2.5 |
| C3 / N-2 日志管线合并评估 | 域6 | **道F 结构债** | 2 |
| N-22 写回缓存空闲 flush | 域6 | **道F 结构债** | 2 |
| N-17 探针窗口心跳缺口(排期详述里的 D6) | 域7 + `App/sync/` | **道F 结构债** | 2 |
| C1 / E-25·E-27·E-28 net 跨上下文收口 | 域7 | **道F 结构债** | 3 |
| N-25 性能与语义簇(PASV/PHY/SOCKETS) | 域7 | **道F 结构债** | 3 |
| S-4 dhara 重试自旋 | 域6 | **道F 结构债** | 3 |
| S-5 全序列卷锁评估 | 域6 | **道F 结构债** | 3 |
| `docs/任务规划/测试与架构专项.md` 的 P1-10 测试固件构建实测 | `MDK-ARM/` 测试配置 | **道C 工具链** | 1 |
| S12 模块级断言宏 | `App/util/app_assert.h`(新增)+ 试点 | **道C 工具链** | 1 |
| S1-c `sys_log` / `time_sync` 主机单测 | `test/host/`(新增) | **道C 工具链** | 1 |
| A-5 残余 CI 体积门禁盲区 | `.gitea/` + `scripts/` | **道C 工具链** | 1 |
| N-3 / D2 L5 基线重锁 | 无码(需 PC peer) | **台架道** | 3 |
| N-16 / D5 A2/A4 负向台架 | 无码 | **台架道** | 3 |
| D7 串口助手 A6/A7 | 无码(需 CH340) | **台架道** | 待硬件 |
| B10 送检(标准源 + 第三方主站) | 无码 | **外部窗口** | Fixed Date |
| T-7 CI runner | 外部基础设施 | **外部** | 待 runner |
| N-30 relisten 收口 / `docs/问题记录/项目审查与优化建议报告.md` 的 F-5(N-28 簇)/ N-29 `.git` / N-18 V0.2 / N-27 内存簇 / B2 RS-485 / 开入开出 / 录波 | — | **不排** | — |
---
## 5. 批 1 三道详解(可以今天开工)
### 5.1 道A「标定与量纲」(关键路径)
**目标**:把 `adc_task.c:335` 的 `frame[s] = (float)code;` 换成折算,让采样环里第一次是电压。
**含**:W8 卡 1 → 卡 3 → 卡 2 → 卡 4 → 卡 5 → 卡 6 → 卡 7,加 L5-2 码值越界。
| 分支 | 内容 | 预计 | 写域 | 依赖 |
|---|---|---|---|---|
| `task/W8-scale-doc` | 卡 1(量程口径定死)+ 卡 3(`CFG_VAL_INT`) | 0.5~1 d | 文档 + 域2 | 无 |
| `task/W8-adc-cal` | 卡 2(`adc_cal.*`)+ 卡 4(落盘)+ L5-2 | 1~1.5 d | 域1 + 域2 | 上一条 |
| `task/W8-lockout-dim` | 卡 5(未标定闭锁)+ 卡 6(三常数)+ 卡 7(量纲回归) | 1~1.5 d | 域3 + 域4 + 域2 | 上一条 |
**退出判据**:M4 六条(`docs/任务规划/W8-数据可信.md` §3)全满足;`@build` 0/0;
主机单测绿;台架 `@test` 的期望已按"默认构建下保护不动作"更新。
**与谁撞**:`iec104_pts.c`(卡 6 改 `k_yc[].deadband`)会与批 2 的道D 撞 → **道A 先合**;
`prot_set.c` 会与批 3 的道G 撞 → **道G 在道A 之后**。
### 5.2 道B「UI 组件层」(与标定并行)
**目标**:把"等数据"的页面工作提前做掉,只留数据绑定给批 2。
**含**:字库扩充 → `ui_w_editor` → `ui_w_setlist` → `ui_page_action` → 记录 reader 注入。
| 分支 | 内容 | 预计 | 写域 |
|---|---|---|---|
| `task/UI-font-subset` | 字库扩字 + `make_font.py` 重生成 + 字符集差集检查 | 0.5 d | `ui_cn_chars.txt`、`tools/font_gen/`、`ui_font_cn_12.c` |
| `task/UI-widgets` | `ui_w_editor` + `ui_w_setlist` + `ui_page_action` | 1.5 d | 域5(新增 3 对文件) |
| `task/UI-rec-reader` | 记录 reader 注入,页面不再 include `sys_log.h` | 1 d | 域5 + `scripts/check_layer_deps.py` |
**退出判据**:`ui-golden` 像素基线更新后通过;`check_layer_deps.py --prune` 报"基线可收紧 3 条"
且实际收紧到 **3 条**(6→3);`@build` 0/0。
**为什么安全**:`Drivers/BSP/UI/` 与道A 的 `App/algo`+`App/cfg` **零文件交集**;
唯一共享的是 `uvprojx`(新增源文件)与内存快照——按 §3 的办法处理。
### 5.3 道C「工具链与验证」(零交集)
**目标**:补门禁与测试底座,让后两批的合并更安全。
**含**:S12 断言宏 → S1-c 单测 → A-5 体积门禁 → 测试固件构建实测(详见 `docs/任务规划/测试与架构专项.md`)。
| 分支 | 内容 | 预计 | 写域 |
|---|---|---|---|
| `task/S12-assert` | `app_assert.h` + 1~2 处试点(`net_socket` 状态机不变量) | 0.5 d | `App/util/` + 域7 单点 |
| `task/S1c-host-tests` | `sys_log` / `time_sync` 主机单测 | 1 d | `test/host/`(新增 2 目录) |
| `task/A5-size-gate` | 体积门禁的强制路径 | 0.5 d | `.gitea/` + `scripts/` |
| `task/P1-10-test-fw` | CH395F 套件构建确认 + `@test` | 1 d | `MDK-ARM/` 测试配置 + 台架 |
**与谁撞**:`test/host/**` 与在途的 `cov` 分支同域 → **批 0 必须先回收 `cov`**(见 §6.1)。
### 5.4 台架道(主工作树,不占工作树名额)
批 1 期间台架只做一件事:**W8 卡 0 已知电压注入验证**(只需万用表,不需要信号源/示波器)。
它验证的是"ADC 到底读得准不准",是道A 系数冻结的前置。
节奏:道A 分支合入 → 主工作树 `@build` → 持 `bench.lock` → 注入三点 → 记录斜率 →
写回 `docs/硬件平台/ADC通道映射说明.md` §8。
> 台架道永不空转(TOC):卡 0 做完后接着做卡 0b(若子板到手),否则跑测试固件构建那一项的 `@test`。
### 5.5 批 1 的并行度
| 资源 | 并发 | 说明 |
|---|---|---|
| 工作树 | **3**(道A/道B/道C 各一) | 达到 §2 约束 1 的上限 |
| `@build` | 1 | 自动排队,增量 4~5 s,不构成瓶颈 |
| 台架 | 1 | 主工作树,只在道A 分支合入后占用 |
| `done` | 1 | 按 道A → 道B → 道C 顺序串行回收 |
---
## 6. 合并次序与冲突预判
### 6.1 批 0:先回收在途分支(必做)
现状(2026-10-23 实测 `task_worktree.py list`):
```
任务 分支 落后 领先 脏 台架
cov task/cov-host-line-coverage 4 10 2 -
```
`cov` 是主机单测覆盖率扩展(60 个文件,`test/host/**` + `.pre-commit-config.yaml` + 文档),
**领先主干 10 个提交、落后 4 个、2 个文件未提交**。它占着 3 个工作树名额里的 1 个,
且与道C 的 `test/host/**` 同域。
**处置**:先 `sync cov` → 清脏文件 → `done cov`。理由不是"它更重要",而是
**不回收它就没有第三个名额给道C**,且两条道同时加 `test/host/` 会让 `done` 的并集审计变复杂。
### 6.2 冲突矩阵(批 1 三道)
| 文件 | 道A | 道B | 道C | 处理 |
|---|---|---|---|---|
| `MDK-ARM/*.uvprojx` | 加 `adc_cal.c` | 加 3 对 UI 文件 | 不动 | 每次 `done` 手工并 `<File>` → `registration-check` |
| `docs/内存管理/RAM使用分析与优化方案.md` | RAM +≈100 B | RAM +≈300 B | 不动 | 每次 `done` 后 `check_mem_numbers.py --write` |
| `.pre-commit-config.yaml` | 加 adc_cal 钩子 | 加 UI 钩子 | 加 2 个钩子 | 并集;三处各自 `git add` 自己的行 |
| `scripts/check_layer_deps.py` | 不动 | **减 3 条基线** | 不动 | 道B 独占 |
| `test/host/**` | 新增 `adc_cal/` | 不动 | 新增 2 目录 | 目录不重叠,安全 |
| `docs/任务规划/**` | 不动 | 不动 | 不动 | 主工作树统一销项 |
**合并次序**:`道A → 道B → 道C`。理由是道A 在关键路径上、且它决定道D 与道G 的前置;
道B 与道C 无先后依赖,按"改动小的先合"以减少 rebase 面(道B 的 `ui-golden` 基线更新是独立提交,好回退)。
### 6.3 每次 `done` 的固定动作
1. `done <ID> --dry-run` 预演(`git merge-tree`,rc≠0 就先在任务分支解冲突)
2. `done <ID>`:合入 → 并集残留审计(三方对比,不用 `tail` 目测)→ 重生成产物 → 门禁
3. 主工作树补:销项删行(`docs/任务规划/` 各文件)→ `AGENTS.md` 任务表重生成 → 内存快照重生成
4. `@build` 0/0 + 台架 `@test`(若该道改了行为)
---
## 7. 三件"看起来能并行、实际不能"的事
| 事项 | 为什么不能并行 | 正确做法 |
|---|---|---|
| **C6 / S-3 USART1 TX-only** | 改 `.ioc` → CubeMX 重生成会**打回 5 处手工定制**(IWDG 延迟启动、Fault Handler、FreeRTOSConfig 加固区等),且重写 `Src/*` 大片生成文件 → 与任何分支必冲突 | **独占一轮**:清空所有工作树 → 在主工作树做 → `check_cubemx_survival.py` 全过 → 台架闭环 |
| **字库重生成** | `make_font.py` 重写 `ui_font_cn_12.c`(整文件生成物),两人同时扩字会互相覆盖 | 归道B 一个分支独占;后续加字必须重新走一次 |
| **往 `prot_set` 加定值项** | 改 `PS_ID_COUNT` → blob VER 2→3 → 影响落盘格式、104 定值段、UI 整定页分组 | 只在**没有任何 W8 定值卡在飞**的时候做(批 3 的道G) |
---
## 8. 执行清单(批 0 + 批 1 起步)
```powershell
$PY = ".venv\Scripts\python.exe"
$WT = ".dsh\skills\task-worktree\scripts\task_worktree.py"
# 批 0:回收在途分支(先 sync 再 done,done 只在主工作树)
& $PY $WT sync cov
& $PY $WT status cov # 看清 2 个脏文件是什么
& $PY $WT done cov --dry-run
& $PY $WT done cov
# 批 1 道A
& $PY $WT new W8-scale-doc
& $PY $WT new W8-adc-cal
# 批 1 道B
& $PY $WT new UI-font-subset
# 批 1 道C(等 cov 回收后再开)
& $PY $WT new S12 assert
# 台架(在主工作树,验证已合入镜像)
& $PY $WT lock acquire bench --task W8-adc-cal
# ……注入验证 / @test……
& $PY $WT lock release bench --task W8-adc-cal --bench-pass
```
> 分支 ID 用语义 slug(`W8-scale-doc` / `UI-font-subset`),与 `docs/任务规划/README.md` §0 的
> "新条目用语义标识"一致;存量编号(N-x / S-x / C-x)仍可直接当 ID 用。
---
## 9. 现在不排的(避免误以为漏了)
| 项 | 状态 | 重开条件 |
|---|---|---|
| B2 RS-485 整簇(含 E-49/E-50、A-4 RS485 侧、N-25 DE 项、待确认-3) | ⏸ 用户决定 2026-10-12 暂缓 | 见 `docs/任务规划/暂缓-RS485.md` |
| N-27 内存优化簇剩余(`docs/问题记录/项目审查与优化建议报告.md` 的 R-2 后半 / R-3 / R-4 / R-6) | ⏸ 用户裁定 2026-10-15 | `docs/问题记录/项目审查与优化建议报告.md` §5.3 |
| N-29 `.git` 235 MB | 决策:登记观察 | 推送/协作前重评 |
| N-18 V0.2 硬件改版 | 下一版硬件 | 硬件改版立项 |
| N-30 relisten 收口 | 观察(原语版实测回退) | 三条语义前置满足后 |
| `docs/问题记录/项目审查与优化建议报告.md` 的 F-5 空 TU(N-28 簇) | 观察 | 有全量构建耗时痛点时 |
| T-7 CI runner | 外部基础设施 | runner 就绪 |
| D7 串口助手 A6/A7 | 待硬件 | CH340 到位 |
| 开入/开出固件、故障录波 + 104 文件传输 | 独立立项 | 产品定义 / 单独立项 |
+3 -1
View File
@@ -142,9 +142,10 @@ STM32(U17)为 LQFP144 脚号。
## 8. 逐通道验证方法(上板自检口径) ## 8. 逐通道验证方法(上板自检口径)
1. **TPAFE 侧**:对目标 `AIN` 注入 1 V DC → 观察对应 `buf[i]` 变化(UA→`buf[6]`、UN→`buf[5]`、IA→`buf[2]`),同时 U3.14 `BUSY` 有脉冲;**语义与下标不符即映射错**。 1. **TPAFE 侧**:对目标 `AIN` 注入 1 V DC → 观察对应 `buf[i]` 变化(UA→`buf[6]`、UN→`buf[5]`、IA→`buf[2]`),同时 U3.14 `BUSY` 有脉冲;**语义与下标不符即映射错**。⚠ **本步无执行记录**(2026-10-23 核查;`V0.0_网表详细分析报告.md` §5.1 第 6 条的同一验证也从未执行)。已排入 `docs/任务规划/W8-数据可信.md` 卡 0,并把两条判据降为**不需要示波器**的口径:① "`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-10 L1-3 台架只验证了"9 通道全部转换成功 + 零超时 + 互异非饱和 + 跨次开机读数不同",台架无信号源);映射的**代码侧**一致性有两道保证:① `App/algo/adc_input.c` 的 `k_adc_map[]` 与 CubeMX 标签(`ADC17_UB`=PC4 等)逐条对齐;② 开机自检 `adc_input_init()` 校验每个 STM32 语义通道都落在 `k_stm32_rank_ch[]` 扫描序列内(挡"映射到不扫描的通道 → 恒读陈旧值")。 2. **STM32 侧**:对目标引脚(如 PC4=UB)注入 0.5 V → 读 `ADC_CHANNEL_14` 应变化;若不变而相邻通道变化 → 通道宏写错(见 §5 警告)。⚠ **本步尚未执行**(2026-10-10 L1-3 台架只验证了"9 通道全部转换成功 + 零超时 + 互异非饱和 + 跨次开机读数不同",台架无信号源);映射的**代码侧**一致性有两道保证:① `App/algo/adc_input.c` 的 `k_adc_map[]` 与 CubeMX 标签(`ADC17_UB`=PC4 等)逐条对齐;② 开机自检 `adc_input_init()` 校验每个 STM32 语义通道都落在 `k_stm32_rank_ch[]` 扫描序列内(挡"映射到不扫描的通道 → 恒读陈旧值")。
3. **备用通道**:RESERVED 路不接入任何语义,UI 与上报里不得出现;若实测有读数漂移,只记录不消费。 3. **备用通道**:RESERVED 路不接入任何语义,UI 与上报里不得出现;若实测有读数漂移,只记录不消费。
4. **端子侧变比(2026-10-23 补)**:上面 1/2 两条都只到 **ADC 引脚**。**"端子电压 → ADC 引脚电压"的变比在仓库里没有任何文档给出**(`docs/硬件平台/` 只有 `.tel` 网表与分析报告,无子板原理图),而 `V0.0_网表详细分析报告.md` §4.7 已把 `1k 串联 + 1k 到地` 这组网络定性为"**源阻抗匹配(手册推荐做法,非分压)**"。故**不得**用"2:1 分压"直接换算出二次值;该变比由 `docs/任务规划/W8-数据可信.md` 卡 0b 实测确认。
--- ---
@@ -156,3 +157,4 @@ STM32(U17)为 LQFP144 脚号。
| 2026-10-09 | **CubeMX 生成 ADC1(9 通道)落地**:新增 `Src/adc.c`/`Inc/adc.h` + HAL adc 三文件并挂进 uvprojx、`HAL_ADC_MODULE_ENABLED` 生效、`MX_ADC1_Init()` 入 `main.c`;分频 PCLK2/4 = 21 MHz——面板里 DIV2 已被 `FadcConstraint`(36 MHz)约束禁掉,**故不加 `.ioc` 键 / 代码守卫 / 审计项等额外防护**(曾加过,按决定撤除,理由见 §7"ADC 时钟"行);修正 PA0 标签笔误 `AD9_RES`→`ADC9_RES`。⚠ 本次重生成打回了 5 处定制(IWDG 延迟启动锚点、HardFault + 3 个 Fault 手工 Handler、`FreeRTOSConfig.h` 加固区、`freertos.c` 三处栈核算注释),已全部复原;存活审计新增 1 项 `adc1-hal-enabled`(共 19 项),现 19 通过 / 1 警告(timeSyncTask 手工定义)/ 0 失败,`@build` 0 错 0 警 | | 2026-10-09 | **CubeMX 生成 ADC1(9 通道)落地**:新增 `Src/adc.c`/`Inc/adc.h` + HAL adc 三文件并挂进 uvprojx、`HAL_ADC_MODULE_ENABLED` 生效、`MX_ADC1_Init()` 入 `main.c`;分频 PCLK2/4 = 21 MHz——面板里 DIV2 已被 `FadcConstraint`(36 MHz)约束禁掉,**故不加 `.ioc` 键 / 代码守卫 / 审计项等额外防护**(曾加过,按决定撤除,理由见 §7"ADC 时钟"行);修正 PA0 标签笔误 `AD9_RES`→`ADC9_RES`。⚠ 本次重生成打回了 5 处定制(IWDG 延迟启动锚点、HardFault + 3 个 Fault 手工 Handler、`FreeRTOSConfig.h` 加固区、`freertos.c` 三处栈核算注释),已全部复原;存活审计新增 1 项 `adc1-hal-enabled`(共 19 项),现 19 通过 / 1 警告(timeSyncTask 手工定义)/ 0 失败,`@build` 0 错 0 警 |
| 2026-10-10 | **口径更正**:8 路电气量分属 TPAFE / STM32 两片转换器**定性为 V0.1 硬件缺陷**,撤销 2026-10-09 建档时"有意分配、不要修正"的说法;补记缺陷实质(跨转换器无同一时刻性、16 位双极性 vs 12 位单极性、语义与归属交叉)与 **V0.2 改版要求**(8 路电气量全部接 TPAFE,与 5 路备用路对调串联电阻目的地,BOM 不变);§7 新增"通道归属"行,明确 V0.1 上禁止跨转换器做相位/功率类运算。同步更正 `V0.1_网表详细分析报告.md` §1.4(新增 V10)/ §6-3,登记簿新增 **N-18** | | 2026-10-10 | **口径更正**:8 路电气量分属 TPAFE / STM32 两片转换器**定性为 V0.1 硬件缺陷**,撤销 2026-10-09 建档时"有意分配、不要修正"的说法;补记缺陷实质(跨转换器无同一时刻性、16 位双极性 vs 12 位单极性、语义与归属交叉)与 **V0.2 改版要求**(8 路电气量全部接 TPAFE,与 5 路备用路对调串联电阻目的地,BOM 不变);§7 新增"通道归属"行,明确 V0.1 上禁止跨转换器做相位/功率类运算。同步更正 `V0.1_网表详细分析报告.md` §1.4(新增 V10)/ §6-3,登记簿新增 **N-18** |
| 2026-10-10 | **STM32 ADC1 消费者落地(L1-3/L1-4)**:新增 `App/algo/adc_input.c/h`——语义映射表 `k_adc_map[]` 按本文件 §3/§5 逐条落地(`UA/UN/IA`→TPAFE `buf[6]/[5]/[2]`,`UB/UC/IB/IC/IN/TEMP`→`CH14/3/6/1/2/5`),并提供 `adc_input_raw()` **按语义取数**;`stm32_scan()` 实现 9 通道软件触发顺序扫描;`adc_input_init()` 增**映射自检**(STM32 映射通道必在扫描序列内)。§7 的"STM32 ADC 外设 / `adc_task` / TPAFE 采样触发"三行同步更新(后两者原为陈旧描述:TIM6 周期触发、L1 层取数)。§8 步骤 2 标注**引脚级注入验证尚未执行**。台架 `@test` PASS(`adc1_rc=0` / `adc1_err=0`、`ADC input layer init: OK`;首帧 `UA=11429 UN=11454 IA=11452`、`UB=1018 UC=1044 IB=943 IC=1069 IN=1052 T=850`——互异非饱和,且两次开机读数不同 → 实时转换而非常量),证据 `测试说明/boot_log_data/20261010_prod_adc_l1_boot_log.txt` | | 2026-10-10 | **STM32 ADC1 消费者落地(L1-3/L1-4)**:新增 `App/algo/adc_input.c/h`——语义映射表 `k_adc_map[]` 按本文件 §3/§5 逐条落地(`UA/UN/IA`→TPAFE `buf[6]/[5]/[2]`,`UB/UC/IB/IC/IN/TEMP`→`CH14/3/6/1/2/5`),并提供 `adc_input_raw()` **按语义取数**;`stm32_scan()` 实现 9 通道软件触发顺序扫描;`adc_input_init()` 增**映射自检**(STM32 映射通道必在扫描序列内)。§7 的"STM32 ADC 外设 / `adc_task` / TPAFE 采样触发"三行同步更新(后两者原为陈旧描述:TIM6 周期触发、L1 层取数)。§8 步骤 2 标注**引脚级注入验证尚未执行**。台架 `@test` PASS(`adc1_rc=0` / `adc1_err=0`、`ADC input layer init: OK`;首帧 `UA=11429 UN=11454 IA=11452`、`UB=1018 UC=1044 IB=943 IC=1069 IN=1052 T=850`——互异非饱和,且两次开机读数不同 → 实时转换而非常量),证据 `测试说明/boot_log_data/20261010_prod_adc_l1_boot_log.txt` |
| 2026-10-23 | **验证现状核查与排期**:确认 §8 步骤 1/2 与 `V0.0_网表详细分析报告.md` §5.1 第 6 条的"首次功能级 ADC 验证"**均无执行记录**——现有台架判据只证"通路活"(9 通道转换成功、零超时、互异非饱和、跨次开机不同),不证读数正确,连极性都未验。新增 §8 步骤 4:**"端子电压 → ADC 引脚电压"的变比在仓库内无任何文档**(无子板原理图),且 `1k 串联 + 1k 到地` 已被 §4.7 定性为"源阻抗匹配、非分压",故撤销"按 2:1 换算二次值"的用法。验证方法同步降为**不需要示波器 / 信号源**:`BUSY` 脉冲改用 `tpafe5160_frame_seq()` 帧计数,幅值改用万用表 + 三点线性拟合。排期见 `docs/任务规划/W8-数据可信.md` 卡 0 / 0b |