产品总览
产品名称:HVCH — High Voltage Coolant Heater(高压冷却液加热器)
客户:Toyota 丰田
供应商:Valeo THS TCC(法雷奥热系统事业部)
料号:bcd8880_00-ESF020
这个产品是干什么的?
电动车没有发动机余热来供暖,所以需要一个独立的加热器。HVCH就是这个角色——它用电池包的高压电(~400V)加热冷却液,热的冷却液通过管路流到暖风芯体,给座舱供暖。
核心工作流程
车辆空调控制器 → 通过LIN总线发指令 → MCU收到并解析 → 计算加热功率 → PWM驱动IGBT开关 → IGBT导通高压电流经过加热元件(HE) → 冷却液被加热 → 同时持续监控温度/电压/电流 → 异常则锁机保护
关键参数
| 参数 | 值 |
|---|---|
| 输入电压(高压侧) | ~400V DC |
| 输入电压(低压侧) | 12V DC (VSUP) |
| 加热功率 | 7KW (60PL) / 10KW (600D/800D) |
| 通信协议 | LIN 2.1 |
| MCU | NXP S32K144 (ARM Cortex-M4) |
| SBC | TJA1128E |
系统架构
硬件架构总览
整个板子分为低压侧(LV)和高压侧(HV)两个域,通过隔离电源(Flyback)和隔离信号连接。
低压侧 (12V域)
- LV_CONNECTOR:外部连接器,接12V电源(LV+)、LIN总线、WSTB待机信号
- DM_FILTER:输入滤波,防EMI 📄 Page 3
- SBC (TJA1128E):系统基础芯片 — 5V稳压 + LIN收发 + 看门狗 📄 Page 8
- MCU (S32K144):主控芯片 📄 Page 5
- 温度传感器:T_OUTLET / T_LS_CMOS / T_LS_NTC 📄 Page 4
- 外部ADC:I2C接口,采高压侧测量值 📄 Page 2
高压侧 (400V域)
- HV_CONNECTOR:高压连接器,接电池包400V
- IGBT模块:HS-IGBT(高侧) + LS-IGBT(低侧),功率开关 📄 Page 7
- Gate Driver (UCC5350):IGBT栅极驱动 📄 Page 7
- HE1/HE2:加热元件(Heating Element),Busbar连接
- Flyback电源:低压侧→高压侧隔离供电(17V_HS/17V_LS) 📄 Page 6
- 过流保护:电流采样 + 比较器(LM2903) 📄 Page 15-16
- 高压测量:HV_MEAS分压采样 📄 Page 2
信号流框图
┌─────────────┐ LIN ┌──────────┐
│ 空调控制器 │─────────────▶│ SBC │
│ (车上) │ │ TJA1128E │
└─────────────┘ └────┬─────┘
│ SPI/UART
┌────▼─────┐
ADC ◄─────│ MCU │─────▶ CMD_HS1 (PWM)
T_OUTLET ◄─────│ S32K144 │─────▶ CMD_LS1/LS2
T_LS_NTC ◄─────│ │─────▶ FLY_EN
T_LS_CMOS ◄─────│ │─────▶ VSUP_EN
I2C ◄───────│ │─────▶ WND (看门狗)
└──────────┘
│
┌───────┴───────┐
│ Flyback 隔离 │
└───────┬───────┘
│ 17V_HS / 17V_LS
┌───────▼───────┐
│ Gate Driver │
│ UCC5350 │
└───────┬───────┘
│ GATE_HS / GATE_LS
HV+ ──▶┌──────▼──────┐──▶ HE1/HE2 ──▶ HVGND
(400V) │ HS-IGBT │ (加热元件)
│ LS-IGBT │
└─────────────┘
项目变体
| 变体 | 型号 | 电压 | 功率 | HW CMOS |
|---|---|---|---|---|
| 00 | Full-featured | 400V | — | ✅ |
| 01 | 60PL | 400V | 7KW | ✅ |
| 02 | 60PL | 400V | 7KW | ❌ |
| 03 | 600D | 400V | 10KW | ✅ |
你当前代码的产品编号是 7DA10017,属于 60PL 系列。变体之间主要区别是功率等级和是否有CMOS安全温度传感器。
软件分层结构
代码严格分层,从上到下:
第1层:入口 (APMAIN)
文件:APMAIN_Applicative.c
main() 函数只做三件事:ICONF_vidInit() → ICONF_vidInitConfiguration() → APMODMGR_vidApplicaive()(进入无限循环)
第2层:应用层 (Applicative)
文件:Applicative/APMODMGR/
核心是模式管理状态机,for(;;) 死循环 + switch-case 切换模式。每个模式函数里按时间片执行不同的任务。
第3层:服务层 (Services)
| 模块 | 功能 |
|---|---|
SCECOM | LIN通信管理:解析指令、组装回复 |
SCEMONI | 主监控:电压/电流/温度/DCDC监控 |
SCEMONIS | 安全传感器监控:NTC/CMOS温度监控和一致性校验 |
SCEDRIV | 驱动控制:加热功率算法、温度调节 |
SCEFCTR | 故障计数器:故障记录和EEPROM管理 |
SCEWDG | 看门狗监管:喂狗 + 各时间片任务监控 |
SVCCKHW | 硬件自检:IGBT HW Check模式 |
第4层:硬件抽象层 (Handler)
| 模块 | 硬件 | 功能 |
|---|---|---|
HDADC | 片内ADC | 采样低压侧模拟信号 |
HDEXTADC | 外部ADC (I2C) | 采样高压侧测量值(隔离的) |
HDDIO | GPIO | 数字IO控制(CMD_HS1等) |
HDLIN | LIN PHY | LIN总线底层驱动和超时管理 |
HDNVM | EEPROM | 非易失存储读写(故障计数等) |
HDPWM | PWM模块 | PWM输出控制 |
HDSBC | TJA1128E | SBC配置和管理 |
HDCPU | S32K144 | CPU相关:时钟、定时器、中断 |
其他模块
OSRTE— 调度器(定时中断分频)MEMCK— 内存/堆栈检查ICONF— 初始化配置COMMON— 通用定义、版本信息
运行模式状态机
系统上电后进入 Start 模式,然后根据条件在各模式间切换。模式切换由 enuManageModeTras() 函数决定。
模式一览
| 模式 | 枚举值 | 说明 |
|---|---|---|
| 🟢 Start | STD_START_MODE | 上电初始化,跑250ms后切到Neutral或HW Check |
| 🔵 Neutral | STD_NEUTRAL_MODE | 空闲待命,监控传感器但不加热 |
| 🔵 IGBT HW Check | STD_IGBT_HW_CHECK_MODE | IGBT硬件自检模式 |
| 🔴 Heating | STD_HEATING_MODE | 正在加热!驱动IGBT输出功率 |
| ⚙️ Calibration | STD_CALIBRATION_MODE | 标定模式(工厂用) |
| ⚠️ Temp Lock | STD_TEMP_LOCK_MODE | 临时锁定:检测到可恢复故障,停止加热但保持监控 |
| ⚠️ LCM | STD_LCM_MODE | Life Cycle Management:带限制的运行模式 |
| 🔒 Perm Lock | STD_PERM_LOCK_MODE | 永久锁定:严重故障,需要维修 |
| 💤 Sleep | STD_SLEEP_MODE | 休眠:SBC进低功耗,等LIN唤醒 |
| 📥 Download | STD_DOWNLOAD_MODE | 刷写模式:更新固件 |
典型流转
上电 → Start → [HW Check OK] → Neutral → [收到加热指令] → Heating
↑ │
└─── [指令=停止] ─────────┘
Heating → [过温/过流] → Temp Lock → [故障恢复] → Neutral
Heating → [严重故障] → Perm Lock(需维修)
Neutral → [待机指令] → Sleep → [LIN唤醒] → Start
每个模式里发生什么
每个模式函数(如 enuAppHeatingMode())内部结构一样:
1ms到了?
├── 做1ms的事(ADC采样、喂狗、传感器监控)
├── 4ms到了?
│ └── 做4ms的事(LIN通信、故障管理、模式切换判断)
├── 10ms到了?
│ └── 做10ms的事(温度监控、LIN状态刷新、驱动控制)
├── 50ms到了?
│ └── 做50ms的事(加热器管理、功率管理)
└── 100ms到了?
└── 做100ms的事(IO刷新、堆栈检查、过流监控)
易错点 / 关键笔记
调度器 OSRTE
文件:OS/Src/OSRTE_Scheduler.c
OSRTE 不是操作系统,是一个极简的定时中断分频器。
工作原理
硬件定时器每 1ms 产生一次中断,调用 OSRTE_vidITSchedulerManage()。这个中断函数做的事很简单:
- 设置 1ms flag = TRUE(每次都设)
- 计数器++,到4就设 4ms flag
- 计数器++,到10就设 10ms flag
- 计数器++,到50就设 50ms flag
- 计数器++,到100就设 100ms flag
主循环里各模式函数通过 OSRTE_bReadClearFlag*msTask() 轮询这些flag,到了就执行对应的任务。读完flag自动清零。
时间片任务分配规律
| 时间片 | 典型任务 | 特点 |
|---|---|---|
| 1ms | ADC采样、喂狗、传感器状态检测、DCDC监控 | 最高优先级,每个周期都跑 |
| 4ms | LIN通信、故障管理、模式切换、NVM写入 | 通信和决策 |
| 10ms | 温度监控、LIN状态回复、驱动控制律 | 控制环路 |
| 50ms | 加热管理、功率管理 | 慢速控制 |
| 100ms | IO刷新、堆栈检查、过流监控 | 后台维护 |
SCEDRIV — 驱动控制服务
路径:Services/SCEDRIV/
负责加热功率控制的核心模块。接收LIN指令的目标功率/温度,计算PWM占空比,驱动IGBT。
关键函数
SCECOM — LIN通信服务
路径:Services/SCECOM/
管理LIN总线通信:解析空调控制器发来的指令帧,组装HVCH的状态回复帧。
关键函数
SCEMONI / SCEMONIS — 监控服务
路径:Services/SCEMONI/
系统最复杂的模块之一。分两部分:SCEMONI管主监控,SCEMONIS管安全传感器。
SCEMONI — 主监控
SCEMONIS — 安全传感器监控
bGetXxxInhibStatus()。Inhibitor = 抑制器。如果某个传感器/通道被检测到故障,就把它的inhibitor激活,后续不再用这个通道的数据做判断,防止用坏数据做决策。
SCEFCTR — 故障计数器服务
路径:Services/SCEFCTR/
管理所有故障的计数和记录。检测到故障时计数器增加,故障消失时递减(去抖动),达到阈值时触发模式切换。
关键函数
enuManageModeTras() 读取这些请求决定切到哪个模式。比如过温确认 → 请求Temp Lock,严重故障 → 请求Perm Lock。
SCEWDG — 看门狗服务
路径:Services/SCEWDG/
双重看门狗机制:
- 外部看门狗:SBC(TJA1128E)内置的看门狗,
SCEWDG_vidManageWatchDog()每1ms通过WND引脚喂一次。不喂就复位。 - 软件看门狗:
SCEWDG_vidMonitor*msTask()监控各时间片任务有没有按时执行。如果某个任务卡住超时,也会触发保护。
Handler 硬件抽象层
路径:_S32K144/Handler/
每个Handler封装一类硬件外设,上层服务不直接操作寄存器,而是调Handler的接口函数。
HDADC — 片内ADC
管理S32K144片内ADC通道的采样。主要采低压侧信号:温度传感器(T_OUTLET, T_LS_NTC)、电压(LV_MEASURE)等。
关键函数:HDADC_vidRefreshAdcChannels() — 1ms调用,刷新所有ADC通道
HDEXTADC — 外部ADC (I2C)
通过I2C接口读取高压侧的测量值。高压侧和低压侧物理隔离,片内ADC够不到,所以用外部ADC桥接。
关键函数:HDEXTADC_vidRfreshAdcExtChannel() — 1ms调用(DCDC OK时)
HDDIO — 数字IO
控制GPIO引脚的输出状态。
关键函数:HDDIO_vidSetCmdHs() — 控制高侧IGBT使能;HDDIO_vidSetFlyEn() — 控制Flyback电源使能;HDDIO_vidRefreshPorts() — 100ms刷新所有IO状态
HDLIN — LIN驱动
LIN总线底层驱动,管超时计时。
关键函数:HDLIN_vidLinTimerTask() — 1ms调用,LIN超时管理
HDNVM — EEPROM
非易失存储,保存故障计数器、标定数据等断电不能丢的东西。
关键函数:HDNVM_vidTaskManageNvmWriting() — 4ms调用,管理写入队列
HDSBC — 系统基础芯片
配置和管理TJA1128E,包括看门狗窗口设置、SPI通信等。
HDCPU — CPU管理
时钟监控、定时器管理。
关键函数:HDCPU_vidManageClockMoni() — 4ms调用,时钟监控;HDCPU_vidClearSchTimerFlag() — 在调度器中断里清除定时器标志
状态机枚举(STD_tenuMode)
定义在 standard.h 的 STD_tenuMode 枚举,是系统所有运行模式的数值定义:
| 值 | 宏名 | 含义 |
|---|---|---|
| 0 | STD_START_MODE | 启动 |
| 1 | STD_NEUTRAL_MODE | 空闲 / 中性 |
| 2 | STD_IGBT_HW_CHECK_MODE | IGBT 硬件检查 |
| 3 | STD_HEATING_MODE | 加热 |
| 4 | STD_TEMP_LOCK_MODE | 临时锁定 |
| 5 | STD_PERM_LOCK_MODE | 永久锁定 |
| 6 | STD_CALIBRATION_MODE | 标定 |
| 7 | STD_SLEEP_MODE | 休眠 |
| 8 | STD_DOWNLOAD_MODE | 下载 / 刷写 |
| 9 | STD_LCM_MODE | 生命周期管理 |
HDLIN_enuEcuState,值 0-7)是两套不同的编码。模式管理用 STD_tenuMode,对外通信用 HDLIN_enuEcuState。
故障确认累积机制
所有故障(传感器 OC/SC、功率校验、温度不一致、过流等)采用累积计数器机制,不是检测到一次就确认。
7.1 基本原理
核心逻辑:
- 检测到故障条件 → 计数器
+= ConfStep - 故障条件消失 → 计数器
-= RehabStep - 计数器
>= Counter_MAX→ 确认故障(Confirmed),计数器锁定在 Counter_MAX - 计数器
== 0→ 清除故障(No failure) 0 < 计数器 < Counter_MAX→ 偶发状态(Punctual)
ConfStep = Ceil(CounterMax x 检测周期 / 故障确认时间)RehabStep = Ceil(CounterMax x 检测周期 / 故障恢复时间)
7.2 各故障确认/恢复时间
| 故障类型 | 确认时间 | 恢复时间 | ConfStep = RehabStep? |
|---|---|---|---|
| T_OUTLET SC | 250ms | 250ms | 是,步长相等 |
| T_OUTLET OC | 250ms | 250ms | 是,步长相等 |
| 功率校验 Pwr_Check | 5000ms | 5000ms | 是(同一个 FmPowerTimeCfm) |
| 温度不一致 (Inconsistency) | 500ms | 500ms | 是,步长相等 |
| 过流 IAV(HE_Over_Curr) | 500ms | 500ms | 是(代码层面共用 FmIavInc 一个变量) |
| NTC 传感器 SC/OC | 250ms | 250ms | 是,步长相等 |
| CMOS 传感器 SC/OC | 250ms | 250ms | 是,步长相等 |
7.3 特殊情况:HE_OC
HE_OC(加热元件开路)不使用累积计数器机制。它的确认逻辑是:
- 第一次检测到硬件过流 → 设 flag
bHeOcFailDetect = TRUE - 第二次检测到 → 直接确认为临时故障(TEMP_FAIL)
- 故障计数器达到上限 → 永久锁定(PERMENENT_FAIL)
7.4 确认后行为
- 故障确认后计数器锁定在 Counter_MAX,不会自动递减
- 需要 HW Reset 才能清除
- HW Reset 后计数器清零,系统从 START 重新开始
7.5 传感器检测在哪些模式下运行
传感器开短路检测函数(NTC、CMOS、T_OUTLET)在以下模式都运行:
- Neutral(空闲)
- Heating(加热)
- Temp Lock(临时锁定)
- LCM(生命周期管理)
不运行的模式:Start、Sleep、Download
7.6 时序图场景分析
场景1:故障在确认时间内完全消失
Counter ▲
│ ╱╲
│ ╱ ╲
│ ╱ ╲
│ ╱ ╲
│╱ ╲
──────────┴──────────╲────────▶ t
0s 4s ╲→0
故障状态:No failure → Punctual → No failure
HVCH Status:保持 Heating 不变
故障条件出现后计数器累加,在 4s 确认时间内故障消失,计数器递减到 0,回到 No failure。
场景2:4s 时故障还没完全消失但最终消失
Counter ▲
│ ╱╲ ╱╲
│ ╱ ╲╱ ╲
│ ╱ ╲
│ ╱ ╲
│╱ ╲
──────────┴───┼──────────╲──▶ t
0s 4s ╲→0
故障状态:No failure → Punctual → No failure(在计数器减到 0 时才回 No failure,不是在 4s 处)
HVCH Status:保持 Heating 不变
场景3:故障最终累积到 Counter_MAX 确认
Counter ▲ ·····Counter_MAX·····
│ ╱╲ ╱╲╱╲ ╱────┐
│ ╱ ╲╱ ╱ │(锁定)
│ ╱ ╱ │
│ ╱ │
│╱ │
──────────┴───┼────────┼───────┼──▶ t
0s 4s 4+n HW Reset→0
故障状态:No failure → Punctual → Confirmed → (HW Reset) → No failure
HVCH Status:Heating → Temp Lock(或对应故障模式)→ (HW Reset) → Start
计数器在 4s 内因抖动没到 Counter_MAX,但残留值未清零,后续故障持续导致在 4+n 时刻达到 Counter_MAX 确认。n = 4 x (1 - 残留比例)。确认后计数器锁定,需 HW Reset 清除。
旧逻辑 · Outlet SC/OC(11版本)
代码位置:
SCEMONI_Services.c → SCEMONI_vidManagOutltSensorMoni()(第 3162 行起)
1. 检测周期与调用范围
- 检测周期:
u8TOUTLET_MAX_PERIODCHK = 4(4ms 一次) - 采样源:
HDADC_u16GetAdcMeasure(HDADC_MES_TEMP_T_OUTLET) - SC 与 OC 是两个独立 switch,各自一套状态变量与计数器,逻辑完全对称
调用点共 5 处(APMODMGR_Applicative.c),分属 4 个模式:
| 模式 | 函数 | 行号 |
|---|---|---|
| Neutral | enuAppNeutralMode | 752 |
| Heating | enuAppHeatingMode | 1081 |
| Temp Lock | enuAppTempLockMode | 1451、1664 |
| LCM | enuAppLCMMode | 1871 |
2. 判据与迟滞(ADC 原始值,非温度值)
| 方向 | 触发条件 | 恢复条件 | 迟滞量 |
|---|---|---|---|
| SC 短路 | ADC ≤ OutletTempMin = 29 | ADC ≥ MinWithHys = 40 | TOUTLET_SC_HYST = 11 |
| OC 开路 | ADC ≥ OutletTempMax = 1004 | ADC ≤ MaxWithHys = 991 | TOUTLET_OC_HYST = 13 |
四个值均可由 NVM 标定覆盖(HDNVM_u8OUTLET_SC_THR_MSB/LSB、OUTLET_SC_HYST_MSB/LSB 等)。
else 的 "Do nothing, keep last value",保持上一次的 Event 标志。
因此计数器在迟滞带内沿原方向继续走,不会来回翻转。
3. 三态状态机
SCEMONI_OC_SC_NO_FAILURE → SCEMONI_OC_SC_PUNCTUAL(中立/待确认) → SCEMONI_OC_SC_FAILURE
default 分支兜底置为 FAILURE——状态变量被踩坏时往安全方向倒,不往"无故障"倒。
4. Punctual 累积机制(确认 / 消失)
- 条件成立 → 计数器
+= ConfStep - 条件消失 → 计数器
-= RehabStep - 计数器
>= 65535(SCEMONI_u16FmCounterMax)→ 确认,进 FAILURE,并钉死在 65535 - 计数器
== 0→ 回 NO_FAILURE - 两者之间 → 留在 PUNCTUAL
| 项 | 宏 | 值 |
|---|---|---|
| 计数器上限 | u16FM_COUNTER_MAX | 65535 |
| 检测周期 | u8TOUTLET_MAX_PERIODCHK | 4 ms |
| SC 确认时间 | SCEMONI_u8TOUTLET_SC_FAIL_CNFT | 252 ms(实际;宏配置 250) |
| SC 恢复时间 | SCEMONI_u8TOUTLT_SC_FAIL_REHT | 252 ms(实际;宏配置 250) |
| OC 确认时间 | SCEMONI_u8TOUTLET_OC_FAIL_CNFT | 252 ms(实际;宏配置 250) |
| OC 恢复时间 | SCEMONI_u8TOUTLT_OC_FAIL_REHT | 252 ms(实际;宏配置 250) |
| ConfStep | Ceil(65535 × 4 / 250) | 1049 |
| RehabStep | Ceil(65535 × 4 / 250) | 1049 |
连续故障 63 次调用到顶(63 × 1049 = 66087 ≥ 65535),63 × 4ms = 252 ms。 SC 与 OC 的确认/恢复时间相同,故四个步长全部相等。
*_FAIL_CNFT / *_FAIL_REHT 配的是 250,
但 250 / 4 = 62.5 不是整数,ConfStep 经 Ceil 向上取整为 1049 后,
实际需要 63 次调用才越过 65535,对应 252 ms。
250 是配置值,252 是器件真实行为,报客户用 252。
counter > RehabStep 才减,否则直接置 0,
避免 uint32 绕回成天文数字。
5. 确认之后:临时锁 → 永久锁
进 FAILURE 的瞬间做四件事:
- 状态置
SCEMONI_WATERTMP_SENSOR_FAILURE - ClassAFail 置
SCEMONI_SENSOR_TEMPORARY_FAILUR(临时锁) - 写 NVM:
SCEFCTR_vidSetFailState(SCEFCTR_OUTLET_SC_CFAIL_ID) - 寿命计数 +1:
SCEFCTR_vidIncFailLifeTimeCntr(HDNVM_u8OUTLET_TEMP_SC_CNT)
PUNCTUAL 里那套递减逻辑不在 FAILURE 分支内,所以确认之后条件消失也不会自愈。
60 秒持续计时:每次调用 LOC_u8ToutletScOneSecCntr + 1,
数到 u8COUNTS_TO_ONE_SECOND = 250 才算一秒(250 × 4ms = 1000ms),
然后 SCEFCTR_vidIncFailCntr(TOUTLET_SC_FAIL_CNTR_ID)。
中间套这一层分频是为了保护 NVM 寿命,代码注释原文 "respect the NVM lifetime and prevent it from corruption"。
升永久锁的判定:先等 FAIL_CNTR ≥ TOUTLET_SC_FAIL_THR = 59(满 60 秒),
再查 RSET_CNTR ≥ TOUTLET_SC_RESET_THR = 3。两者都满足 →
SCEMONI_SENSOR_PERMENANT_FAILUR + 置 SCEFCTR_FAILURE_LOCK_ID。
不到 3 次则停在临时锁,等下一次重启。
6. HW Reset 计数从哪来
在 SCEMONI_Services.c 1317–1337 行,初始化时读 NVM:
若 SCEFCTR_bGetFailState(SCEFCTR_OUTLET_SC_CFAIL_ID) 为真,
则置 SCEMONI_bToutletScResetFlag = TRUE。
函数开头检测到该 flag 且 RSET_CNTR < u8CLASS_A_MAX_RESET_COUNT (15) 时,
RSET_CNTR + 1 并清 flag。因此这 3 次累积的是
"带着已确认故障重启过几次",不是任意重启都算。
u8CLASS_A_MAX_RESET_COUNT = 15 名字里带 CLASS_A,
但它不是 Condition A 的 3 次判据,只是递增前的溢出封顶保护。
真正判永久锁的是 SCEFCTR_bIsFailCntReachLim() 拿 RESET_THR = 3 去比。两个数各管各的。
7. 完整恢复路径
彻底清零只发生在 NO_FAILURE 态且 ADC 正常时:
- 清
FAIL_CNTR(60 秒计数) - 清
RSET_CNTR(重启次数) - ClassAFail 回
SENSOR_NORMAL - 清 NVM 故障状态
SCEFCTR_vidResetFailState()
代码注释:"to be able to do the Class A failure recovery once again"——本次 Class A 周期作废重来。
从 FAILURE 出来只有一条路:HW Reset。重启后状态机从 NO_FAILURE 起步; 若此时 ADC 已正常则走上述清零,若仍异常则直接再进 PUNCTUAL,且 RSET_CNTR 已经 +1。
旧逻辑 · 温度不一致 Sfty_LS_Inconsist(11版本)
LIN 信号:
FM_Sfty_LS_Inconsist_Cfail代码位置:
SCEMONIS_Services.c → SCEMONIS_vidManageConsisMoni()(第 3445 行起)注意文件名是 SCEMONIS(带 S),与 outlet 所在的 SCEMONI 不是同一个文件。
1. 检测周期与调用范围
- 检测周期:
u8INCONSIS_OT_CHECK_PERIOD_MS = 10(10ms 一次,outlet 是 4ms) - 采样源:
HDADC_u8GetCmosPhVal()与HDADC_u16GetNtcPhVal()——用物理值,不是 ADC 原始值
调用点共 5 处(APMODMGR_Applicative.c),分属 4 个模式,与 outlet 完全相同:
| 模式 | 函数 | 行号 |
|---|---|---|
| Neutral | enuAppNeutralMode | 847 |
| Heating | enuAppHeatingMode | 1187 |
| Temp Lock | enuAppTempLockMode | 1548、1742 |
| LCM | enuAppLCMMode | 1954 |
2. 安全冗余机制(本节独有)
__attribute__((section(".SAFEDATABYCOPY"))) 副本,四个位置逐项比对,
只要主副本对不上就立即 HDCPU_vidPerformReset() 硬复位。
原因:T_Safety 一致性检查本身就是安全机制,其自身数据必须防 RAM 单点翻转(bit flip)。
outlet 那个函数完全没有这套。
| 检查位置 | 比对项 | 项数 |
|---|---|---|
| 函数入口 | 状态、resetFlag | 2 |
| NO_FAILURE 态 | 差值阈值、IncStep | 2 |
| PUNCTUAL 态 | 阈值、迟滞、IncStep、DecStep、计数器、Flag | 6 |
| FAILURE 态 | resetFlag、一秒计数器 | 2 |
3. 判据与迟滞(物理值)
先各自换算再取绝对差:
- CMOS 物理值 =
HDADC_u8GetCmosPhVal() - NTC 物理值 =
HDADC_u16GetNtcPhVal() / SCEMONIS_u8NTC_OT_THR_FACTOR(10) delta = |CMOS − NTC|
| 动作 | 条件 | 宏 |
|---|---|---|
| 触发 | delta ≥ 140 | SCEMONIS_u8TLS_CONSIST_THR |
| 恢复 | delta ≤ 138(140 − 2) | SCEMONIS_u8TLS_CONSIST_HYS = 2 |
迟滞带 138 < delta < 140 内两个条件都不成立,保持上次标志,与 outlet 同一套路。
NTC 需先除以 10,阈值单位待 ADC-温度转换表确认,此处先记原始数值。
4. 三态状态机
SCEMONIS_OVER_TEMP_NO_FAILURE → SCEMONIS_OVER_TEMP_PUNCTUAL → SCEMONIS_OVER_TEMP_FAILURE
default 分支兜底置 FAILURE(主变量与安全副本同时置)。
5. Punctual 累积机制(确认 / 消失)
| 项 | 宏 | 值 |
|---|---|---|
| 计数器上限 | u16INCONSIS_OT_FAIL_MAX_STEP | 65535 |
| 检测周期 | u8INCONSIS_OT_CHECK_PERIOD_MS | 10 ms |
| 确认时间 | SCEMONIS_u16INCONSIS_FAIL_CNF_P | 500 ms |
| 恢复时间 | SCEMONIS_u16INCONSIS_FAIL_REH_P | 500 ms |
| IncStep | Ceil(65535 × 10 / 500) | 1311 |
| DecStep | Ceil(65535 × 10 / 500) | 1311 |
累加与递减时主计数器和 LOC_u32SafeTInconOvrTempCntr 安全副本同步操作;
递减同样有防下溢保护(先判 counter > DecStep,否则置 0)。
6. 确认之后:临时锁 → 永久锁
- ClassAFail 置
SCEMONIS_SENSOR_TEMPORARY_FAIL(主 + 安全副本) - 计数器钉死 65535,写 NVM
SCEFCTR_TEMP_INCONSIS_CFAIL_ID - 寿命计数 +1:
HDNVM_u8SFTY_INCONSIS_CNT
60 秒计时:u8INCONSIS_COUNTS_TO_ONE_SECOND = 100,100 × 10ms = 1 秒,
同样是为保护 NVM 寿命做的分频(outlet 是 250 × 4ms)。满一秒才
SCEFCTR_vidIncFailCntr(SCEFCTR_SFTY_CONSIS_CNTR_ID)。
升永久锁:先等 SFTY_CONSIS_CNTR_THR = 59(满 60 秒),
再查 SFTY_CONSIS_RESET_THR = 3。两者都满足 →
SCEMONIS_SENSOR_PERMENANT_FAIL + 置 SCEFCTR_FAILURE_LOCK_ID。
7. HW Reset 计数与恢复路径
入口处若 SCEMONIS_bInconsisResetFlag 为真且
RSET_CNTR < u8CLASS_A_MAX_RESET_COUNT (15),则
SCEFCTR_SFTY_CONSIS_HW_RES_ID + 1 并清 flag(主 + 安全副本同步)。
彻底清零只发生在 NO_FAILURE 态且 delta 正常时:清 60 秒计数、清 HW Reset 计数、
ClassAFail 回 SENSOR_NORMAL、清 NVM 故障状态。
与 outlet 一致:从 FAILURE 出来只有 HW Reset 一条路。 本节为标准 Condition A(3 次 + 60 秒),与故障清单表格完全吻合。
旧逻辑 · NTC / CMOS SC·OC(11版本)
LIN 信号:
FM_Sfty_LS_Temp_OC/SC_Cfail(NTC)、FM_Sfty2_LS_Temp_OC/SC_Cfail(CMOS)代码位置:
SCEMONIS_Services.c →
SCEMONIS_vidManageNtcSensorMoni()(3890 行)、
SCEMONIS_vidManagCmosSensorMoni()(4744 行)两个函数均带
.SAFEDATABYCOPY 安全副本机制(同温度不一致节),使用 ADC 原始值。
1. 检测周期与调用范围
u8NTC_SFTY_OC_SC_FAIL_PERIOD = 1、
u8CMOS_SFTY_OC_SC_FAIL_PERIOD = 1)。
注意三个模块各不相同:outlet 是 4ms,温度不一致是 10ms,本节是 1ms。
两个函数调用点各 5 处,分属同样 4 个模式:
| 模式 | NTC 行号 | CMOS 行号 |
|---|---|---|
| Neutral | 731 | 734 |
| Heating | 1059 | 1062 |
| Temp Lock | 1430、1646 | 1433、1649 |
| LCM | 1854 | 1857 |
2. 判据与迟滞(ADC 原始值)
| 通道 | 触发 | 恢复 | 迟滞量 | 阈值宏 |
|---|---|---|---|---|
| NTC SC | ≤ 29 | ≥ 40 | 11 | SCEMONIS_u16MIN_TLSNTC_VAL |
| NTC OC | ≥ 1004 | ≤ 978 | 26 | SCEMONIS_u16MAX_TLSNTC_VAL |
| CMOS SC | ≤ 4 | ≥ 21 | 17 | SCEMONIS_u16MIN_TLSCMOS_VAL |
| CMOS OC | ≥ 391 | ≤ 372 | 19 | SCEMONIS_u16MAX_TLSCMOS_VAL |
NTC 的 29 / 1004 与 outlet 完全相同;CMOS 是 4 / 391,量程小得多,应为不同类型的传感器。 四个迟滞值 11 / 26 / 17 / 19 各不相同,不像 outlet 那样成对配置。
3. 三态状态机与累积机制
状态机结构与前两节一致(NO_FAILURE → PUNCTUAL → FAILURE),迟滞带内保持上次标志。 主计数器与安全副本同步加减,递减带防下溢保护。
四个通道的累积参数完全一致:
| 项 | 宏 | 值 |
|---|---|---|
| 计数器上限 | u16SAFETY_CONF_COUNT_LIMIT | 65535 |
| 检测周期 | u8*_SFTY_OC_SC_FAIL_PERIOD | 1 ms |
| 确认时间 | SCEMONIS_u8{NTC,CMOS}_{SC,OC}_SFTY_CNFT | 250 ms |
| 恢复时间 | SCEMONIS_u8{NTC,CMOS}_{SC,OC}_SFTY_REHT | 250 ms |
| ConfStep | Ceil(65535 × 1 / 250) | 263 |
| RehabStep | Ceil(65535 × 1 / 250) | 263 |
4. Condition A 参数
与故障清单表格一致:NTC_SC/OC_FAIL_THR、CMOS_SC/OC_FAIL_THR 均为 59(满 60 秒),
四个 *_RESET_THR 均为 3。两者都满足才升永久锁。
5. 已知差异:60 秒分频常量为 999(不修)
| 模块 | 常量 | 周期 | 实际一格 |
|---|---|---|---|
| outlet | u8COUNTS_TO_ONE_SECOND = 250 | 4 ms | 1000 ms |
| 温度不一致 | u8INCONSIS_COUNTS_TO_ONE_SECOND = 100 | 10 ms | 1000 ms |
| NTC / CMOS | u16COUNTS_TO_ONE_SECOND = 999 | 1 ms | 999 ms |
if (u16COUNTS_TO_ONE_SECOND == LOC_u16NtcSftyScOneSecCntr),
计数器从 0 起每次 +1,等于 999 时触发并清零,中间经过 999 次调用,故一格为 999ms 而非 1000ms。影响:60 格 = 59.94 秒,比标称 60 秒短 60ms,偏差 0.1%。
结论:不修。功能上无实际差别,而改动安全相关模块的时间常量需重新走验证, 代价远大于收益。此处仅作记录备查。
旧逻辑 · HE_OC(11版本 · Condition C)
LIN 信号:
FM_HE_OC_Cfail 永久锁阈值:SCEFCTR_u8HE_OC_FAIL_THR = 3代码位置:
SCEMONI_Services.c → SCEMONI_vidIHeOcMoni()(第 3850 行起)本节与前三节几乎没有共同点——不使用累积计数器,不需要 60 秒持续,状态机是 4 态。
1. 时间基准(先理清,否则后续全错)
① 函数在 100ms 任务内调用(
bFlagTask100ms 分支)② 内部再分频:
SCEMONI_u16HeOcCheckPeriod = (SCEMONI_u8HE_OC_CHECK_PERIOD(10) × u8HE_OC_CHECK_FACTOR(10)) − 1 = 99,
SCEMONI_u16HeOcTaskCntr 每次调用 +1,到 99 才执行一次判断⇒ 100 次 × 100ms = 10 秒 / 判断周期
| 模式 | 函数 | 行号 |
|---|---|---|
| Neutral | enuAppNeutralMode | 897 |
| Heating | enuAppHeatingMode | 1241 |
| Temp Lock | enuAppTempLockMode | 1600 |
只有 3 个调用点(前三节都是 5 个),LCM 模式下不调用。
2. 四态状态机
SCEMONI_HE_OC_NO_FAIL → SCEMONI_HE_OC_PUNCTUAL →
SCEMONI_HE_OC_TEMP_FAIL → SCEMONI_HE_OC_PERMENEMT_FAIL
比前三节多一个 PERMENEMT 态——Condition A 的永久锁体现在 ClassAFail 变量上, 本节直接做进主状态机。
3. 检测条件(三层嵌套,全中才算)
| 层 | 条件 | 宏 / 值 |
|---|---|---|
| 1 | PWM 占空比 > 300 | u16HE_OC_FAIL_PWM_THR |
| 2 | (估算负载 × 100) > (标称负载 × 150) 或 IAV < 10 | u8HE_OC_LOAD_ESTIM_FACTOR = 100SCEMONI_u16HeOcLoadCoef = 150u8IAV_INCONSIS_THRESHOLD = 10 |
| 3 | HV − HE < 10 → 判 HE_OC | u16HE_OC_FAIL_VOLT_THR |
| 3' | HV − HE > 10,且 IAV < 10,且 STB=ON,且 HS 命令=ON → 判 HS_IGBT_OC | 另一条分支 |
4. 确认机制:两次命中(非累积计数器)
- 第一次条件成立 → 仅置
SCEMONI_bHeOcFailDetect = TRUE,不报故障 - 第二次成立 →
vidHeOcDetection()进TEMP_FAIL,写 NVMSCEFCTR_HE_OC_CFAIL_ID,寿命计数HDNVM_u8HE_OC_CNT+1
两次之间相隔一个判断周期,即 10 秒。
升永久锁:进 TEMP_FAIL 时立即查 SCEFCTR_HE_OC_FAIL_CNTR_ID 是否达
HE_OC_FAIL_THR = 3,达到则直接 PERMENEMT_FAIL + 置 SCEFCTR_FAILURE_LOCK_ID。
没有 60 秒持续这道门槛,这是 Condition C 与 Condition A 的本质区别。
5. HS_IGBT_OC 分支(带自恢复)
置位后若 HV − HE 回落到 10 以下且 HS 仍为 ON,则清除 SCEMONI_bHsIgbtOcState。
寿命计数走 HDNVM_u8IGBT_OC_CNT。
6. 60 秒清零机制(方向与 Condition A 相反)
Condition A 的 60 秒:故障持续存在 60 秒 → 满足升永久锁的条件之一
HE_OC 的 60 秒:正常运行 60 秒 → 把累积的故障次数清零,往回退
代码在 3974–3992:
- PWM ≥
u16HE_OC_FAIL_60S_CNTR_PWM_THR(150)且SCEMONI_u8HeOcHwRstCntrTimer ≥ u8HEOC_HW_RST_60S_CNTR(5)且bHeOcFailDetect == FALSE→SCEFCTR_vidResetFailCntr(HE_OC_FAIL_CNTR_ID) - PWM < 150 → 计时器归零
- 其余 → 计时器 ++
60 秒怎么算出来的:计时器在判断周期的 else 分支 +1,每周期 10 秒。
从 0 起,第 1~5 个周期把值从 0 加到 5,第 6 个周期时 5 ≥ 5 成立触发清零——
共 6 个周期 × 10 秒 = 60 秒,与注释 "Wait until 60 Seconds Passed" 一致。
u16HE_OC_FAIL_PWM_THR = 300 —— 检测故障用u16HE_OC_FAIL_60S_CNTR_PWM_THR = 150 —— 维持清零计时用低门槛清零、高门槛检测,意味着 PWM 处于 150~300 之间时,既不会被判故障,又能让清零计时器继续走。
注意范围:该机制清零的只是 SCEFCTR_HE_OC_FAIL_CNTR_ID 这个累积次数。
一旦已进入 PERMENEMT_FAIL、FAILURE_LOCK 写入 NVM,此机制救不回来。
旧逻辑 · Pwr_Check 功率校验(11版本 · Condition C)
LIN 信号:
FM_Pwr_Check_Cfail 永久锁阈值:SCEFCTR_u8PWR_CHK_FAIL_THR = 3代码位置:
SCEDRIV_Services.c → SCEDRIV_vidTaskManagePower()(第 1335 行起)注意本节在 SCEDRIV 模块,不在 SCEMONI / SCEMONIS。
代码里该功能统一用
PLS(Plausibility,合理性)前缀,与温度不一致
Sfty_LS_Inconsist 是两个不同的东西。
1. 时间基准
- 调用点仅 1 处:
APMODMGR_Applicative.c:1217,50ms 任务, 仅 Heating 模式(Neutral / TempLock / LCM 都不调用——不加热时没有功率可校验) - 检查周期
SCEDRIV_u16FM_MAX_PWR_CHK_PER = 50(与 50ms 任务一致) - 确认时间
SCEDRIV_u16FM_PWR_TIME_CFM_DEF = 5000→ 5 秒
u16PWRPLAUS_HW_RST_60S_CNTR = 1200,1200 × 50ms = 60000ms 正好 60 秒。
同一时间基准下两个数都能对上,确认 50ms 周期无误,故 5000 即 5 秒。
2. 判据:双区间(按目标功率分界)
| 区间 | 故障条件 | 阈值宏 |
|---|---|---|
| 目标 > 3500 | 估算功率 ≥ 目标 × 120% | SCEDRIV_u8PWR_HI_THR_DEF = 120 |
| 目标 ≤ 3500 | 估算功率 ≥ 目标 + 700 且 目标 ≥ 200 | SCEDRIV_u8PWR_HI_THR2_DEF(70) × u8RESOLUTION_FACTOR(10)SCEDRIV_MIN_POWER_REQ = 200 |
两个区间均额外要求 SCEDRIV_bPwmInconsistencyState == FALSE。
分界值宏为 u16PWR_PLS_THR_CHCK = 3500。
3. 本通道无迟滞(与前四节不同)
PWR_HI_THR_DEF = PWR_LO_THR_DEF = 120,
PWR_HI_THR2_DEF = PWR_LO_THR2_DEF = 70。
前四节都是「触发用原值、恢复用迟滞线」,中间留一段带子保持上次状态;本节两线重合,没有带子。
推论:else 分支是死代码。以「目标 > 3500」支为例:
- 故障条件 = (估算 ≥ 120%) && (PWM 一致)
- 恢复条件 = (估算 ≤ 120%) || (PWM 不一致)
后者即前者的逻辑非,两分支覆盖全部情况,第三个 else 里的
"Do nothing, Keep last value" 永远走不到。另一区间同理。
因此每个 50ms 周期都会明确判定一次,计数器要么 +656 要么 −656,不存在停在原地的情况。 功率信号本身波动较大,缺少迟滞在临界点会来回抖动,但 100 次累积把抖动摊平了, 这应是它不加迟滞的原因。
4. 累积机制
| 项 | 宏 / 公式 | 值 |
|---|---|---|
| 计数器上限 | SCEDRIV_u16FM_COUNTER_MAX | 65535 |
| 检查周期 | SCEDRIV_u16FM_MAX_PWR_CHK_PER | 50 ms |
| 确认时间 | SCEDRIV_u16FM_PWR_TIME_CFM_DEF | 5000 ms |
| 恢复时间 | 同上(共用同一参数) | 5000 ms |
| Inc | Ceil(65535 × 50 / 5000) | 656 |
| Dec | Ceil(65535 × 50 / 5000) | 656 |
到顶次数 = 65535 / 656 = 99.9 → 100 次,100 × 50ms = 5000 ms,正好整除。 递减同样带防下溢保护。
5. 60 秒清零机制(同 HE_OC,方向与 Condition A 相反)
位于 NO_FAILURE 态的无故障分支内(代码 1432–1455):
- PWM 占空比 ≥
u16CLASS_C_PWM_THR(150)→ 计时器SCEDRIV_u16PwrPlsHwRstCntrTMR++ - 计时器 ≥
u16PWRPLAUS_HW_RST_60S_CNTR(1200)→ 计时器归零,并SCEFCTR_vidResetFailCntr(SCEFCTR_PWR_CHK_COUNTER_ID)清空累积次数 - PWM < 150 → 计时器直接归零
1200 × 50ms = 60 秒。与 HE_OC 的清零机制同为「正常运行满 60 秒即把累积的故障次数一笔勾销」, 与 Condition A 的「故障持续 60 秒才升永久锁」方向相反。
6. Condition C 两节对照
| 项 | HE_OC | Pwr_Check |
|---|---|---|
| 所在模块 | SCEMONI | SCEDRIV |
| 任务周期 | 100ms(内部分频至 10s) | 50ms |
| 确认方式 | 两次命中(间隔 10s) | 累积计数(656 × 100 次 = 5s) |
| 迟滞 | — | 无 |
| 调用模式 | Neutral / Heating / TempLock | 仅 Heating |
| 60 秒清零 | 有(6 × 10s) | 有(1200 × 50ms) |
| 永久锁阈值 | 3 次 | 3 次 |
两者都带「正常运行 60 秒清账」机制,应为 Condition C 的共同设计。
旧逻辑 · HE_SC(11版本 · Condition C · 15次)
LIN 信号:
FM_HE_SC_Cfail 永久锁阈值:SCEFCTR_u8HE_SC_THR = 15(全部故障中最高)代码位置:
SCEMONI_Services.c → SCEMONI_vidTaskScHeMont(STD_tenuMode)(第 4057 行起)本节不采 ADC——读数字输入引脚
HDDIO_bGetScHeInput(),引脚为低即判短路。
1. 调用范围
- 10ms 任务,3 个调用点:Neutral(861)、Heating(1134)、Temp Lock(1564)
- 三处均包在
if(STD_bFALSE == SCEMONI_bGetDcdcInhibStatus())内—— DCDC 抑制激活时不检测 - 函数带模式入参
enuCurrentMode,这在其他故障模块里没有
2. 四态状态机
SCEMONI_SC_NO_FAILURE → SCEMONI_SC_FAILURE_NO_LOCK →
SCEMONI_SC_TEMP_LOCK / SCEMONI_SC_PERM_LOCK
FAILURE_NO_LOCK 态的整段处理逻辑外面套着
if(STD_TEMP_LOCK_MODE == enuCurrentMode)。
在 Neutral 和 Heating 下检测到引脚为低,只会切到该状态然后卡住不动,
必须等系统进入 Temp Lock 模式才开始处理。
3. 硬件复位重试机制
与其他故障"累积计数"的思路完全不同,本节是主动尝试复位硬件:
| 时机 | 动作 | 宏 |
|---|---|---|
| 计数器 = 0(首次) | HDDIO_vidSetScRst() 拉高复位引脚 | — |
| 计数器 = 1 | HDDIO_vidClearScRst() 放开复位引脚 | u8HE_SC_CLEAR_TIME = 1 |
| 计数器 ≥ 99 | 归零,置 bRecDelayElapsed,回 NO_FAILURE 重测 | u8HE_SC_FAIL_DETECT_DELAY = 99 |
99 × 10ms = 990ms,约一秒一轮重试。
4. 两层计数(解释了为何阈值是 15)
| 层 | 宏 | 值 | 含义 |
|---|---|---|---|
| 内层 | u8HE_SC_FAIL_CHK_NUM | 3 | 连续 3 轮复位重试都未清除 → 确认故障、写 NVM |
| 外层 | SCEFCTR_u8HE_SC_THR | 15 | 确认时查 HW Reset 累积次数,达 15 → PERM_LOCK |
TEMP_LOCK 与 PERM_LOCK 两态内均为空实现,什么都不做,等下次上电。
旧逻辑 · HE_Over_Curr / IAV 过流(11版本 · Condition C)
LIN 信号:
FM_HE_Over_Curr_Cfail 永久锁阈值:SCEFCTR_u8HE_OVC_THR = 3代码位置:
SCEMONI_Services.c → SCEMONI_vidIavMoni()(第 2305 行起)
1. 时间基准
- 1ms 任务,仅 1 个调用点(APMODMGR 1049),仅 Heating 模式
- 检测周期
u8HE_IAV_MAX_PERIODICTY = 1(1ms)——全部故障中检测最密的一个
2. 判据与迟滞(物理值)
| 动作 | 条件 | 宏 |
|---|---|---|
| 触发 | IavPhyVal ≥ 550 | SCEMONI_u16IAV_OVER_ON_THR_DEF |
| 恢复 | IavPhyVal ≤ 530(550 − 20) | SCEMONI_u16IAV_OVER_ON_HYS_DEF = 20 |
迟滞带 530 < val < 550 保持上次标志。
3. 累积机制
| 项 | 宏 / 公式 | 值 |
|---|---|---|
| 计数器上限 | SCEMONI_u16FmCounterMax | 65535 |
| 检测周期 | u8HE_IAV_MAX_PERIODICTY | 1 ms |
| 确认时间 | SCEMONI_u8IAV_CONF_TIME | 500 ms(宏配置) |
| Inc = Dec | Ceil(65535 × 1 / 500) | 132 |
代码实际行为为 497 ms:到顶次数 = 65535 / 132 = 496.48 → 497 次,497 × 1ms = 497 ms,比标称短 3ms。 差值仅 0.6%,此处对外仍按 500ms 报,实际值记录备查。
与 outlet 方向相反的原因:outlet 的理论次数 250/4 = 62.5 不是整数,向上凑到 63 次, 63 × 4 = 252ms 比标称长;IAV 的理论次数 500/1 = 500 本是整数, 但步长
Ceil 后 132 > 131.07,每步多走一点,497 次就够了,比标称短。
一个向上凑次数、一个向上凑步长,效果就反过来了。
4. 两个易踩的细节
SCEMONI_u16FmIavInc,
没有独立的 Dec 变量。其他模块都是 Inc / Dec 两个变量分开算(默认值虽相等,但可分别标定),
本节从代码层面锁死了两者必须相等。
LOC_u8FmIavcfm = au8Page[HDNVM_u8HE_OVER_CUR_TIME_CFM] + u8IAV_OC_CONFIRM_OFFSET(400)标定表里填的数要 +400 才是实际确认时间,读标定表时切勿看岔。
SCEMONI_enuGetIavState() 是有副作用的 getter。
该函数(2489 行)名为 Get,但内部会改写状态:if (HE_OVC 计数达限 && 当前为 STD_PERM_LOCK_MODE) → enuIavState = SCEMONI_PERMENEMT_FAIL即使主状态机没走到永久锁,只要计数器已达 3 且系统处于 PERM_LOCK 模式, 这个 getter 会顺手把状态改成永久锁。排查状态变化时只盯
vidIavMoni 主函数会漏掉这条路径。
if (enuIavState != SCEMONI_PUNCTUAL) enuRetIavtState = enuIavState;返回的是上一次非 Punctual 的值,因此外部只能拿到 NO_FAIL / TEMP_FAIL / PERMENEMT_FAIL 三种, 永远看不到 Punctual。对 LIN 上报应为有意设计——偶发状态不报给整车。
确认之后的分支(2438–2451)与其他 Condition C 同构:寿命计数
HDNVM_u8HE_OVER_CURR_CNT +1 → 查 SCEFCTR_HE_OVC_COUNTER_ID 是否达限(3)
→ 达限进 PERMENEMT_FAIL 并置 FAILURE_LOCK_ID,否则 TEMP_FAIL。
两个终态的 case 内均为自赋值的空实现,进去出不来。
5. 60 秒清零机制
与 Pwr_Check 结构相同,位于 NO_FAILURE 态的无故障分支内:
- PWM 占空比 ≥
u16CLASS_C_PWM_THR(150)→SCEMONI_u16HeOVCHwRstCntrTimer++ - 计时器 >
u16HEOVC_HW_RST_60S_CNTR(60000)→ 归零,并清空SCEFCTR_HE_OVC_COUNTER_ID - PWM < 150 → 计时器直接归零
60000 × 1ms = 60 秒。
6. Condition C 四节总对照
| 项 | HE_OC | Pwr_Check | HE_SC | HE_Over_Curr |
|---|---|---|---|---|
| 模块 | SCEMONI | SCEDRIV | SCEMONI | SCEMONI |
| 任务周期 | 100ms(分频至 10s) | 50ms | 10ms | 1ms |
| 信号源 | PWM+负载+电压 | 功率估算 | 数字引脚 | 电流物理值 |
| 确认方式 | 两次命中 | 累积 656×100 | 3 轮复位重试 | 累积 132×497 |
| 实际确认时长 | 10 s | 5000 ms | 约 990ms/轮 | 497 ms |
| 迟滞 | — | 无 | —(数字量) | 有(20) |
| 调用模式 | Neu/Heat/TL | 仅 Heating | Neu/Heat/TL | 仅 Heating |
| 60 秒清零 | 有 | 有 | 无 | 有 |
| 永久锁阈值 | 3 | 3 | 15 | 3 |
四者中三个带「正常运行 60 秒清账」机制,唯 HE_SC 没有——它改用内层 3 轮复位重试来容错。
新逻辑 · 新旧 Condition A/C 清单对照
旧逻辑 = 7DA10011 已实现的代码行为;新逻辑 = 客户新要求下的目标设计。
1. 分类定义的变化
| 类别 | 旧(11版本) | 新 |
|---|---|---|
| 自恢复 | Minor failure,12 个,不进永久锁 | OK 诊断后立即恢复 |
| Condition A | 3 次 HW Reset 且 有一次持续 60 秒 → 永久锁 | 2 次 NG 诊断(每次确认 4 秒)→ 输出 010「温度传感器特性异常」,不进永久锁 |
| Condition B | —(无此类) | 仅 IGN ON 时诊断;SW reset 后 OK 即恢复,等效自恢复 (本项目暂不涉及) |
| Condition C | 次数达阈值(3 或 15)直接永久锁 | 1 次连续 4 秒判异常,或 IGBT 异常 → 输出 011「电路异常」 |
| 永久锁 | 独立类别(HS/LS_Igbt_SC,1 次 HW reset 后锁) | 并入 Condition C,上报为「电路异常(含永久锁)」,不可恢复 |
① Condition A 不再进永久锁——counter 封顶在 2,最坏情况是一直挂在 010 等 HW reset, 直到某次诊断 OK 才恢复。永久锁现在只可能来自 Condition C。
② 永久锁不再是独立类别,并入 C 后对整车上报口径统一为 011, 总线上看永久锁与一般电路异常长得一样,区别只在内部。
2. DTC 编码
| 值 | 含义 | 说明 |
|---|---|---|
001 | 自恢复故障 | 同时被借用为 Condition A 第 1 次 NG 之后的中间态 |
010 | 需 HW reset 的故障 | Rationality abnormal / 温度传感器特性异常 |
011 | 会进永久锁的故障 | Circuit abnormal(含永久锁) |
3. 故障清单对照
旧 Condition A(7 个)→ 新 Condition A(3 个)
| 新清单 | 对应旧清单 | 备注 |
|---|---|---|
HVH_FailPowerCheck | FM_Pwr_Check_Cfail | 从旧 C 移入新 A(判定放宽),已确认——客户明确「Condition A 的功率不一致确认时间改 5s」 |
HVH_FailSensorTOut | FM_Outlet_Coolant_Temp_OC_CfailFM_Outlet_Coolant_Temp_SC_Cfail | 本就是同一信号可报 SC / OC 两种故障,不存在"合并"问题 |
FM_Sfty_LS_Inconsist_Cfail | 同名 | 唯一留在 A 类未变的 |
旧 Condition C(4 个)+ 旧永久锁(2 个)→ 新 Condition C(4 个)
| 新清单 | 对应旧清单 | 备注 |
|---|---|---|
HVH_LoadOCFail | FM_HE_OC_Cfail | 负载开路,已确认——客户 Condition C 图示标题直接写明 1.HVH_LoadOCFail |
Abnormal safety sensor | FM_Sfty_LS_Temp_OC/SC_CfailFM_Sfty2_LS_Temp_OC/SC_Cfail | 从旧 A 移入新 C(判定收严)= NTC / CMOS 四个通道,已确认(2026-07-29) |
HVH_FailHighCurrent (SW) | FM_HE_Over_Curr_Cfail | 软件测电流(IAV),已确认——即讨论中的 overcurrent,确认时间 500ms |
HVH_FailHighCurrent (HW) | FM_HE_SC_Cfail | 硬件引脚检测,已确认(客户文档直接标注 HE_SC_Cfail) |
| (IGBT 异常) | FM_HS_Igbt_SC_CfailFM_LS_Igbt_SC_Cfail | 旧独立永久锁类别,现并入 C 的永久锁分支 |
Pwr_Check:旧 C(3 次直接永久锁)→ 新 A(2 次 NG,不锁)——放宽安全温度传感器四个:旧 A(3 次 + 60 秒才锁)→ 新 C(1 次连续 4 秒就锁)——收严
4. 待定事项清单(截至 2026-07-29)
| # | 待定内容 | 影响范围 | 状态 / 倾向 |
|---|---|---|---|
| 1 | overcurrent 自恢复间隔取 1.25 s 还是 3 s | Overcurrent | 等 7/29 下午会议。1.25s 总时长正好 4000ms;3s 为 7500ms |
| 2 | uint8 装不下 4000 怎么解决——加分辨率因子,还是改 NVM 两字节布局 | outlet + NTC/CMOS 两个 | 建议加分辨率因子(改动最小);改 NVM 布局会牵扯标定工具与下线程序 |
| 3 | HE_SC 自恢复 14 次还是 15 次 | HE_SC | 14 次→间隔 280ms;15 次→260ms,均落在 4 秒内 |
| 4 | HE_SC 的 FAILURE_NO_LOCK 态是否保留 TempLock 模式限制 | HE_SC | 旧代码套着 if(TEMP_LOCK_MODE == enuCurrentMode),保留则需在该模式下连续待满 4 秒 |
| 5 | overcurrent 的 60 秒清零机制是否删除 | Overcurrent | 建议删除——新逻辑 3 次全在数秒内完成,该机制几乎不会触发 |
| 6 | NTC/CMOS | ✅ 已确认(2026-07-29):就是那四个通道 |
前 5 条均为选项问题,可在动手前择期确定;第 6 条属前提问题,已确认,
C-2 NTC/CMOS 的全部分析据此成立。
新逻辑 · Condition A 判定流程
1. 判定流程
| 阶段 | 条件 | 结果 |
|---|---|---|
| 第 1 次 NG | 诊断 4 秒不通过 | counter = 1,发 001(借用的中间态),等待 HW reset |
| 第 2 次 NG | reset 后重测,仍不通过 | counter = 2,Fail confirmed,发 010,等待 HW reset |
| 第 3 次及以后 | 仍不通过 | counter 保持 2,维持 010,继续等待 HW reset |
| 任意一次 OK | 诊断通过 | 恢复 |
每两次 NG 诊断之间必须经过一次 HW reset;counter 封顶 2,不进永久锁。
1.1 三条已确认的实现约定
两者差别很大:累计两次 = 历史上坏过两回就报;连续两次 = 必须坏得连着。本项目取后者。
| 问题 | 结论 |
|---|---|
| 第 2 次诊断 OK 时 counter 如何处理 | 清零,什么时候 OK 就什么时候清零 |
| 001 与自恢复故障的 001 冲突 | 客户已接受该复用 |
| HW reset 由谁触发 | 整车上下电,用户手动;软件不主动请求复位 |
| counter 何时 +1 | 跑完一次 4 秒诊断且结果 NG 时才 +1;不是沿用旧机制的「上电读到 NVM 故障标记就 +1」 |
| outlet 的 SC / OC 计数 | 合并计数——同属 HVH_FailSensorTOut 一个信号,两者都算在同一个 counter 里 |
SCEFCTR_bGetFailState() 为真就 RSET_CNTR++。
该机制下,用户若上电后立即下电(未跑满 4 秒、未完成诊断),counter 仍会 +1;
连续开关三次即可把 counter 刷到 2 并报出 010,而实际一次完整诊断都没做过。新逻辑取「完成诊断且 NG 才 +1」,需在诊断完成处显式递增,不能沿用上电 flag 顺带的写法。
TOUTLET_SC_RSET_CNTR_ID / TOUTLET_OC_RSET_CNTR_ID)。
新逻辑要求合并——第一次测出 SC NG、上下电后测出 OC NG,算作连续两次 NG,直接报 010。
新增
SCEMONI_u8GetToutletNgCntVal() 返回两个 NVM 计数之和,所有判定(递增前的封顶判断、
严重度选择)一律走这个和值;两个 NVM 计数器仍各存各的。这么做比合并更好:NVM 布局一个字节都不用动,而且诊断 data dump 帧里 SC / OC 那两个 4bit 字段保持独立,售后仍能分辨是短路还是开路——正好满足「诊断帧里 SC / OC 仍要分开看」这条要求。
清零时两个计数器一起清,但带守卫:只有对面通道也干净(状态机在 NO_FAILURE 且 NVM 里没有对面已确认的故障)才清,否则每个周期都会被健康的那条通道抹掉。 详见「实现记录 · Condition A 代码改动」第 4 节。
1.15 counter +1 的时机:新旧对比(2026-07-29 定)
①
SCEMONI_vidInit() 上电执行一次,若 SCEFCTR_bGetFailState(OUTLET_SC_CFAIL_ID)
为真(NVM 存着上次断电前已确认的故障),置 bToutletScResetFlag = TRUE② 监控函数开头见到该 flag 即
SCEFCTR_vidIncFailCntr(TOUTLET_SC_RSET_CNTR_ID) 并清旗⇒ 触发条件是「NVM 里有已确认故障」,不是「这次诊断 NG」; 上电后监控函数一开始跑就加了,此时本轮 4 秒诊断尚未开始。
ResetFlag 仍因 NVM 标记置位,
counter 照常 +1。连续开关三次车门即可把 counter 刷到 3,而一次完整诊断都没做过。
新逻辑:跑完一次 4 秒诊断、且结果为 NG,才 +1。
1.16 实现方案:把 +1 挪进确认分支(NVM 结构不动)
原方案(2026-07-29):现在是在函数开头
if (ResetFlag) { RSET_CNTR++; ResetFlag = FALSE; };
改为把这段挪进「计数器到顶、确认故障」的分支内,条件本身不变(即仍保留 ResetFlag 判断)。
理由是两个条件天然同时满足:ResetFlag 为真 ⇒ 上次是带着已确认故障重启的;
能走到该分支 ⇒ 本轮诊断已完成且为 NG。
原方案的问题:第一次 NG 时 NVM 里还没有故障标记,ResetFlag 为假,counter 加不上去, 要到第二次 NG 才变成 1 —— 跟客户要求的「1 次 NG → count 1、2 次 NG → count 2」整整差一次。
实际做法:
SCEMONI_bToutletScResetFlag / OcResetFlag 两个变量、
它们的初始化、上电置旗的两段 if、按旗递增的两段,全部删除;
改为在 SC / OC 各自的确认分支里、写完 NVM 故障状态之后直接递增,递增前判两个计数器之和是否已达 2。「开关车门刷计数」那个漏洞照样堵住了,而且堵得更彻底——现在触发递增的唯一条件就是「跑完一次诊断且结果 NG」, 跟上电次数彻底脱钩。
CFAIL_ID 与 reset 计数
RSET_CNTR_ID,字节数、位置、含义均不动,变的只是写入时机。
1.17 为什么不采用「恢复后才 +1」
「确认即 +1」无此问题,且 counter 与 DTC 始终一一对应—— A 类 1→001、2→010;HE_SC 1~14→001、15→011,看日志无需偏移换算。 DTC 上报时机也随之确定:与 counter 同一时刻。
1.18 counter 存储位置:按恢复方式分开
| 类型 | 故障 | 存储 | 理由 |
|---|---|---|---|
| HW reset 型 | outlet、温度不一致、Pwr_Check | NVM | 中途断电 RAM 全丢;间隔不可控(可能数天);语义本就是「带故障重启了几次」 |
| 自恢复型 | HE_SC、Overcurrent | RAM | 全程在一次上电周期内跑完(4s / 7.5s);语义是「连续 N 次」,中途断电本就该从头数 |
1.19 改动位置与难度
| 故障 | 改动 | 位置 |
|---|---|---|
| outlet SC/OC | 纯挪代码,每处四五行,逻辑不变 | SCEMONI_vidManagOutltSensorMoni() 开头 3184–3216 → 各自 PUNCTUAL 确认分支(SC 约 3325) |
| 温度不一致 | SCEMONIS_vidManageConsisMoni() 3514–3536 → 3684–3704 | |
| Pwr_Check | SCEDRIV_vidTaskManagePower() 1349–1357 → 确认分支 | |
| HE_SC | 计数改本地 static,间隔 99→28 或 26 | SCEMONI_vidTaskScHeMont() |
| Overcurrent | 新增 TEMP_FAIL 自恢复出口 + 3 秒等待计时器 | SCEMONI_vidIavMoni() |
HE_SC_COUNTER_ID、HE_OVC_COUNTER_ID 不再使用。删除需动 SCEFCTR 枚举与阈值数组、
可能牵连标定表布局;保留仅占几字节,注释标注「新逻辑不再使用」即可——这是最划算的省法。
1.2 由此推出的两点实现要求
- counter 必须存 NVM。两次 NG 之间隔着用户手动上下电,RAM 全丢,只能靠 NVM 带过去。
旧代码的
SCEFCTR_TOUTLET_SC/OC_RSET_CNTR_ID本就是 NVM 计数,机制现成,无需新建。 - 清零逻辑可复用旧实现。旧逻辑在 NO_FAILURE 态、条件不满足时清零,即「诊断 OK」, 与新要求一致。真正要改的是判定条件:旧的需 3 次 reset + 一次持续 60 秒, 新的只要连续 2 次 NG、不看持续时间,60 秒那整套删除。
SCEDRIV_vidTaskManagePower() 现状恰好就是:检测周期 50ms、
FM_PWR_TIME_CFM_DEF = 5000、ConfStep = 656、到顶 100 次 × 50ms = 5000ms。⇒ 该故障维持现状即可,参数一个都不用改。
2. 实现方式:保留累积法
团队评估:改连续法需要给每个故障加滤波取平均,改动量大;累积法只需调参数,改动最小。
3. 对外口径:n = 1000 次 / 4 s
采样周期 4ms × 1000 次 = 4000ms。这是与客户沟通、对外文档、TMC 交付的统一口径。
ConfStep = Ceil(65535 × 4 / 4000) = 66,到顶次数 = 65535 / 66 = 992.95 → 993 次,
即 3972ms,比 4000ms 少 28ms(Ceil 使步长略大于理论值,故走不满 1000 次)。该差值不对外说明——客户实测无法分辨(两次 NG 之间还隔着 HW reset 的时间), 提出反而会引来大量追问。此处仅作工程记录,便于日后调试时对得上数。
3.5 对客户的正式描述(2026-07-29 定稿,可直接引用)
Temporally 的原拼写),
只用状态名、不用 DTC 编码。
1) After an abnormality is confirmed (detected continuously for 4 s), the count
number is incremented to 1, HVCH moves to [Temporally Lock] and holds until
HW reset.
2) After HW reset (IGN OFF ⇒ ON), the diagnosis is performed again. If the result
is normal, HVCH recovers and the count number is reset to 0.
3) If the abnormality is confirmed again (detected continuously for 4 s) after
HW reset, the count number is incremented to 2, HVCH moves to
[Rationality abnormal] and holds until HW reset.
4) From the 3rd confirmation onward, the count number remains at 2 and
[Rationality abnormal] is maintained. HVCH does NOT move to Permanent lock.
Whenever the diagnosis result becomes normal, the count number is reset to 0.
Note 1: Confirmation time is 4 s, except HVH_FailPowerCheck which is 5 s.
Note 2: The count number is incremented only when a diagnosis is completed and
the result is NG. A HW reset alone does not increment the count.
| 相对客户 draft 的修改 | 原因 |
|---|---|
计数主语由 HW reset count 改为挂在「异常被确认」上 | draft 沿用旧逻辑说法;新逻辑要求跑完诊断且 NG 才 +1 |
| 第 4 条门槛由「2 consecutive HW resets」改为「从第 3 次确认起」 | 实际第 2 次诊断 NG 即报 Rationality abnormal,中间只隔 1 次 HW reset,draft 差一次 |
补写 does NOT move to Permanent lock | draft 删掉了旧版的 Permanent lock 却未说明「到此为止不再升级」,对比两版会以为是漏写 |
| 补写 4 秒确认时间及 Pwr_Check 的 5 秒例外 | draft 完全没有时间条件,读不出「连续异常多久算一次 NG」 |
detecting → confirmed | 检测到 ≠ 确认:ADC 越阈值即为检测到,须连续 4 秒才算确认,counter 在确认后才加 |
| 新增 Note 2 | 新旧逻辑最大差异,不写则看过旧文档者会沿用老理解,实现与验收将对不上 |
4. 累积法的确认时间与故障占空比(2026-08-05 已结论)
累积法的确认时间取决于故障占空比,不存在时间上界。客户曾就「为何采用累积法」提出疑问, 我方已说明最快 4 秒、最慢不作保证,客户已接受。方案维持累积法不变。
- 分母是总采样次数,不是未触发次数。它是占比不是比值: 80% 占空比 = 每 5 次采样有 4 次越阈值,写成比值才是 4:1。
- 不存在「一个完整的检测周期」。累积法没有窗口——计数器自由累加, 越阈值 +ConfStep、未越 −RehabStep,不会在任何周期边界清零重来。 所以占空比是整段故障从头到尾的平均比例,可跨几十秒甚至更久。 这正是它与滑动时间窗最本质的区别:滑动窗有记忆上限,累积法没有。
4.1 确认时间计算公式
以 outlet SC/OC 新参数为例:采样 4ms,确认时间参数 4000 ⇒
ConfStep = RehabStep = Ceil(65535 × 4 / 4000) = 66。
设 p = 越阈值采样占全部采样的比例,走 N 次采样后:
净增 = N·p·66 − N·(1−p)·66 = 66·N·(2p−1)
到顶需净增 ≥ 65535,即净增步数 993:
N = 993 / (2p − 1) 确认时间 = 4ms × N
| 占空比 p | 所需采样次数 N | 确认时间 | 说明 |
|---|---|---|---|
| 100% | 993 | 3972 ms(约 4 秒) | 对外口径的 4 秒即此值 |
| 80% | 1655 | 6620 ms(约 6.6 秒) | — |
| 60% | 4965 | 19860 ms(约 20 秒) | — |
| 50% | ∞ | 永远确认不了 | 加一次减一次,净增恒为 0 |
| < 50% | — | 永远确认不了 | 整体往下走,计数器趴在 0 |
max. confirmation time = 4 s,等于书面承诺了一个累积法给不了的保证。
客户已口头接受「最慢不保证」,但书面措辞仍建议用 min / typical 而非 max。
4.2 平衡点为何是 50%,以及不采用的调节手柄
分界线正好落在 50%,是因为 ConfStep 与 RehabStep 配了同一个值(均为 66)。
这不是架构决定的——旧代码里确认时间与恢复时间本就是两个独立的宏
(SCEMONI_u8TOUTLET_SC_FAIL_CNFT / SCEMONI_u8TOUTLT_SC_FAIL_REHT),
只是历史上都配了 250,才看着像一个数。
因此存在一个现成的手柄:把 REHT 配得比 CNFT 大,减得就比加得慢,平衡点自然下移。 例如 CNFT=4000(步长 66)、REHT=8000(步长 33),平衡点从 50% 降到 33%, 占空比三分之一以上的故障都能确认。
新逻辑 · Condition C 判定流程
counter = 1 →
DTC = 011「电路异常」→ 永久锁,HVCH 停止工作。本框架主要适用 HE_OC 与 NTC / CMOS SC·OC; overcurrent 与 HE_SC 情况特殊,待另行讨论。
1. 与 Condition A 的根本区别
| 项 | Condition A | Condition C |
|---|---|---|
| 需要几次 NG | 2 次(连续) | 1 次 |
| 两次之间 | 必须经过用户手动上下电 | —(没有第二次) |
| 中间态 | 第 1 次 NG 后发 001 | 无中间态 |
| 确认后 | DTC 010,等 HW reset,可恢复 | DTC 011,永久锁,不可恢复 |
| counter 上限 | 2 | 1 |
2. HE_OC(HVH_LoadOCFail)
客户图示:采样周期 100ms,n = 40,40 × 100ms = 4 s。
与舟舟给客户报的 4s 一致。
if (HeOcTaskCntr >= 99) { HeOcTaskCntr = 0; ...执行判断... } else { HeOcTaskCntr++; }计数器从 0 数到 99 共 100 次调用,只在第 100 次执行 1 次判断,然后清零。 即「每 100 次调用判断 1 次」,判断本身只做一次。100 × 100ms = 10 秒一判。
该分频是为 HE_OC 设计的(变量名
HeOcCheckPeriod / HeOcTaskCntr 均带 HeOc 前缀),
HS_IGBT_OC 只是写在同一判断块内被动跟随。
2.1 改动清单
| 项 | 旧 | 新 |
|---|---|---|
| 分频 | HeOcCheckPeriod = 99,10 秒一判 | 整个删除,每次 100ms 调用都判 |
| 确认方式 | 两次命中(bHeOcFailDetect),实际 20 秒 | 累积计数器 |
| 确认时间 | —(无此参数) | 新增 4000 ms |
| 步长 | — | Ceil(65535 × 100 / 4000) = 1639 |
| 到顶次数 | — | 65535/1639 = 39.98 → 40 次 = 4000ms(正好整除) |
| 永久锁阈值 | HE_OC_FAIL_THR = 3 | 1(或去掉计数,确认即锁) |
| 60 秒清零 | 有 | 删除(1 次即锁,清零无意义) |
| DTC | — | 011 |
三层检测条件本身不动:PWM > 300、(估算负载 × 100) > (标称负载 × 150) 或 IAV < 10、HV − HE < 10。
2.2 改 4 秒是好事——判据反而更严格
⇒ 从「采两个点」变成「看一整段」,误报会变少而不是变多,同时确认时间从最长 20 秒缩到 4 秒。
2.3 物理背景(判据设计依据)
HE_OC 是开路(短路是 HE_SC)。加热元件为两根 HE 并联:
- 开路一根 → 只剩一半功率,等效电阻翻倍,估算负载达标称的 2 倍
→ 越过阈值
SCEMONI_u16HeOcLoadCoef = 150(1.5 倍),由第一个分支报出 - 开路两根 → 完全不加热,电流消失 → 由第二个分支
IAV < 10报出
判据里那个「或」的两个分支正好对应开一根和开两根两种情况,是有意设计的。
2.4 HS_IGBT_OC 的副作用
if(bHsIgbtOcState == FALSE) 保护只触发一次)。
但它与 HE_OC 共用同一函数,删掉分频后它也从 10 秒粒度变为 100ms 粒度,检出会变快。IGBT 短路属严重故障,早发现是正面的——除非历史上有 IGBT 误报记录,需确认。
3. NTC / CMOS SC·OC(Abnormal safety sensor)
同属新 Condition C,采用相同判定框架。其采样周期为 1ms(与 HE_OC 的 100ms 不同), 按 4 秒确认推算:
| 项 | 值 |
|---|---|
| 检测周期 | 1 ms |
| 确认时间 | 4000 ms |
| ConfStep | Ceil(65535 × 1 / 4000) = 17 |
| 到顶次数 | 65535 / 17 = 3855 次(17 × 3855 = 65535 正好) |
| 实际确认时间 | 3855 × 1ms = 3855 ms |
Ceil 使步长略大于理论值。此差值不对外说明。
4. HE_SC(HVH_FailHighCurrent HW)—— 自恢复循环型
FM_HE_SC_Cfail,读数字引脚而非 ADC。
4.1 大逻辑
| 步骤 | 动作 |
|---|---|
| 1 | 检测到 SC → counter++,报 DTC = 001 |
| 2 | 约 285ms 后自恢复(复位硬件锁存,故障消失) |
| 3 | 进行下一次检测;若仍 SC,重复 1–2 |
| 4 | 如此自恢复 14 次 |
| 5 | 第 15 次仍 NG → DTC = 011,进永久锁 |
全过程约 4 秒内由软件自行完成,用户无需任何操作。 285ms ≈ 4000 / 14;若取 15 次则为 4000 / 15 ≈ 266.7ms。 HE_SC 检测本身耗时极短,可忽略不计,故用 4s ÷ 次数估算间隔即可。
4.2 此处的 001 是「真」自恢复,与 Condition A 不同
HE_SC 的 001 是名副其实——每次复位锁存后故障确实消失了,报自恢复故障完全对应实际行为。
两者含义不同,排查时不可混为一谈。
4.3 ⚠ 新旧「15 次」含义完全不同
SCEFCTR_HE_SC_COUNTER_ID 由 SCEMONI_bHeScFailResetFlag 驱动,
而该 flag 在 SCEMONI_vidInit()(1354–1358 行)中置位——条件是 NVM 存有 HE_SC 故障且计数未达上限。
vidInit 每次上电才执行一次,因此这 15 次是「带着故障重启 15 次」,
靠用户反复上下电攒出来,过程可长达数日。新的 15 次 = 复位硬件锁存。使用代码中现成的
HDDIO_vidSetScRst() / HDDIO_vidClearScRst(),
软件自主拉引脚,4 秒内即可完成 15 次。两者都叫「reset」、都是 15,但一个是整机重启、一个是拉引脚,差着几个数量级。 改代码与写文档时必须区分,否则极易照旧变量名的语义往下写而走岔。
4.4 结论
可以实现。「自恢复」所需的动作(清硬件锁存)代码中本就存在, 要改的是间隔、次数,以及把跨上下电的计数换成本地循环计数。具体实现待后续细化。
5. Overcurrent / IAV(HVH_FailHighCurrent SW)—— 三次确认+自恢复
FM_HE_Over_Curr_Cfail,检测周期 1ms,确认时间 500 ms
(SCEMONI_u8IAV_CONF_TIME = 500;累积法实际 497ms,对外报 500ms)。
5.1 时序
| 步骤 | 动作 | 耗时 |
|---|---|---|
| 1 | 第 1 次检测,故障确认 | 500 ms |
| 2 | counter = 1,报 DTC = 001 | — |
| 3 | 等待后故障自恢复,开始第 2 次检测 | 3 s 或 1.25 s(待定) |
| 4 | 第 2 次检测确认 → counter = 2,DTC = 001 | 500 ms |
| 5 | 再次等待、自恢复,开始第 3 次检测 | 3 s 或 1.25 s(待定) |
| 6 | 第 3 次检测确认 → counter = 3 → DTC = 011,永久锁 | 500 ms |
5.2 两个候选间隔的总时长(待 2026-07-29 下午会议确定)
| 方案 | 算式 | 总时长 | 是否落在 4 s 内 |
|---|---|---|---|
| 1.25 s | 500 + 1250 + 500 + 1250 + 500 | 4000 ms | ✅ 正好 4 秒 |
| 3 s | 500 + 3000 + 500 + 3000 + 500 | 7500 ms | ❌ 超出 |
取舍:若客户对 overcurrent 同样要求 4 秒上界,则只能选 1.25 s,3 s 出局; 若无此要求,两者皆可,而 3 s 的间隔更长,更不易被连续的瞬时干扰凑够三次,误报风险更低。
最终取值待会议结果确定,届时更新本节。
5.3 实现分析
结论:可以实现,难度中等。
确认时间 ——
SCEMONI_u8IAV_CONF_TIME = 500,本就是 500ms永久锁阈值 ——
SCEFCTR_u8HE_OVC_THR = 3,本就是 3 次
TEMP_FAIL 目前是死胡同,没有"出来"的路。现有代码该 case 内仅一句
SCEMONI_enuIavState = SCEMONI_TEMP_FAIL;(自赋值),
进入后无法退出,只能等重启。新逻辑要求确认后等待 3s / 1.25s 再自恢复并进行下一次检测,因此必须新写: 等待计时器 → 计时到 → 清故障状态、回
NO_FAIL、
counter 保留不清零,累计至 3 才进永久锁。
SCEMONI_bIavFailResetFlag 在 SCEMONI_vidInit()(789 行)置位,
条件为 NVM 存有 OVER_CURR 故障且计数未达上限——
故旧的 3 次 = 带着故障重启 3 次(跨上下电攒);
新的 3 次 = 数秒内本地循环 3 次。数字相同、语义迥异,实现时不可沿用旧路径。
6. NTC / CMOS 的改动分析(补充)
| # | 问题 | 说明 |
|---|---|---|
| 1 | 确认时间是 uint8,装不下 4000 | SCEMONIS_u8NTC_SC_SFTY_CNFT 等 8 个宏全为 (uint8)250;
局部变量 uint8 LOC_u8NtcScSftyFailConfTime;NVM 亦为单字节直读。与 outlet 完全相同的卡点 |
| 2 | 类别从 A 变 C | 判定逻辑整个换掉——删 60 秒持续、删 3 次 reset、改为确认即永久锁 |
| 3 | 带安全冗余 | 所有关键变量都有 .SAFEDATABYCOPY 副本,每处改动必须同步改副本,否则触发 HDCPU_vidPerformReset() 硬复位 |
| 4 | 四个通道 | NTC SC / NTC OC / CMOS SC / CMOS OC,同样的改动要做四遍 |
参数推算见本节第 3 部分(ConfStep = 17,到顶 3855 次 = 3855ms,对外报 4 s)。
7. Condition C 四个故障的改动难度对照
| 故障 | 难度 | 主要工作 |
|---|---|---|
| HE_OC | 最好改 | 删分频、换累积法、改几个数值——都是现成机制挪位置 |
| Overcurrent | 中等 | 参数全部现成,但需新写 TEMP_FAIL 的自恢复出口与等待计时器 |
| HE_SC | 稍麻烦 | 涉及硬件引脚拉放时序,且需把 15 次从跨上下电改为本地循环 |
| NTC / CMOS | 最麻烦 | uint8 卡点 + 类别 A→C 逻辑重写 + 安全副本同步 + 四通道重复,四项叠加 |
四者均可实现,无原理性障碍,但 NTC / CMOS 的工作量与验证成本明显高于其余三个。
outlet 传感器故障的连带影响(跨旧/新逻辑)
SCEMONI_u16GetTOutletLastValid(),
而该值在 SC/OC 状态离开 NO_FAILURE 的瞬间即冻结。
1. LIN 上报:永远是数值,不会变 invalid / SNA
上报函数 u8UpdateOutletWaterTemperature() 直接返回冻结值除以分辨率因子,
没有任何「故障时改报无效」的分支。故障状态走独立信号
u8OutletTempSensorFail_Stat3(enuGetToutletSensorState())。
- 短路时 ADC 掉到 29 以下、开路时冲到 1004 以上,这些极端读数一次都不会出现在 LIN 上——报的是故障前最后一个正常值
- 该故障位不区分开路与短路:
SC==FAILURE || OC==FAILURE都映射为同一个SENSOR_FAILURE - Punctual 期间该函数走
else分支「keep last state」,确认之前仍报 NORMAL; 按新逻辑 4 秒确认计,物理故障与 LIN 状态变化之间有 4 秒延迟
2. 温度降额失效 ⇒ 满功率持续加热
SCEDRIV_vidManageTempDerate() 取的同样是
SCEMONI_u16GetTOutletLastValid(),再拿它查降额表
(82℃→2600W、85℃→1100W、89℃→0W、90℃→0W)。outlet 故障后该值冻结(例如冻在 50℃),降额条件永远不成立, HVCH 满功率持续加热。
真正的兜底是 NTC / CMOS 这条独立的安全温度链路,到 90℃ 触发过温保护停止加热。 因此可以说温度闭环控制断了,但不是完全无保护。
3. 低流量检测同样失效
SCEMONIS_vidLowFlowMoni() 的判据是
(GetTOutletLastValid() - u16LowFlowToutPreviousVal) >= SCEMONIS_u16LowFlowThr,
用的还是那个冻结值。outlet 坏了之后温度不再更新,差值恒为 0,永远判不出低流量。
| 参数 | 值 | 说明 |
|---|---|---|
SCEMONIS_u8LOWFLOW_THR | 20 ⇒ 2.0℃ | 除以温度分辨率因子 TOUT_OT_THR_FACTOR = 10 |
u8LOW_FLOW_FILTER_SIZE | 10 | 滑动窗大小 |
SCEMONIS_u8LOWFLOW_REH_THR | 0 | 恢复阈值 |
SCEMONIS_u16LOWFLOW_REH2_THR | 600 | 第二恢复阈值(另加温度偏移) |
版本核对:7DA1000E / 7DA10011 / 7DA10017 / 7DA10018 四个版本
LOWFLOW_THR 全部为 20(即 2.0℃),未曾变动。
该值可由 NVM 标定(HDNVM_u8LOW_FLOW_THR),实际运行值以标定表为准。
另注:判断前提是目标功率处于 SCEDRIV_MIN_POWER_REQ ~ MAX_POWER_REQ 之间,不加热时不判。
4. 给前端的答复口径
可接受,但需限定含义:若指「失去温度闭环控制」,准确; 若被理解为「温度可无限上升」,则不准确——安全温度传感器仍提供保护。
建议答复中同时写明「降额同样失效、满功率运行」与「NTC/CMOS 在 90℃ 兜底」两句, 这段话日后也是「已说明存在二次保护」的书面证据。
实现记录 · Condition A 代码改动(Fox01 · outlet OC/SC)
SCEMONI_Services.c、SCEMONI_Services.h、SCEFCTR_Services.c。
未做编译验证(无 S32K144 工具链),编译与台架在舟舟侧完成。
1. 需求 ↔ 实现对照
| # | 要求 | 实现 |
|---|---|---|
| 1 | 故障确认时间 250ms → 4000ms | 加 16 倍分辨率因子,250×16 = 4000ms |
| 2 | counter 在故障确认时直接加一,不等 reset | 加一挪进 SC/OC 各自确认分支,位于写 NVM 故障状态之后 |
| 3 | 1 次 NG → counter = 1 | 一次完整诊断出 NG 加一次 |
| 4 | 2 次 NG → counter = 2 | FAILURE 无自愈出口,一个上电周期最多确认一次 |
| 5 | counter 封顶不再增长 | u8CLASS_A_NG_COUNT_MAX = 2,加一前判 < 2 |
| 6 | SC 与 OC 合起来算(对整车是一个信号 HVH_FailSensorTOut) | SCEMONI_u8GetToutletNgCntVal() 返回两个 NVM 计数之和 |
| 7 | 诊断帧里 SC / OC 仍分开看 | 两个 NVM 计数各存各的,data dump 两个 4bit 字段未动 |
| 8 | counter = 1 → ECU state 001 | MINOR → SCEFCTR minor → TEMPORALLY_LOCK = 1 |
| 9 | counter = 2 → ECU state 010 | TEMPORARY → LOCKED_UNTIL_NEXT_HW_RESET = 2 |
| 10 | 报 1 但不真自恢复,必须等 HW reset | 结构性成立,无需额外代码(见下) |
| 11 | outlet 不再进永久锁 | 60 秒累积 + 3 次 reset + vidSetFailState(FAILURE_LOCK_ID) 整段删除 |
| 12 | 诊断 OK 后计数清零 | 两个 NO_FAILURE 分支互清,带守卫 |
第 10 条为什么天然成立:TEMP_LOCK 回 NEUTRAL 的唯一条件是 SCEFCTR_NO_FAILURE
(APMODMGR_Applicative.c:2588),而 outlet 状态机进 FAILURE 后没有任何出口,
ClassAFail 恒为 MINOR 或 TEMPORARY,SCEFCTR 永远回不到 NO_FAILURE。
MINOR 与 TEMPORARY 在 APMODMGR:2465 都进 TEMP_LOCK,锁的行为完全一样,区别只在 LIN 上报的数字。
2. ECU state 编码对照(新文档二进制 ↔ 旧文档十进制)
| 二进制 | 十进制 | 枚举名 | 客户文档叫法 |
|---|---|---|---|
| 000 | 0 | OFF | OFF(初期値) |
| 001 | 1 | TEMPORALLY_LOCK | Temporally Lock(旧称 MINOR_TEMPORAY_LOCK) |
| 010 | 2 | LOCKED_UNTIL_NEXT_HW_RESET | Rationality abnormal(旧称 MAJOR_TEMPORARY_LOCK) |
| 011 | 3 | PERMANENT_LOCK | Circuit abnormal(永久锁) |
| 100 / 101 / 110 | 4 / 5 / 6 | 温控 / Derating / Power Control | — |
3. 改动清单
SCEMONI_Services.c
- 新增
u16TOUTLET_TIME_RES_FACTOR = 16(185 行)、u8CLASS_A_NG_COUNT_MAX = 2(261 行) - 删除
SCEMONI_bToutletScResetFlag/OcResetFlag、它们在vidInit的初始化、上电置标志的两段 if、上电按标志加计数的两段、两个一秒计数器 - 四处
COMMON_u16Ceil分母乘上因子(确认 / 恢复 × SC / OC) SCEMONI_enuGetClassAFailStatus()补四级优先级 PERMANENT > TEMPORARY > MINOR > NORMAL,末尾 else 降为防御兜底- 新增
SCEMONI_u8GetToutletNgCntVal() - 两个确认分支加 NG 计数递增(封顶判两者之和)
- 两个 FAILURE 分支改为按计数置 MINOR / TEMPORARY,并删掉永久锁整段
- 两个 NO_FAILURE 分支互清对方计数,带守卫
SCEMONI_Services.h
- class A 枚举末尾新增
SCEMONI_SENSOR_MINOR_FAILUR(= 3), 原 0/1/2 的值一个不动——这三个值进 NVM,改了跟旧件存量数据对不上 - 导出
SCEMONI_u8GetToutletNgCntVal()声明
SCEFCTR_Services.c
vidClassifyFails的 minor 分支条件加enuClassAfailState == SCEMONI_SENSOR_MINOR_FAILUR(1354 行)。 不加这句 MINOR 匹配不到任何分支,会掉进最后的空 else,SCEFCTR_enuFailureFlag保持上次的值不更新——真 bug,不是风格问题
4. 踩过的坑:互清计数导致计数永远为 0
根因:为满足要求 6(SC/OC 合算),在两个 NO_FAILURE 分支各加了「把对方计数器也清掉」。
但这两个分支不是恢复时跑一次,而是每个周期都在跑。SC 故障时 OC 通道健康,
OC 的 NO_FAILURE 分支每周期清一次,把 SC 刚加上的 1 立刻抹掉 →
计数恒 0 → 恒 < 2 → 恒 MINOR → ECU state 恒 1。
修复:清零加双重守卫,只有对面通道也干净时才清。
if ((SCEMONI_OC_SC_NO_FAILURE == SCEMONI_enuToutletCurrOcState)
&& (STD_bTRUE != SCEFCTR_bGetFailState(SCEFCTR_OUTLET_OC_CFAIL_ID)))
{
/* 清两个 RSET 计数 */
}
两个条件缺一不可:状态条件管本上电周期内对面正在诊断(PUNCTUAL)的情况;
NVM 条件管上次上电就已确认、而状态机开机不恢复的情况。
SC 状态机先于 OC 执行(3210 行 vs 3402 行),OC 故障时第一个周期 SC 会先跑,
那时 OC 本周期还没更新,只能靠 NVM 条件兜住。
四种组合(SC 故障 / OC 故障 / 双故障 / 修复后)均已推演;双故障修复后能在同一周期解开,
因为 vidResetFailState 不在守卫内。
5. 标定单位变更(外部影响)
四个参数:outlet OC/SC 的确认与恢复时间,NVM PAGE3 偏移 100 / 101 / 106 / 107,默认值均为 250。 字节宽度、诊断帧、LDF 全不变,只有单位变了:1 count 从 1ms 变成 16ms。 写入值 = 目标毫秒 ÷ 16。
- CAPL 脚本不用改:写入路径是通用的原始字节透传(面板填 WRITE_ID + D2~D5),无换算、无量程校验
- 要改的是人那边:标定表 LSB 1ms→16ms、量程上限 4080ms、下线程序与文档里「250 = 250ms」改成 4000ms、测试用例期望值改 4000ms
- 两个恢复时间没有诊断读写入口(SCECOM 只有确认时间那两个字节的处理器),现场标不了,只能改代码默认值。既有状况,非本次引入
- 实际确认时间是 3972ms 不是 4000ms:步长 = Ceil(65535×4/4000) = 66,993 次 × 4ms。Ceil 取整使实际值偏小(早 28ms 确认),方向保守。改动前的 250ms 同样有此偏差
- 该字节当除数用,不能写 0
- 工程内已有同类先例:
SCEDRIV_u16FM_PWR_TIME_CFM_DEF / u8PWR_CHK_RES_FACTOR
6. 上电时序行为(设计的必然结果,非 bug)
严重度不从 NVM 恢复:vidInit 每次上电把 ClassAFail 置 NORMAL。
NVM 存的是故障标志和 NG 计数,但没有代码在上电时用计数恢复严重度。
所以每次上电都要重跑完整诊断(约 3972ms)才会重新置 TEMPORARY 报 2,第 n 次上电也一样。
SCEMONI_vidManagOutltSensorMoni 在 APMODMGR 的
NEUTRAL / HEATING / TEMP_LOCK / LCM 四处 4ms 任务里被调用),
4 秒从上电起算,不是从开机请求起算。
- 上电后立刻请求开机 → 真的加热约 4 秒 → 确认故障 → 切 TEMP_LOCK 停机报 2
- 上电 4 秒后才请求开机 → 故障已在 NEUTRAL 中确认,
SCEFCTR_NO_FAILURE不成立, 请求不起作用,该次上电一次都不工作 - 因永久锁已删除,这个循环无限重复,永远不会进入「再也开不起来」的状态
2026-08-10 决定:维持现状(「上电先工作同时检测,确认故障后才会停下来」)。
7. 台架验证记录(2026-08-10)
- SC:
LIN_Coolant_temp_out_of_range先置起(短路使读数看起来温度极高,过温先于 4 秒判出), 几秒后LIN_fail_outlet_temp_sensor置起,HVCH_state 变 2,诊断上过温故障同时置起 - OC:几秒后
LIN_fail_outlet_temp_sensor置起,HVCH_state 变 2, 无 out_of_range(原因见下一节 9.1) - 台架未通高压时,高压欠压故障恒在 → SCEFCTR 恒为 minor → 上电即 TEMP_LOCK 报 1,outlet 确认后升 2。 此时产品全程未工作,「先加热 4 秒」的场景在台架上不会出现,需通高压才能复现
观察点:ECU state 在 0x11 帧 byte4;Rst_cnt 在 0x1B 帧 byte5
(高 4 位 OC、低 4 位 SC,判定用的是两者之和);寿命计数在 0x24 帧。
实现记录 · Condition A 代码改动(Fox02 · NTC/CMOS 温度不一致)
FM_Sfty_LS_Inconsist_Cfail,新 Condition A 三个故障里唯一留在 A 类没变的那个。
改动落在 4 个文件:SCEMONIS_ExtConfiguration.h、SCEMONIS_Services.h、
SCEMONIS_Services.c、SCEFCTR_Services.c。基线 Fox01 → 交付 Fox02。
未做编译验证(无 S32K144 工具链)。
1. 参数改动
| 参数 | 旧值 | 新值 | 说明 |
|---|---|---|---|
SCEMONIS_u8TLS_CONSIST_THR | 16 | 8 | 温差阈值,单位摄氏度 |
SCEMONIS_u8TLS_CONSIST_HYS | 2 | 2(不变) | 所以 8 度触发、6 度恢复 |
SCEMONIS_u16INCONSIS_FAIL_CNF_P | 500 | 4000 | 确认时间 |
SCEMONIS_u16INCONSIS_FAIL_REH_P | 500 | 4000 | 恢复时间,与确认保持一致 |
单位来源:CMOS 直接取物理值,NTC 取 HDADC_u16GetNtcPhVal() / SCEMONIS_u8NTC_OT_THR_FACTOR
换成物理值,两者相减取绝对值,所以 delta 的单位就是摄氏度,8 就是 8 度。
(注意站点「旧逻辑 · 温度不一致」那节记的是 11 版本的 140,20 版本已经是 16,本次再降到 8。)
HDNVM_u8INCONSIS_TIME_CFM_MSB / _LSB、..._REH_MSB / _LSB),
4000 直接放得下,单位仍然是 1 ms。阈值和迟滞也各有自己的 NVM 字节
(HDNVM_u8INCONSIS_THR / HDNVM_u8INCONSIS_HYST),8 也在 uint8 范围内。
所以不会出现 outlet 那种「250 现在等于 4000ms」的标定单位变更。
时间算得比 outlet 还准:检查周期 10 ms, IncStep = Ceil(65535 × 10 / 4000) = 164,到顶次数 = 65535 / 164 = 400, 400 × 10 ms = 正好 4000 ms,没有 outlet 那 28 ms 的零头。
2. 逻辑改动
- 删掉上电按 flag 加计数那套:
SCEMONIS_bInconsisResetFlag及其安全副本、 它们的初始化、vidInit里读 NVM 置旗那段、监控函数入口按旗递增那段,全部删除; 那两处 RAM 校验里对这个旗的比对也跟着去掉 - 新增
SCEMONIS_u8GetInconsisNgCntVal():读的还是SCEFCTR_SFTY_CONSIS_HW_RES_ID这个 NVM 计数器,NVM 布局没动, 只是写入时机从上电挪到了确认 - 确认分支里递增 NG 计数,递增前判
< 2封顶 - FAILURE 分支按计数选严重度:1 次置 MINOR(LIN 报 001)、2 次置 TEMPORARY(报 010), 主变量与安全副本同时写
- 删掉 60 秒累积和永久锁整段(原来是满 60 秒 + HW reset 计数到限才升永久锁)
- 清零沿用原有实现:NO_FAILURE 态且温差正常时清
SFTY_CONSIS_HW_RES_ID, 正好就是新逻辑要的「诊断 OK 就清零」。这里不需要 outlet 那种守卫—— 温度不一致只有一个通道,不存在被另一条健康通道抹掉计数的问题 - SCEFCTR 的 minor 分支条件加上
enuSafeClassAfailState == SCEMONIS_SENSOR_MINOR_FAIL
3. 与 outlet 那次的三处结构差异
| 差异 | outlet | 温度不一致 |
|---|---|---|
| 时间参数宽度 | NVM 单字节,4000 放不下,要加 16 倍分辨率因子 | NVM 两字节,直接存 4000 |
| 安全冗余 | 无 | 所有关键变量维护 SAFEDATA 副本,四处逐项比对,对不上就硬复位 |
| ClassA 枚举编码 | 普通顺序 0/1/2/3 | 4 位汉明距离编码 0x05/0x12/0x2B/0xFA |
SCEMONIS_SENSOR_MINOR_FAIL 取 0x3C,与原有四个值两两距离均为 4,已逐对验算。
同族码字里 0x48 也满足,可作备选。为什么要这样编:普通枚举 0/1/2/3 相邻值只差 1 个 bit,RAM 里一位翻转就会从一个合法值变成另一个合法值, 程序无从察觉;两两差 4 位之后,翻 1 到 3 位都会落到非法值上,能被发现。 这个模块本身就是安全机制,其自身数据必须防单点翻转。
4. 又踩到同一个坑:聚合函数把 MINOR 吃掉了
SCEMONIS_enuGetClassAFailStatus() 原本只有三个分支——任一永久就报永久、
全部正常就报正常、否则一律当临时。新置的 MINOR 会掉进最后那个 else 被当成 TEMPORARY 传出去,
SCEFCTR 里新加的 minor 判断永远匹配不到,第一次 NG 就直接报 010,改动等于白做。
已补成四级优先级 永久 > 临时 > minor > 正常,末尾 else 降级为防御兜底。
这与 outlet 那次是同一位置的同一个坑(那边是 SCEMONI_enuGetClassAFailStatus())。
以后再给别的故障加 MINOR,第一件事就是去看它的聚合函数。
5. 这个故障特有的检测条件:低压必须 ≥ 8.0 V
LOC_u8PhyTempDelta >= 阈值 && u8LvMeasure >= u8LvUvThr,
即低压电压低于 8.0 V 时根本不做这个诊断,8.0 V 整这一点仍然检测(是大于等于)。
单位追溯:LV 的 ADC 查表出来是 0.01 V 分辨率,再除以
u16LV_VOLTAGE_CALCULATION = 10 变成 0.1 V 分辨率;阈值
SCEMONI_u8LV_UV_THR_DEF = 80 即 8.0 V,可由 NVM 标定
(HDNVM_u8LV_UV_THR)。
测试须知:2026-08-11 台架上把电源调到 8 V 测出「不检测」, 说明 ECU 实际读到的是 79(7.9 V)——电源表显示 8.00 V,线阻、接插件压降、ADC 舍入凑一凑就差这零点一伏。 验这条逻辑不要卡在 8.0 V 上测,拉开距离取两点:9 V 应照常报、7 V 应完全不报, 这样零点几伏的误差不影响结论。
6. 保留未删的东西(按「少改动」原则)
u8INCONSIS_COUNTS_TO_ONE_SECOND(= 100):60 秒分频用的,新逻辑不再使用,已加注释SCEFCTR_SFTY_CONSIS_CNTR_ID:原来的 60 秒累积 NVM 计数器,现在只剩 NO_FAILURE 分支里的清零调用,已加注释u8CLASS_A_MAX_RESET_COUNT(= 15):本故障不再使用,但同文件其它监控还在用,不能删
函数内那两个一秒计数器局部变量(含 SAFEDATABYCOPY 副本)是删掉了的—— 它们随 60 秒累积一起失去用途,留着会触发 set-but-not-used 警告。保留的是宏和 NVM 计数器,不是这两个变量。
7. 台架验证观察点
温差拉到 8 度以上 → 4 秒后第一次确认,NG 计数 1、ECU state 报 001; 断电重上、温差仍在 → 第二次确认后计数 2、state 变 010;再上电仍是 2 不再涨; 温差降到 6 度以下且诊断走 OK → 计数清 0。
实现记录 · Condition A 代码改动(Fox03 · 功率不一致)
FM_Pwr_Check_Cfail,从旧 Condition C(3 次直接永久锁)移入新 Condition A(2 次 NG、不锁)。
代码在 SCEDRIV_Services.c → SCEDRIV_vidTaskManagePower(),不在 SCEMONI / SCEMONIS。
改动落在 4 个文件、19 处。diff Fox03_pwrcheck.diff(466 行,第二版含清零延时修复)。
1. 需求 ↔ 实现对照
| # | 要求 | 实现 |
|---|---|---|
| 1 | 2 次 NG 封顶 | u8CLASS_A_NG_COUNT_MAX = 2,加一前判 < 2 |
| 2 | counter 在故障确认时加一,不等 reset | 加一挪进确认分支,删掉上电按标志递增那段 |
| 3 | 1 次 NG → 001 | SCEDRIV_POWER_MINOR_FAILURE → SCEFCTR minor → TEMPORALLY_LOCK |
| 4 | 2 次 NG → 010 | SCEDRIV_POWER_TEMP_FAILURE → LOCKED_UNTIL_NEXT_HW_RESET |
| 5 | 不再进永久锁 | 删掉确认分支里置 SCEFCTR_FAILURE_LOCK_ID 那段 |
| 6 | 诊断 OK 后计数清零 | 连续 5 秒正常且 PWM 达标才清(第二版,见第 4 节) |
| 7 | NG 计数跨电源循环保留 | 存 NVM,上电不清——与 Fox04 过流正好相反 |
2. 时间参数一个都没改
检查周期 50 ms、SCEDRIV_u16FM_PWR_TIME_CFM_DEF = 5000、
Inc = Dec = Ceil(65535 × 50 / 5000) = 656、到顶 65535 / 656 = 99.9 → 100 次,
100 × 50 ms = 正好 5000 ms。客户要 5 秒(这是新 A 里唯一不是 4 秒的),现在就是 5 秒。
3. 改动清单
SCEDRIV_Services.c(13 处)
- 新增
u8CLASS_A_NG_COUNT_MAX = 2、u16PWRPLAUS_OK_5S_CNTR = 100(100 × 50 ms = 5 秒) - 新增计时器
SCEDRIV_u16PwrChkOkTMR,在vidInit与vidHeatingInit各初始化一次 - 删掉上电按标志递增
SCEFCTR_PWR_CHK_COUNTER_ID那段,递增挪进确认分支 - 确认分支:递增前判封顶;严重度按计数分 MINOR / TEMP;删掉升永久锁整段
- 新增
case SCEDRIV_POWER_MINOR_FAILURE,必须单独写——少了它会掉进 default, 下一周期状态被重置成NO_FAILURE,第 1 次 NG 保不到硬件复位 NO_FAILURE分支:清零改成连续 5 秒才清(第二版核心)- 旧的
u16PWRPLAUS_HW_RST_60S_CNTR = 1200保留不删,注释写明被新宏取代
SCEDRIV_Services.h(2 处)
- 枚举末尾追加
SCEDRIV_POWER_MINOR_FAILURE(= 4)。 这个枚举是普通顺序 0/1/2/3,不是汉明距离编码,加末尾即可,比温度不一致那次简单 - 导出
SCEDRIV_u8GetPwrChkNgCntVal()
SCEFCTR_Services.c(2 处):高边故障标志、故障分类,两处 minor 分支各加一条判断。
SCECOM_Services.c(2 处):诊断 data dump 帧的 Power Check 位、LIN power check failure signal,
两处原本只判 TEMP / PERM 的列表各加 MINOR。
4. 踩过的坑:清零太激进,大功率下计数永远为 1
第一版的做法:照搬 Fox01 的写法——检查一读 OK 就清 NG 计数,外面套 PWM 占空比门槛。
根因:这个状态机除了硬件复位没有别的出口,所以第 2 次 NG 必然从一次断电重启开始。 而重启后功率要从 0 爬到目标,这段时间估算功率还没到阈值,检查读数就是 OK, 那一拍就把上次存的 NG 计数抹了。等功率爬上来、故障重新确认,计数又从 0 加到 1。 NVM 寿命计数器是无条件累加的,不受影响,所以它老实数到 2——这个数字反过来证明检测本身是好的,坏的只是计数保持。
为什么小功率没暴露:清零那行外面套着 u16CLASS_C_PWM_THR = 150 的占空比门槛。
小功率时占空比低够不到门槛,清零被挡住,计数侥幸保住了。
不是小功率正确、大功率有 bug,是小功率恰好被门槛遮住了同一个 bug。
为什么 Fox01 同样写法却没事:outlet 传感器短路 / 断路是开关量, 故障在就一直在,重启后立刻又检出,中间没有「读 OK」的窗口。 功率不一致是连续量,加热启动必然有爬升过程,这段时间物理上就是正常的。 Fox01 的写法不能直接套到连续量的故障上。
第二版:改成连续 5 秒正常才清(100 × 50 ms)。功率约 1 秒爬到位,5 秒余量充足—— 真实的爬升期填不满计时器,而真正正常运行的产品几乎立刻就清。 原厂那个 60 秒计时器等于用小一个量级的值恢复了回来。
vidHeatingInit() 里那次清零是关键:
计时器在两个地方清零,vidInit()(上电一次)和 vidHeatingInit()(每次进加热模式)。
后者才是修复真正生效的地方——断电重启后进加热模式,计时器从 0 开始,
爬升期那几十个 OK 周期无论如何也累不到 100。
5. PWM 占空比门槛不能删
它区分的是「功率检查通过了」和「根本没有功率可检查」。小功率分支里目标功率低于
SCEDRIV_MIN_POWER_REQ(200 W)会直接判定正常——这是代码构造出来的正常,不是真的做了检查。
没有这个门槛,产品挂在加热模式但实际不发热时计数就会被反复清掉,上一个电源周期存下的 NG 白白丢失。
6. 三条已定的决策(2026-08-11)
| # | 问题 | 决定 |
|---|---|---|
| 1 | 60 秒清零机制留不留 | 清零机制与 Condition A 保持一致,但保留一个 5 秒的延时(第二版修正) |
| 2 | 只在 Heating 模式检测,不加热就不诊断 | 已知悉,按现状 |
| 3 | SCEDRIV_enuGetPowerStatus() 里那条独立永久锁路径 | 保留,做好注释 |
关于第 2 条的后果(记录备查):第一次 NG 报 001 之后,用户下次上电如果只通电不加热, 这个故障永远不会被重新诊断,counter 一直停在 1。必须下次真的加热起来、 并再连续异常 5 秒才会升到 010。测试时两次 NG 之间不光要上下电,还得真的加热。 另外两个故障在 Neutral 就开始诊断,没有这个限制。
7. 高低阈值目前标定成一样
SCEDRIV_u8PWR_HI_THR_DEF 与 SCEDRIV_u8PWR_LO_THR_DEF 都是 120,
所以大功率分支里「保持上次值」的 else 实际永远进不去,判定没有迟滞带。
本版没改这个标定(Condition A 的要求里没提),若以后想要迟滞,改这两个标定值即可,代码结构支持。
8. 台架验证记录(2026-08-14)
- 功率 < 3500 W:Rst_cnt 正常累到 2,清除正常,NVM_cnt 正常 —— 通过
- 功率 > 3500 W:第一版 Rst_cnt 卡在 1;第二版修复后累到 2、state 正常升到 010 —— 通过
实现记录 · Condition C 代码改动(Fox04 · HE 过流 IAV)
HVH_FailHighCurrent(SW detection),需求编号 2-2-2。
这一版是 Condition C,不是 Condition A——产品会自己恢复,
与 Fox01/02/03 的 MINOR 含义相反,见第 6 节。
改动落在 5 个文件、18 处。diff Fox04_ovc.diff(435 行,第二版含清零延时修复),
源码包 Fox04_src_0814b.tar.gz。
1. 规格时序(TMC 提案,2026-07-30 Accepted)
Cycle time 1 ms,检测到过流后连续确认 500 ms 算一次 NG。过流阈值默认 49.0 A, 迟滞 2.0 A(掉回 47.0 A 才算恢复)。
| 第几次 NG | Error_counter | DTC | 之后 |
|---|---|---|---|
| 第 1 次 | 1 | 001 | 锁定,3 秒后自恢复,继续下一次检测 |
| 第 2 次 | 2 | 001 | 锁定,3 秒后自恢复,继续下一次检测 |
| 第 3 次 | 3 | 011 | 永久锁,HVCH can't work |
名义总时长 500 ms × 3 + 3 s × 2 = 7.5 秒。 实测会偏长——自恢复的实际路径是 TEMP_LOCK → NEUTRAL → IGBT 硬件自检 → HEATING, 整个序列要过两次自检,规格没算这段。已与需求方确认 7.5 秒是名义值,不作硬指标。
2. 需求 ↔ 实现对照
| 要求 | 实现 |
|---|---|
| 确认时间 500 ms | 标定 SCEMONI_u8IAV_CONF_TIME = 500 |
| 判定 3 次 | SCEFCTR_u8HE_OVC_THR = 3 |
| 第 1、2 次报 001 | MINOR → SCEFCTR minor → TEMP_LOCK 模式 → TEMPORALLY_LOCK |
| 第 3 次报 011 | PERMENEMT + FAILURE_LOCK_ID → PERM_LOCK 模式 → PERMANENT_LOCK |
| 正常工作报 110 | HEATING 模式 → POWER_CONTROL_MODE |
| Self-recovery 3 秒 | u16IAV_SELF_RECOVERY_TIME_MS = 3000 × 1 ms |
| 计数不跨电源循环 | 上电无条件清零——与 Fox03 功率检查正好相反 |
| 过流消失则序列重来 | 连续正常 2 秒后清零(第二版,见第 5 节) |
3. 改动清单
SCEMONI_Services.c(12 处)
- 新增
u16IAV_SELF_RECOVERY_TIME_MS = 3000、u16IAV_OK_2S_CNTR = 2000 - 新增计时器
SCEMONI_u16IavSelfRecovCntr(自恢复)与SCEMONI_u16IavOkTMR(正常运行) - 删掉
SCEMONI_bIavFailResetFlag,上电改为无条件清零 Error_counter - 确认分支:Error_counter 在这里递增;达上限 → PERMENEMT + 永久锁,未达 → MINOR + 启动自恢复计时
- 新增
case SCEMONI_MINOR_FAIL:计时到点后清 NVM 故障位、清两个计时器、清确认计数器、回NO_FAIL NO_FAIL分支:检出过流时打断正常计时;读数正常则累加,满 2 秒才清 Error_counter- 删除旧的 60 秒硬件复位计时器
SCEMONI_u16HeOVCHwRstCntrTimer(声明 / 初始化 /vidHeatingInit三处)。 注意 OC 那个SCEMONI_u8HeOcHwRstCntrTimer(u8)没动——那是 HE 短路故障的计时器,不是同一个故障
SCEMONI_Services.h(1 处):枚举末尾追加 SCEMONI_MINOR_FAIL,
已有成员取值一个不动(这些值进 NVM 和诊断帧)。
APMODMGR_Applicative.c(1 处):
enuAppTempLockMode() 的 1 ms 任务里补上 SCEMONI_vidIavMoni() 调用 —— 死锁修复,见第 4 节。
SCEFCTR_Services.c(2 处):高边故障标志、故障分类,两处各加 MINOR 判断。
SCECOM_Services.c(2 处):诊断 data dump 帧 D4 的 b0 位、
LIN 的 IAV failure signal,两处原本只判 TEMP / PERM 的列表各加 MINOR。
4. 踩过的坑一:必现死锁
SCEFCTR_MINOR_FAILURE,而 APMODMGR 见到它就把产品
从 HEATING 踢到 TEMP_LOCK。可是 3 秒自恢复计时器是在
SCEMONI_vidIavMoni() 里数的,而这个函数原本只在 HEATING 模式调度。
结果是第 1 次过流确认就死锁:进故障 → 立刻被踢出加热模式 → 计时器不再递增 → 3 秒永远数不完 → 永远不解锁 → 永远回不到加热模式。产品卡死,只能断电,7.5 秒序列连第 2 次都走不到。
修法:在 enuAppTempLockMode() 的 1 ms 分支补上同样的调用,
守卫条件与加热模式那处完全一致(DCDC 与 I2C 抑制都未激活才跑),
位置放在 SCEFCTR_vidManageFail() 之前——这样自恢复完成的当拍,故障管理就能看到状态已回到 NO_FAIL。
通用教训:凡是「进故障态后靠计时自恢复」的设计, 都要先确认那个计时器所在的函数在故障态下还跑不跑。
5. 踩过的坑二:清零太激进(同一个错犯了两次)
根因:自恢复到点后产品解锁、重新加热,电流要约 1 秒才爬回来。 这段爬升期电流低于 49 A,读数就是正常,那一拍就把上次确认存下的 Error_counter 清成 0 了。 等电流爬上来、过流重新确认,计数又从 0 加到 1。所以每转一圈都是 0→1,永远到不了 3、永远进不了永久锁。
NVM 寿命计数器无条件累加,不受影响,所以老实数到 10——这个数字反过来证明检测本身是好的。
这个错犯了两次。Fox03 功率不一致的第一版清零策略是同一个毛病,台架先暴露的是 Fox03;
改过流时照抄了 Fox03 的第一版写法,注释里甚至留着
Same handling as the power check failure,等于把刚被否掉的逻辑又复制了一份。
第二版:改成连续正常 2 秒才清(u16IAV_OK_2S_CNTR = 2000 × 1 ms)。
电流爬升约 1 秒,2 秒给了一倍余量;过流真的消失时 2 秒后照样清零,「序列被打断」的需求保住了。
另外在检出过流的那一拍把正常计时器归零——「连续正常 2 秒」被打断就得重新计。
6. 与 Condition A 的两处「相反」
| 对比项 | Condition A(Fox01/02/03) | Condition C(Fox04) |
|---|---|---|
| MINOR 的含义 | 第 1 次 NG,报 001,不会自己恢复,要断电或 HW reset | 第 1/2 次 NG,报 001,3 秒后自己恢复继续检测 |
| 状态机出口 | 没有,进 FAILURE 就锁到硬件复位 | 有,自恢复延时到点就退出 |
| NVM 计数要求 | 必须跨电源循环保留(两次 NG 之间隔着断电重启) | 必须上电清零(三次检查是软件 7.5 秒内自己跑完的) |
改 SCEFCTR 分类时两者共用同一个 minor 分支,但注释要分开写,不要混。NVM 计数那条最容易记混。
7. 掉电重启的行为
过流确认那一刻,代码连着动三样东西,都在相邻几行:
| 量 | 含义 | 上电处理 |
|---|---|---|
故障标志位 SCEFCTR_OVER_CURR_CFAIL_ID | 只有 0/1,「故障是否正挂着」 | 不清,检查正常时自动清 0 |
Rst_cnt SCEFCTR_HE_OVC_COUNTER_ID | 图里的 1→2→3 | 本版改为清零 |
NVM cnt HDNVM_u8HE_OVER_CURR_CNT | 这个件一辈子发生过几次过流 | 不清,历史履历 |
ICONF_Initialization.c 里 SCEFCTR_enuInit()(读 NVM)
在 SCEMONI_vidInit()(清零)之前,顺序正确。以后若有人调整初始化顺序,这条会被破坏。
掉电时机不同,结果不同:
- 第 1 个 500 ms 之内掉电:三样都没动过,干净。因为置位、加计数这三行都在「500 ms 数满」之后才执行。
这段时间状态机处在疑似态(
SCEMONI_PUNCTUAL),而故障分类表里没有这一项,所以整机正常加热,状态仍是 110 - 确认完、正在数 3 秒时掉电:标志位是 1,重启后仍是 1;Rst_cnt 被清成 0
- 自恢复完成后掉电:标志位已清 0,干净
残留的标志位只影响诊断帧 D5 上那一位的显示,不影响检测流程,第一次检查正常后自动清掉。 另有一个原厂固有机制:改内存和真正写 NVM 之间有个时间窗(先打「有变动」标记,后统一写页), 卡在这个窗口掉电 NVM 里存的还是旧值。本版未改动该机制。
8. 自恢复依赖持续的加热请求
自恢复要走完,前提是整车这期间一直在请求加热。 中途撤销加热请求,模式会停在 NEUTRAL,序列自然中断,下次重新请求加热时从头开始。 已与需求方确认此行为可接受。做台架用例时如果有「故障期间松开加热请求」的场景,注意预期要按这个来。
9. 台架验证记录(2026-08-17)
- 第一版:无限循环,Rst_cnt 卡在 1,NVM_cnt 数到 10 —— 不通过
- 第二版:Rst_cnt 正常走 1→2→3,第三次确认进永久锁报 011 —— 通过
实现记录 · Condition C 代码改动(Fox05 · HE_SC 硬件过流)
HVH_FailHighCurrent(HW detection),需求编号 2-2-1。
这是 Fox04 那个故障的另一半——Fox04 是 SW 检测(2-2-2,读 ADC 电流值),
这一版是硬件比较器引脚检测,两套状态机完全独立,Fox04 的 diff 一行都没碰过 HE_SC。
Condition C 的改动只落在 SCEMONI_Services.c 一个文件,
另外还原了一处基础软件遗留的 HDLIN 改动。
diff Fox05_hesc.diff(314 行),源码包 Fox05_src_0818.tar.gz。
1. 规格时序
检出信号是 HDDIO_bGetScHeInput()——硬件比较器(LM2903)输出引脚,
低电平 = 过流,硬件 10 µs 内响应并锁存。
与 Fox04 读 ADC 电流值比阈值完全不是一条路径。
| 第几次检出 | Error_counter | ECU_State | 之后 |
|---|---|---|---|
| 第 1 ~ 14 次 | 1 ~ 14 | 001 | 产品停止输出,285 ms 后自恢复,继续下一轮 |
| 第 15 次 | 15 | 011 | 永久锁,HVCH can't work |
15 次检测 = 14 次自恢复。客户依据:过流会 damage IGBT 所以「一回判定就先停止」; 15 次是「贵司现有产品有实绩的次数」;中间是 self recovery、同一电源周期, 所以虽不满足 Condition C 的「1 回判定」,客户认为可接受。
2. 285 ms 除不尽 → 取 290 ms
SCEMONI_vidTaskScHeMont() 挂在 10 ms 任务上
(三个调用点分别在 enuAppNeutralMode / enuAppHeatingMode / enuAppTempLockMode),
所以所有时间参数都只能是 10 ms 的整数倍:28 拍 = 280 ms,29 拍 = 290 ms,没有正好 285 ms 的。
取 29 拍 = 290 ms:IGBT 保护场景宁可多给恢复时间,不要少给。 要精确 285 ms 只能把状态机挪到 1 ms 任务,会连带动复位脉冲宽度和整个时序,风险与收益不成比例。
3. 需求 ↔ 实现对照
| 要求 | 实现 |
|---|---|
| 自恢复 285 ms | u8HE_SC_FAIL_DETECT_DELAY = 29 × 10 ms = 290 ms(旧值 99 = 990 ms) |
| 检测 15 次 | u8HE_SC_FAIL_CHK_NUM = 15(台架先用 3 验证,通过后只改这一个数) |
| 前 14 次报 001 | 零改动——原厂 SCEMONI_SC_FAILURE_NO_LOCK 本就被分类成 minor |
| 第 15 次报 011 | SCEMONI_SC_PERM_LOCK + FAILURE_LOCK_ID |
| 计数不跨电源循环 | 上电无条件清零 NVM 计数(同 Fox04) |
| 某轮正常则序列重来 | 加热模式守卫 + 连续正常 2 秒(第二版,见第 6 节) |
4. 001 的上报一行代码都没改
这是本版比 Fox04 省事得多的地方。SCEFCTR_Services.c 的 vidClassifyFails() 里,
HE_SC 的三个状态原厂就已经映射好了:
| 状态机状态 | SCEFCTR 分类 | ECU_State |
|---|---|---|
SCEMONI_SC_FAILURE_NO_LOCK | MINOR | 001 |
SCEMONI_SC_TEMP_LOCK | TEMPORARY | 010 |
SCEMONI_SC_PERM_LOCK | PERMANENT | 011 |
状态机一进 FAILURE_NO_LOCK 就报 001,整个 290 ms 自恢复期间保持 001。
而 Fox04 的 IAV 原本只有 TEMP / PERMENEMT 两级,为了报 001 必须新增 SCEMONI_MINOR_FAIL 枚举,
再去 SCECOM 两处、SCEFCTR 两处补判断列表——那是 Fox04 diff 里最零碎的部分,这一版全省了。
产品也确实会停:APMODMGR 的模式转换里 Neutral 和 Heating 两处都写着
MINOR_FAILURE → STD_TEMP_LOCK_MODE,符合「一回判定就先停止」。
SCEMONI_vidIavMoni() 里、
原本只在加热模式调度,于是第一次确认就永久卡死,得去 enuAppTempLockMode() 补调用。
HE_SC 这边不存在这个问题:自恢复计时器所在分支本来就写着
if(STD_TEMP_LOCK_MODE == enuCurrentMode),而该模式函数里本来就有调用点。原厂这套是自洽的。
5. 代码里有两个 15,含义相反
SCEFCTR_u8HE_SC_THR 也是 15,但和新需求的 15 完全不是一回事,极易看混。
旧的 15(SCEFCTR_u8HE_SC_THR) | 新的 15(u8HE_SC_FAIL_CHK_NUM) | |
|---|---|---|
| 含义 | 15 个电源循环 | 15 次本地检测 |
| 谁来数 | 用户反复开关机,可能跨几天 | 软件自己 4 秒内跑完 |
| 旧逻辑 | 确认 3 次 → 临时锁;断电重启计数 +1;累计 15 次才永久锁 | |
SCEFCTR_u8HE_SC_THR 保持 15 不动(datadump 的 4 位字段还用着它),
但新逻辑不再拿它判锁——改成直接比本地计数。源码注释里也写了这段警告。
6. 清零策略:改过两版(本版最关键的一处)
第一版只要「引脚正常 + 产品在加热模式」就清零计数。 当时的判断是「HE_SC 是硬件比较器引脚、开关量,不像电流功率要爬升,所以不需要延时」。 台架现象:计数一直停在 1,进不到 3。
错在哪:加热模式只说明产品被「允许」加热,不说明电流已经建立。 每次自恢复后产品回到加热模式,电流从零开始爬,爬升期间当然没有过流、引脚读正常—— 而第一版看到「加热模式 + 正常」就把计数清了,于是计数在 0 和 1 之间反复震荡,永远到不了 15。
这与 Fox03 功率检查、Fox04 SW 过流是同一个失效模式,第三次出现。 教训是:需要延时的从来不是信号本身,而是信号背后的产品状态。 判据不该问「信号是开关量还是渐变量」,而该问 「读到『正常』的这一拍,产品是否真的处于能暴露该故障的工作状态?」
第二版改成两个条件同时满足才清零:
- 条件 ① 产品确实在加热模式(
STD_HEATING_MODE) - 条件 ② 已经连续正常
u16HE_SC_OK_TIME = 200× 10 ms = 2 秒
配套三个细节:检出时把计时器清零(每次过流后都要重新累计满 2 秒);
离开加热模式时把计时器清零而不是冻结(每次重新加热电流都要重新爬,Fox03 就栽在留了残值);
SCEFCTR_vidResetFailState() 不受这两个条件限制,引脚一正常就立即调用——
它负责让产品退出临时锁重新加热,和「清计数」是两件事,一起延后会让产品卡在锁定里。
2 秒取自 Fox04(那里电流约 1 秒爬到位,留一倍余量)。
交付前用逐拍模拟扫过「产品恢复耗时」和「电流爬升时间」两个未知量: 第一版在电流爬升 ≥ 50 ms 时全部锁不住(检出 44~111 次,计数卡在 1); 第二版在 0 ~ 1000 ms 全区间都稳定锁定。故障真消失时仍能正常清零 (检出 1 次后修好 → 2.3 秒后计数归零),已进永久锁则不清——那是正确行为。
7. 顺带修掉一个 off-by-one
原结构在自恢复完成时才 ConfCtr++、判断放在下一轮开头,
于是第 N 次检出时计数还是 N-1,要等第 N+1 次检出才判到条件成立——设 3 实际第 4 次才锁。
改成检出即计数即判,第 N 次检出就是锁定的那一次。
同时不再读 NVM 上限决定 PERM 还是 TEMP,直接按本地计数判。
SCEMONI_SC_TEMP_LOCK(010)在新逻辑下不再被进入,但枚举和消费点全部保留不动——别的故障还在用。
8. IGBT 自检不受影响
自检确实和电流有关,但走的是另一条路,三层理由:
- 自检模式函数
enuAppHwCkMode()里没有 HE_SC 状态机的调用点,那段跑的是SVCCKHW_vidTaskHwCheck() - 自检读的是
HDEXTADC_u16GetIlsPhVal()相电流 ADC 值,不是 HE_SC 引脚;HDDIO_bGetScHeInput()全工程只有两处读取(本状态机 + HDLIN 上报) - 进自检要求
SCEFCTR_NO_FAILURE,而序列进行中产品报着 001,根本进不去
9. 总时长:名义值,不作验收指标
客户图上标「4 s 後の最終判定」,来自 14 × 285 ms = 3.99 s。 本版实现是 14 × 300 ms = 4.2 s——每轮 = 290 ms 自恢复 + 10 ms 重新读引脚那一拍。 多出的 0.21 s 就是这两项差值 × 14。
| 电流爬升时间 | 每轮 | 15 次总时长 |
|---|---|---|
| 0 ms(真短路,瞬间过流) | 330 ms | 4.65 s |
| 100 ms | 430 ms | 6.15 s |
| 500 ms | 830 ms | 12.15 s |
客户的 4 s 假设自恢复后立刻又过流,即爬升时间 ≈ 0。HE_SC 是短路级保护, 真短路时电流确实瞬间上去,实机应接近 4.65 s;台架若用信号注入模拟,则取决于注入设备响应。 验收看次数和行为,不看总时长(同 Fox04 的 7.5 秒)。
10. 还原基础软件遗留改动(与本需求无关)
HDLIN_Handler.c 里 LIN 的 HVCH_ID_Code 信号被改成报 HE_SC 引脚电平,
看着是为了用 LIN 分析仪直接观测那个引脚临时挂上去的。本版已还原:
| 还原后(正确) | 还原前 | |
|---|---|---|
| 信号赋值 | kpstrSignalsStatusData->u8ID_Code_Stat2 | HDDIO_bGetScHeInput() |
| include | 无 | 多一行 #include "HDDIO_Handler.h" |
已核实它不影响任何逻辑:HDDIO_bGetScHeInput() 只调 bReadInputPin(),
纯读 GPIO,不清硬件锁存、无副作用。2026-08-17「计数卡在 1」的现象与它无关,那是清零策略的问题。
删 include 安全:该文件里 HDDIO_ 只有这两处引用。
HDLIN_Handler.c 还曾在 Unix 环境下被编辑过,行尾符从 CRLF 变成了 LF——
它是全工程 58 个源文件里唯一一个不一致的。
| 纯净原厂版 | 之前当基线的那份 | |
|---|---|---|
| 信号赋值 | u8ID_Code_Stat2 | HDDIO_bGetScHeInput() |
| include | 无 | 多 HDDIO_Handler.h |
| 行尾符 | CRLF(与全工程一致) | LF(唯一的例外) |
11. 台架验证记录(2026-08-18)
- 第一版(只有加热模式守卫):计数一直停在 1,进不到 3 —— 不通过
- 第二版 3 次测试版(模式守卫 + 连续正常 2 秒):计数正常累加,第 3 次进永久锁 —— 通过
- 15 次正式版(只改
u8HE_SC_FAIL_CHK_NUM一个宏):通过
先用 3 次验证序列逻辑是刻意安排的——每次检出都是一次真实过流、都在冲击 IGBT, 所以在逻辑没验证过之前把次数压到最低,通过后再上规格要求的 15 次。
交付版本 · 7DA10021 总包(五个故障)
1. 五个故障
| # | 故障 | 需求 | 类型 | 台架通过 |
|---|---|---|---|---|
| 1 | outlet 温度传感器 OC/SC | — | Condition A | 2026-08-10 |
| 2 | NTC/CMOS 温度不一致 | — | Condition A | 2026-08-11 |
| 3 | 功率不一致 | — | Condition A | 2026-08-14 |
| 4 | IAV 过流(SW 检测) | 2-2-2 | Condition C | 2026-08-17 |
| 5 | HE_SC 过流(HW 检测) | 2-2-1 | Condition C | 2026-08-18 |
2. 版本号怎么升
Common/Include/COMMON_Versions.h 里四个字节拼成软件版本号,只改 PATCH 一个:
| 宏 | 值 | 对应 |
|---|---|---|
COMMON_u8TYPE_SW_VERSION | 0x7D | 7D |
COMMON_u8MAJOR_SW_VERSION | 0xA1 | A1 |
COMMON_u8MINOR_SW_VERSION | 0x00 | 00 |
COMMON_u8PATCH_SW_VERSION | 0x21 | 21 ← 只改这个 |
该版本号经 LIN 的 READ_SW_VERSION(0x9A) 与 datadump 帧上报,烧录后用诊断仪读一下即可确认版本。
后续 0x22 → 7DA10022、0x23 → 7DA10023。
3. ⚠️ diff 基准换成了真正的原厂纯净版
最初当基线的那份 7DA10020_src 不是纯净的原厂版,它带着一处人为改动
(LIN 的 HVCH_ID_Code 被挪去报 HE_SC 引脚电平)和一个行尾符问题
(HDLIN_Handler.c 是 LF,全工程其余 57 个源文件都是 CRLF)。
2026-08-18 拿到真正的原厂版后,两者对比忽略行尾符实际只差 6 行,就是那两处。 换基准并把行尾符转回 CRLF 之后:
| 旧基准 | 新基准(纯净原厂版) | |
|---|---|---|
| diff 行数 | 2203 | 2183 |
| 涉及文件 | 12 个 | 11 个 |
| HDLIN | 夹在 diff 里 | 完全消失 |
| 改动性质 | 混着一处与故障无关的还原 | 全部是故障改动 |
4. 改动分布
| 文件 | + | − | 涉及故障 |
|---|---|---|---|
SCEMONI/Src/SCEMONI_Services.c | 549 | 286 | #1 #4 #5 |
SCEDRIV/Src/SCEDRIV_Services.c | 193 | 53 | #3 |
SCEMONI/Src/SCEMONIS_Services.c | 132 | 128 | #2 |
SCEMONI/Include/SCEMONI_Services.h | 30 | 2 | #4 |
SCEFCTR/Src/SCEFCTR_Services.c | 28 | 1 | #3 #4 |
SCEMONI/Include/SCEMONIS_Services.h | 26 | 0 | #2 |
SCECOM/Src/SCECOM_Services.c | 23 | 1 | #3 #4 |
SCEDRIV/Include/SCEDRIV_Services.h | 23 | 1 | #3 |
APMODMGR/Src/APMODMGR_Applicative.c | 21 | 0 | #4 |
SCEMONI/Include/SCEMONIS_ExtConfiguration.h | 20 | 3 | #2 |
Common/Include/COMMON_Versions.h | 1 | 1 | 版本号 |
| 合计 | 1046 | 476 |
5. 后续版本规划
7DA10021(本版,五个故障,冻结)
├─ 7DA10022 剩余两个故障用 Condition A
└─ 7DA10023 剩余两个故障用 Condition C
22 与 23 是并行分支、内容互斥,均以本版为基线,等客户拍板采用哪套方案。
两者的 diff 都以 7DA10021 为基准,便于直接对比两种方案的差异。
6. 一条贯穿五个故障的经验
读到「正常」的这一拍,产品是否真的处于能暴露该故障的工作状态?
只要产品刚从锁定/停机恢复,答案就是否——负载还没建立,这时读到的「正常」不携带任何故障信息。 拿它清零,计数就永远在 0/1 之间震荡,锁不住也报不上去。这个坑在 #3、#4、#5 上各踩了一次(每次都是台架才暴露)。 最终写法是双条件:产品确实在工作模式(模式守卫)且已连续正常 N 秒(计时器)。 单靠任何一个都不够;计时器还必须在离开工作模式时清零而不是冻结,否则残值会让修复失效。
7DA10022 · 安全传感器 NTC/CMOS 开短路(Condition A)
1. 先厘清一件事:它不是 LIN 上那个 out_of_range
LIN 信号 LIN_Safety_Temp_Out_Of_Range 报的是 NTC/CMOS 过温,
驱动源头是 enuGetSafetyTempOutOfRngState(),只读 NtcOtState / CmosOtState
两个过温状态,开短路那四个状态根本没进这个函数。
开短路走的是 datadump 诊断帧,四个 bit 各占一位(D2 b0 = NTC OC,D3 有 CMOS OC/SC 等)。 所以:过温走 LIN 周期信号,开短路走诊断帧,两套完全分离。本节改的是后者。
2. 与 Fox01(outlet)的异同
| Fox01 outlet | 本次 安全传感器 | |
|---|---|---|
| 确认时间宏 | 250(uint8) | 250(uint8)× 4 个 |
| 步进公式 | Ceil(65535×周期, 确认时间) | 同构 |
| 检测周期 | 4 ms | 1 ms |
| 双变量校验 | 无 | 有——每个变量带 Safe 影子,不一致直接硬复位 |
| 分支数 | 2(SC/OC) | 4(NTC/CMOS × SC/OC) |
Safe 影子是本次独有的负担:16 处步进计算全部成对存在,每改一处都要同步改影子, 漏一个就是运行时硬复位。
3. 确认时间:250 ms → 4000 ms
沿用 Fox01 的分辨率因子:标定字节仍是 uint8、值仍是 250, 单位从 1 ms 改成 16 ms,只在步进公式分母乘因子。
#define u16SFTY_TIME_RES_FACTOR ((uint16)16)
步进 = ceil(65535 / (250×16)) = ceil(16.38) = 17
次数 = ceil(65535 / 17) = 3856 次 × 1 ms = 3856 ms
4. NG 计数:四个故障共享一个
客户要求:四路独立检测、独立存储,但 NG 次数合起来算。 即 NTC_SC 一次 → counter=1;CMOS_OC 再一次 → counter=2;第三次仍是 2。
做法照搬 Fox01,只是从两路扩到四路——物理计数器各存各的(诊断帧四个 bit 照常独立显示), 只在判定时取和:
uint8 SCEMONIS_u8GetSftySensorNgCntVal(void)
{
return NTC_SC_RESET_CNTR + NTC_OC_RESET_CNTR
+ CMOS_SC_RESET_CNTR + CMOS_OC_RESET_CNTR;
}
| 改的项 | 原厂 | 改成 |
|---|---|---|
| 计数时机 | 上电时 +1(HW 复位计数) | 确认 NG 时 +1 |
| 上限 | 阈值 3 → 永久锁 | 封顶 2,无永久锁 |
| 严重度 | 只有 TEMPORARY / PERMENANT | NG<2 → MINOR(001),NG≥2 → TEMPORARY(010) |
| ResetFlag | 四套完整机制 | 全删(声明/初始化/置位/上电累加) |
u8CLASS_A_MAX_RESET_COUNT = 15 改后已无引用,
与 Fox01 一致地保留(原厂通用命名宏,删了反而给客户 diff 添无关噪音),两个文件均已加注释说明。
5. ⚠️ 2026-08-19 台架发现:NG 计数被过早清零(待改)
1. 触发 NTC_SC → 计数 1,ECU_State = 1 ✓
2. 下电,修复样件
3. 触发 NTC_OC,上电
4. NTC_OC 计数 = 1,NTC_SC 计数 = 0
→ 总数仍是 1,ECU_State = 1 ✗ 应为 2
根因是时序,不是漏加守卫。四路按固定顺序跑,SC 排在 OC 前面:
上电第 1 拍 SC 先跑 → 读数正常 → 查「别的分支有事吗」
→ OC 此刻尚未开始检测,看着是干净的
→ 清零自己那格 ← NG 就在这一拍丢的
上电第 1 拍 OC 后跑 → 读数异常 → 进入确认计时
约 4 秒后 OC 确认故障 → 计数 1(但 SC 那个 1 早没了)
⚠️ Fox01(outlet)有完全相同的行为——它的清零条件是「SC 恢复 + OC 那路健康」, 照同样步骤测 outlet 会得到一模一样的结果。这是从 Fox01 一路带下来的设计,不是本版新引入的。
同一 bug 的第二种表现:上电瞬间被清零(更隐蔽)
1. 触发 NTC_SC → NTC_SC = 1
2. 上下电
3. 同时触发 NTC_SC 与 CMOS_OC
4. 实测:NTC_SC = 1,CMOS_OC = 1(总数 2,ECU_State 2)
上下电之后 NTC_SC 是第二次确认,应该累加到 2。实测却仍是 1, 而 CMOS_OC 反倒记上了 1。逐拍推演两种假设,实测数据只与「有 bug」一组吻合:
| 步骤 | 无 bug(正确) | 有 bug(实际) |
|---|---|---|
| 首次 NTC_SC | NTC_SC=1 | NTC_SC=1 |
| 上电头几拍 | — | 读到「正常」→ NTC_SC 清零 |
| NTC_SC 确认 | NTC_SC=2,总数 2 | NTC_SC=1,总数 1 |
| CMOS_OC 确认 | 总数已封顶 → CMOS_OC=0 | CMOS_OC=1,总数 2 |
| 结果 | NTC_SC=2 CMOS_OC=0 | NTC_SC=1 CMOS_OC=1 ← 实测 |
根子与第一例相同——「读到一次正常就清零」,不区分那次正常是否真实。 区别只在触发时机:第一例是修复样件后,本例是上电信号尚未建立时 (样件刚通电、采样未稳,软件读到的「正常」是假的)。
已定方案对两种表现同时有效:上电头几拍那个「正常」撑不满 5 秒,不会触发清零。
衍生问题:封顶导致后来的分支记不上(待向客户确认)
即使修好清零问题,本例的正确结果是 NTC_SC=2、CMOS_OC=0——
CMOS_OC 确实坏过一次,却记成 0,因为总数封顶 2 之后不再往任何一路累加。
若诊断帧那四个数是给售后看「哪一路坏过几次」的,这个封顶会让后发生的故障记不上。 可选方案:各路计数照实记录,只把 ECU_State 封顶在 2。此项尚未向客户确认。
已定方案(尚未实施,2026-08-19 舟舟决定先继续测试)
清零需同时满足两条:
- 四路当前全部正常——含当前状态与 NVM 故障标记两个条件。
状态覆盖本次上电周期内正在进行的诊断,NVM 标记覆盖上电之前已确认的故障
(状态机启动时不恢复历史状态,正是本场景的关键)。
守卫函数bAreOtherSftyBranchesClean()已写好,尚未随版本发布。 - 该状态持续超过最长确认时间——建议 5 秒(4 秒确认 + 1 秒余量), 确保每一路都真正测完一轮。
改后该场景变为:
上电 → SC 读正常但先不清(等待期内)
→ 4 秒内 OC 确认故障 → 计数 1
→ SC 见 OC 有事,不清零,自己那个 1 保住
→ 总数 = 1 + 1 = 2 → ECU_State = 2 ✓
实施时 Fox01(outlet)必须同步改——同为 Condition A, 两个故障不能一个改一个不改,否则客户复测又是一轮。
2026-08-19 已实施:封顶位置从「计数」移到「State 判定」
原写法是判断用总数、累加却是自己那格,总数一满 2,后发生的分支自己那格也停在 0:
if (四路总数 < 2) ← 看总数
该路计数 + 1; ← 加自己那格
| 步骤 | 改前 | 改后 |
|---|---|---|
| NTC_SC 第 1 次 | NTC_SC=1 总1 State1 | NTC_SC=1 总1 State1 |
| 上下电,NTC_SC 第 2 次 | NTC_SC=2 总2 State2 | NTC_SC=2 总2 State2 |
| CMOS_OC 再坏一次 | CMOS_OC=0 ✗ | CMOS_OC=1 ✓ |
| ECU_State | 2 | 2(不变) |
危害在售后:诊断帧读出 CMOS_OC=0 会被判断成「CMOS 没坏过」,
可能只换 NTC 而漏掉 CMOS 侧问题;且总数封顶后诊断帧从此定格,之后哪路坏都记 0。
改法:各路计数照实累加(SCEFCTR_vidIncFailCntr() 自带溢出保护),
封顶只留在严重度判定处。ECU_State 行为完全不变,仍封顶 010。
关于 min 的说明:min(总数, 2) 是把总数截断在 2——
总数 3、4、10 一律 State 2,只会封在 2,不会退回 1。
代码实现是 if (总数 < 2) 报 001 else 报 010,效果等价。
清零语义:A(现行)与 B(备选)
| A · 单路消失即清自己那格(现行) | B · 四路全消失才清 | |
|---|---|---|
| 行为 | 某路读数恢复正常,立即清零自己的 NG | 需其余三路当前状态正常且 NVM 无故障标记 |
| 已知副作用 | 本节前述两例(修复后清零、上电瞬间清零)仍然存在 | 两例均可解 |
| 实现 | 原厂逻辑,无需改动 | 守卫函数 bAreOtherSftyBranchesClean()(已写好未发布)
+ 5 秒时间保护(4 秒确认 + 1 秒余量),
否则上电头几拍的假「正常」仍会触发清零 |
选 B 时 Fox01(outlet)必须同步改——它的清零条件同为「SC 恢复 + OC 那路健康」, 不同步会导致两个 Condition A 故障行为不一致。
待客户确认:两路同时故障是否直接跳 010
首次上电即 NTC 与 CMOS 同时故障时,两路各 +1,总数直接到 2:
NTC_SC 确认 → 总数 0→1 ECU_State=1
CMOS_SC 确认 → 总数 1→2 ECU_State=2
001 中间态确实存在但仅几毫秒——两路同属一轮 4 秒确认、几乎同时结束, LIN 上大概率采不到,表现为「第一次检测就直接 010」。
规格未覆盖此场景:截图那张图画的是时间轴上 1NG → HW reset → 2NG 依次发生, 未考虑同时故障。两种读法均说得通:
| 算 2 次(现行) | 算 1 次 | |
|---|---|---|
| 依据 | 确实存在两个故障 | NG = 一轮诊断不合格,不论几路 |
| 结果 | 首次上电直接 010 | 首次 001,第二次才 010 |
| 改动 | 无需改 | 需增加「本轮是否已计数」标记 |
建议维持现行:NTC 与 CMOS 是两个独立传感器,同时故障多半是共因(线束、供电、地线), 比单路故障更严重,安全件宜宁重勿轻;且改为「同轮算一次」需额外状态跟踪, 并会把两个真实故障记成一次,诊断帧上亦难解释。 但须客户点头——若客户按「第一次应报 001」验收,一上来看到 010 会判不通过。
6. 交付与验证
| 项 | 值 |
|---|---|
| 基线 | 7DA10021 |
| diff | 1081 行 / 3 个文件 |
| 净代码变化 | +118 / −260(净减 142 行,其余为注释与空行) |
| 版本号 | COMMON_u8PATCH_SW_VERSION = 0x22 |
| 行尾符 | CRLF,全工程 58/58 统一 |
| 台架状态 | 测试中——已发现第 5 节的问题 |
删得比加得多,因为本次主体是删逻辑:四路各删「60 秒累积 + 永久锁判定」, 加上四套 ResetFlag(OneSecCntr 32 行、ResetFlag 20 行、永久锁 8 行、复位计数递增 4 行, 再计入配套的双变量校验项与变量声明)。
待处理 · 历史遗留问题
9.1 Coolant_temp_out_of_range 只判上限,低温侧缺失
现象:outlet OC(断路,读数看起来温度极低)时
LIN_Coolant_temp_out_of_range 不置起;SC(短路,读数看起来温度极高)时会置起。
原因:SCECOM_Services.c:10783 的
enuGetCoolantTempOutOfRngState() 唯一输入是
SCEMONI_enuGetToutOverTempState(),即 outlet 过温状态;
OT 状态机(SCEMONI_Services.c:2603)的判据只有单向的
u16ToutMeasure >= SCEMONI_u16ToutOverThr,全程没有下限比较。
信号名叫 out_of_range,实现上只是过温警告。
版本对比:该函数在 7DA10011 与 7DA10020 中逐字节相同, 非本次改动引入,也非 20 版本引入,基础软件一直如此。
待办:对 LIN 规格书确认客户对该信号的定义。 若为双向(高于上限或低于下限都要置),则低温那一半从 11 版起就缺失,需补下限判断或新增低温超范围状态机; 但下限阈值、确认时间、迟滞需客户给定。若客户定义就是过温警告,则行为无误,改文档即可。
9.2 寿命计数(NVM Fail Life Time Counter)偶发被清
现象(2026-08-10 台架):故障消失后,寿命计数
(0x24 帧的 NVM_Outlet_Coolant_Temp_OC_Cnt / SC_Cnt)
有时被清除、有时没有,不稳定。判定为之前就存在的问题。
已知事实:全代码搜索 HDNVM_u8OUTLET_TEMP_SC_CNT / OC_CNT
只有三类引用——SCEMONI_Services.c:3353 / 3560 的 vidIncFailLifeTimeCntr 递增,
SCECOM_Services.c:8279 / 8282 的读取。没有任何一处清零。
所以按代码逻辑它只增不减,看到被清就是异常。
0x1B 帧)清零是设计行为(要求 12),
且只可能发生在断电重上之后——状态机进 FAILURE 后本上电周期无出口,
清零代码写在 NO_FAILURE 分支里,不断电根本执行不到。这一条与 9.2 不是一回事。
待查方向(尚未验证,仅为线索):
- NVM / EEPROM 模拟层的页写入、擦除或掉电保护逻辑,是否在某些时序下整页回默认
- 写入时机与断电的竞争:是否存在计数刚递增、页还没落盘就断电的窗口
- 读回路径:
0x24帧的字节偏移与 CAPL 解析是否始终一致(脚本 1428、1429 行) - 先记录「清了 / 没清」两种情况下的断电时机与故障持续时长,找出规律再看代码
代码 ↔ 硬件对照表
| 代码信号名 | 原理图网络 | MCU引脚 | 功能 | 原理图页 |
|---|---|---|---|---|
CMD_HS1 | CMD_HS1 | PTD15 | 高侧IGBT使能 | Page 5, 16 |
CMD_LS1 | CMD_LS1 | — | 低侧IGBT1控制 | Page 2 |
CMD_LS2 | CMD_LS2 | — | 低侧IGBT2控制 | Page 2 |
FLY_EN | FLY_EN | PTD3 | Flyback电源使能 | Page 5, 6 |
VSUP_EN | VSUP_EN | PTD3 | 电源使能 | Page 5 |
WND | WND | PTB1 | 看门狗喂狗 | Page 5, 8 |
T_OUTLET | T_OUTLET | ADC ch | 出口水温 | Page 4, 5 |
T_LS_NTC | T_LS_NTC | ADC ch | NTC安全温度 | Page 4, 5 |
T_LS_CMOS | T_LS_CMOS | ADC ch | CMOS安全温度 | Page 4, 5 |
LV_MEASURE | LV_MEASURE | ADC ch | 12V电源电压 | Page 3, 5 |
DATA_EXT_ADC | DATA_EXT_ADC | PTA2 | 外部ADC I2C数据 | Page 5 |
CLK_EXT_ADC | CLK_EXT_ADC | PTA3 | 外部ADC I2C时钟 | Page 5 |
TXD_SDI | TXD_SDI | — | SBC SPI发送 | Page 8 |
LIN | LIN | — | LIN总线 | Page 8 |
SHORT_CIRCUIT | SHORT_CIRCUIT | PTB0 | 短路检测 | Page 5 |
STB | STB | — | SBC待机控制 | Page 9 |
缩写速查表
| 缩写 | 全称 | 中文 |
|---|---|---|
| HVCH | High Voltage Coolant Heater | 高压冷却液加热器 |
| IGBT | Insulated Gate Bipolar Transistor | 绝缘栅双极晶体管(功率开关) |
| HE | Heating Element | 加热元件 |
| SBC | System Basis Chip | 系统基础芯片 |
| MCU | Micro Controller Unit | 微控制器 |
| LIN | Local Interconnect Network | 本地互联网络(车载通信协议) |
| ADC | Analog to Digital Converter | 模数转换器 |
| NVM | Non-Volatile Memory | 非易失存储(EEPROM) |
| PWM | Pulse Width Modulation | 脉宽调制 |
| DCDC | DC-DC Converter | 直流变换器 |
| NTC | Negative Temperature Coefficient | 负温度系数热敏电阻 |
| CMOS | — | CMOS温度传感器(ES0003) |
| OC | Open Circuit / Over Current | 开路(HE_OC)/ 过流(视上下文) |
| SC | Short Circuit | 短路 |
| LCM | Life Cycle Management | 生命周期管理 |
| WDG | WatchDog | 看门狗 |
| OSRTE | OS Real Time Environment | 实时环境调度器 |
| HD* | Handler | 硬件抽象层模块 |
| SCE* | Service | 服务层模块 |
| AP* | Applicative | 应用层模块 |
| vid | void | 函数名中表示无返回值 |
| b | boolean | 函数名前缀表示返回布尔值 |
| enu | enum | 函数名前缀表示返回枚举值 |
| u8/u16/u32 | unsigned 8/16/32 bit | 无符号整型 |
原理图页码索引
| 页码 | 内容 | 关联代码模块 |
|---|---|---|
| 1 | 变更历史 + 项目信息 | — |
| 2 | 系统总览框图(信号流) | 全部 |
| 3 | DM_FILTER 输入滤波 + LV_MEASURE | HDADC |
| 4 | 温度传感器 (OUTLET / CMOS / NTC) | SCEMONI, SCEMONIS |
| 5 | MCU S32K144 引脚分配 | 全部 |
| 6 | Flyback隔离电源 + 5V_HV_LS | HDDIO (FLY_EN) |
| 7 | IGBT Gate Driver (UCC5350) | HDDIO (CMD_HS1), SCEDRIV |
| 8 | SBC TJA1128E + LIN | HDSBC, HDLIN, SCECOM |
| 9 | WSTB待机 + STB控制 | SCEMONI (Standby) |
| 10-14 | 其他外围电路 | — |
| 15-16 | 过流保护 + IGBT使能逻辑 (LM2903) | SCEMONI (OC/SC), HDDIO |