Files
STM32F4-Base/docs/硬件平台/ADC通道映射说明.md
T
wandering1 4a4ad6bc5f chore(全仓): @build/@test 旧文档别名清退为技能调用名
现状口径:/keil-build 与 /serial-boot-test 是 DSH 会话的技能调用名,
不是 shell 命令;「名 + 命令行参数」的命令形态改为可执行体
run_boot_test.py 的真实调用。

- AGENTS.md:别名说明重写为「技能调用名不是 shell 命令」,两条目改
  「编译(/keil-build)」「串口回归(/serial-boot-test)」
- keil-build / serial-boot-test 两 skill 调用名与示例同步;task-worktree
  方案文档去掉 @build/@test 惯例从句;@task 保留(不在点名范围)
- 123 文件现状陈述全改;台架捕获、变更记录/时间线、rename 映射输入
  等 41 行历史证据保留旧名
- gen_memory_svg.py 6 处措辞随改,3 张 SVG 产物同批重跑
- 顺手补并行方案同行漏网计数 51→52 钩子

验证:提交期快钩子对 123 文件实跑全 Passed;check_doc_links --all
rc=0(3038 处、无法判定 0);check_mermaid --all rc=0;YAML 解析 52
钩子不变;skill-size rc=0;py_compile 全过;字节卫生零漂移。
2026-10-30 13:03:12 +08:00

221 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# V0.1 ADC 通道映射表(权威口径)
> **一句话结论**: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))。
---
## 1. 语义分配(2026-10-09 硬件确认)
| 语义 | 网名 | 类别 | 说明 |
|---|---|---|---|
| **UA** | AIN1 | 电压 | A 相电压 |
| **UB** | AIN2 | 电压 | B 相电压 |
| **UC** | AIN3 | 电压 | C 相电压 |
| **UN** | AIN4 | 电压 | 零线(中性线)电压 |
| **IA** | AIN8 | 电流 | A 相电流 |
| **IB** | AIN9 | 电流 | B 相电流 |
| **IC** | AIN10 | 电流 | C 相电流 |
| **IN** | AIN11 | 电流 | 零线电流 |
| **温度** | 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)改版项(登记簿 **N-18**)。
**缺陷实质(为什么必须改)**:
1. **跨转换器通道没有同一时刻性**:TPAFE5160 是 8 通道**同步**采样,STM32 ADC 是**顺序**扫描(9 通道一轮 ≈ 67 µs),且两片转换器**没有共同采样触发**(CONVST 只打 TPAFE,ADC1 为软件触发)。于是 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 两张表的存在本身就是代价)。
**下一版硬件(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 现板的软件口径**:主板侧只做**逐通道独立监视**(有效值 / 越限 / 温度),**禁止**做跨转换器的同周期相位、功率、功率因数、矢量类运算;确需此类量,取子板计量模块的结果。
---
## 2. 三套编号,别混
| 编号族 | 含义 | 出现位置 |
|---|---|---|
| `AINn`(n=1~15)、`V_ZL1/2` | **子板侧网名**:语义挂在这一层(UA/UB/…/温度) | 连接器 U5 各脚 → 串联电阻 |
| `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 通道)。
---
## 3. 完整映射表(17 路)
TPAFE5160(U3)通道脚:`AIN_1P`=49 / `AIN_2P`=51 / `AIN_3P`=53 / `AIN_4P`=55 / `AIN_5P`=57 / `AIN_6P`=59 / `AIN_7P`=61 / `AIN_8P`=63。
STM32(U17)为 LQFP144 脚号。
| 语义 | 网名 | U5 脚 | 串联电阻 | 板级网名 | 转换器 | 转换器脚 / MCU 脚 | **代码通道** | 状态 |
|---|---|---|---|---|---|---|---|---|
| **UA** | AIN1 | A3 | R31 | ADC7 | TPAFE5160 | U3.61 = `AIN_7P` | `buf[6]`(ch7) | 在用 |
| **UB** | AIN2 | B7 | R52 | ADC17 | STM32 ADC123 | U17.44 = **PC4** | `ADC_CHANNEL_14` | 在用 |
| **UC** | AIN3 | C14 | R20 | ADC12 | STM32 ADC123 | U17.37 = PA3 | `ADC_CHANNEL_3` | 在用 |
| **UN** | AIN4 | A4 | R28 | ADC6 | TPAFE5160 | U3.59 = `AIN_6P` | `buf[5]`(ch6) | 在用 |
| 备用 | AIN5 | B6 | R12 | ADC1 | TPAFE5160 | U3.49 = `AIN_1P` | `buf[0]`(ch1) | RESERVED |
| 备用 | AIN6 | C13 | R5 | ADC9 | STM32 ADC123 | U17.34 = PA0 | `ADC_CHANNEL_0` | RESERVED |
| 备用 | AIN7 | A5 | R23 | ADC4 | TPAFE5160 | U3.55 = `AIN_4P` | `buf[3]`(ch4) | RESERVED |
| **IA** | AIN8 | B5 | R19 | ADC3 | TPAFE5160 | U3.53 = `AIN_3P` | `buf[2]`(ch3) | 在用 |
| **IB** | AIN9 | A8 | R49 | ADC15 | STM32 ADC123 | U17.42 = PA6 | `ADC_CHANNEL_6` | 在用 |
| **IC** | AIN10 | C9 | R46 | ADC10 | STM32 ADC123 | U17.35 = PA1 | `ADC_CHANNEL_1` | 在用 |
| **IN** | AIN11 | C10 | R48 | ADC11 | STM32 ADC123 | U17.36 = PA2 | `ADC_CHANNEL_2` | 在用 |
| 备用 | AIN12 | B3 | R13 | ADC8 | TPAFE5160 | U3.63 = `AIN_8P` | `buf[7]`(ch8) | RESERVED |
| 备用 | AIN13 | A6 | R17 | ADC2 | TPAFE5160 | U3.51 = `AIN_2P` | `buf[1]`(ch2) | RESERVED |
| 备用 | AIN14 | C12 | R45 | ADC13 | STM32 ADC123 | U17.40 = PA4 | `ADC_CHANNEL_4` | RESERVED |
| 备用 | AIN15 | B4 | R26 | ADC5 | TPAFE5160 | U3.57 = `AIN_5P` | `buf[4]`(ch5) | RESERVED |
| 备用 | V_ZL1 | A7 | R51 | ADC16 | STM32 ADC123 | U17.43 = PA7 | `ADC_CHANNEL_7` | RESERVED |
| **温度** | V_ZL2 | C11 | R47 | ADC14 | STM32 ADC123 | U17.41 = PA5 | `ADC_CHANNEL_5` | 在用 |
**汇总**:TPAFE 8 路 = AIN5/13/**8**/7/15/**4**/**1**/12;STM32 9 路 = AIN6/**10**/**11**/3/14/**9**/**2**/V_ZL1/**V_ZL2**(粗体为在用通道)。
---
## 4. TPAFE 侧:读出顺序 → 驱动缓冲区下标
`tpafe5160_read_all()` / EXTI 自动读取按 RD 时序连续读 8 次,`FRSTDATA` 标记第一通道,故 **`buf[0..7]` = `ADC1..ADC8` 网名 = TPAFE `ch1..ch8`**:
| `buf[i]` | 板级网名 | TPAFE 通道 | 语义 |
|---|---|---|---|
| 0 | ADC1 | ch1 | RESERVED(AIN5) |
| 1 | ADC2 | ch2 | RESERVED(AIN13) |
| **2** | ADC3 | ch3 | **IA** |
| 3 | ADC4 | ch4 | RESERVED(AIN7) |
| 4 | ADC5 | ch5 | RESERVED(AIN15) |
| **5** | ADC6 | ch6 | **UN** |
| **6** | ADC7 | ch7 | **UA** |
| 7 | ADC8 | ch8 | RESERVED(AIN12) |
> 消费侧**必须经语义映射表取数**(`UA → buf[6]`),不要按"buf[0]=UA"这类直觉下标写代码。
---
## 5. STM32 侧:网名 → 引脚 → 代码通道宏
| 板级网名 | U17 脚 | 引脚 | **代码宏** | 语义 |
|---|---|---|---|---|
| ADC9 | 34 | PA0 | `ADC_CHANNEL_0` | RESERVED(AIN6) |
| ADC10 | 35 | PA1 | `ADC_CHANNEL_1` | **IC** |
| ADC11 | 36 | PA2 | `ADC_CHANNEL_2` | **IN** |
| ADC12 | 37 | PA3 | `ADC_CHANNEL_3` | **UC** |
| ADC13 | 40 | PA4 | `ADC_CHANNEL_4` | RESERVED(AIN14) |
| ADC14 | 41 | PA5 | `ADC_CHANNEL_5` | **温度(V_ZL2)** |
| ADC15 | 42 | PA6 | `ADC_CHANNEL_6` | **IB** |
| 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)
| 项 | 现状 | 影响 |
|---|---|---|
| **通道归属(硬件缺陷)** | 8 路电气量分属两片转换器:UA/UN/IA → TPAFE,UB/UC/IB/IC/IN → STM32 ADC | **V0.1 硬件缺陷**(非有意分配,理由见 §1)→ V0.1 上禁止跨转换器做相位/功率/功率因数/矢量类运算;**V0.2 改版要求 8 路电气量全部走 TPAFE**(登记簿 N-18) |
| 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`(512 words / **AboveNormal**) | 数据路径已通(台架 `/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` 现只在自检帧通过后才打印 → 判据在本板成立、非空转 |
### 7.1 端到端量纲链路口径(网名 AINn → 端子 → 变比 → 码值 → 满量程,2026-10-25 量程口径冻结定死)
> 出处:`docs/任务规划/数据可信.md` §2.1(量程口径冻结)。本节把 **语义端子(二次侧)→ 子板/端子板 → 网名 `AINn` → 主板电阻网络 → 板级网名 `ADCn` → 转换器引脚 → 码值 → 满量程** 的链路**逐段**定口径。
> ③ 段(`AINn` ↔ 转换器引脚)已有台架实测数值——变比 **1:1**,斜率实测见 §8.1;④ 段(语义端子 ↔ `AINn` 的子板/
> 端子板变比)仓库内没有任何数据,只给口径与判据。
**芯片级口径(定死,与前端网络无关)**:
| 项 | 口径 | 依据 |
|---|---|---|
| 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 同口径 |
“±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 通道前端:端子 → 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,连接地串阻都没有)。
**链路分段口径**:
| 段 | 关系 | 状态 |
|---|---|---|
| ① 语义 ↔ 网名 ↔ 板级网名 ↔ 转换器代码通道 | §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 风险表)。
---
## 8. 逐通道验证方法(上板自检口径)
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,此处只留结论。
| 项 | 实测 | 判据 | 结论 |
|---|---|---|---|
| 零点(8 路短接 AGND) | 0~5 码(TPAFE ≤4.6 mV / STM32 ≤4.0 mV) | TPAFE ≤30 / STM32 ≤5 码 | PASS |
| 三点线性(UA) | R² = 0.9999997 | ≥0.999 | PASS |
| 斜率(UA,TPAFE) | **6544.2 码/V**(期望 6553.6,偏差 −0.14 %),截距 −7.2 码 | 偏差 ≤2 % | PASS |
| 逐通道映射 | 8 路各自塌到**本路**(零点步骤逐路代偿) | 注入哪路只动哪路 | PASS |
| 极性(TPAFE 三路) | −6566 / −6568 / −6566,对称性 ≤0.34 % | 落在 −6554 附近且 ≤2 % | PASS |
| 节奏 | 注入前/后 Δ9998 码 / 10 s ≈ 1000 Hz,`idle=0`、`adc1_err=0` | 注入前后仍 1000 Hz | PASS |
**由此确认的三件事**:
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,但别当成已验证):**串扰**未单独证(零点步骤时其余七路浮空、
本身在漂,小幅串扰看不出来);**节奏**只测了注入前后、没测注入进行中。