3、DTC状态位详解:testFailed、testFailedThisOperationCycle、pendingDTC、confirmedDTC等8个状态位

各位工程师,咱们今天来啃一块硬骨头——DTC的8个状态位。

说实话,这8个位是UDS诊断里最容易让人头晕的地方。我刚入行那会儿,对着规范看了三天,脑子里还是一团浆糊。后来在项目里被坑了几次,才真正搞明白它们是怎么配合工作的。

嗯,咱们一个一个来拆解。

3.1 状态位的整体架构

先看一张总表,心里有个谱:

Bit位 名称 缩写 核心含义
Bit 0 testFailed TF 当前监测周期内,该故障是否激活
Bit 1 testFailedThisOperationCycle TFTOC 本次操作循环内,是否至少失败过一次
Bit 2 pendingDTC PDTC 待确认故障,等待下一个操作循环验证
Bit 3 confirmedDTC CDTC 已确认故障,需要维修或清除
Bit 4 testNotCompletedSinceLastClear TNC 上次清除后,该监测是否从未完成过
Bit 5 testFailedSinceLastClear TFSC 上次清除后,是否至少失败过一次
Bit 6 testNotCompletedThisOperationCycle TNCTOC 本次操作循环内,监测是否未完成
Bit 7 warningIndicatorRequested WIR 是否请求点亮故障指示灯(MIL)

这8个位,每个都是独立的状态标志。它们不是互斥的,可以同时为1。你想想看,一个故障可以既是pending又是confirmed吗?可以。后面咱们细说。

3.2 核心状态位详解

3.2.1 testFailed (Bit 0)

这个位最简单,也最直接。它表示:当前这个监测周期里,故障是不是激活的

举个例子。你监测一个传感器对地短路。如果当前采样到电压低于阈值,testFailed就置1。如果下一次采样正常了,testFailed立刻清0。

说白了,它就是故障的「实时快照」。ECU每跑完一次监测,就会更新这个位。

重要:testFailed只反映当前监测周期的结果。它不记忆历史,也不做任何确认。很多新手以为testFailed=1就是故障确认了,其实不是。

3.2.2 testFailedThisOperationCycle (Bit 1)

这个位比testFailed多了一层记忆。它记录的是:本次操作循环内,这个故障有没有出现过

什么叫「操作循环」?对于OBD系统来说,通常就是一次点火循环——钥匙ON到钥匙OFF。

我个人的习惯是,把这个位理解成一个「锁存器」。一旦testFailed在本次循环内变成过1,TFTOC就锁住为1,直到循环结束才复位。

为什么要这么设计?

因为有些故障是间歇性的。比如线束接触不良,可能只闪了一下就恢复了。testFailed已经变回0了,但TFTOC会告诉你:「嘿,刚才出过问题,别不当回事。」

3.2.3 pendingDTC (Bit 2)

pendingDTC,待确认故障。这个位是很多工程师的噩梦。

它的逻辑是这样的:

  • 如果本次操作循环内,testFailed出现过,pendingDTC就置1。
  • 如果下一个操作循环内,testFailed没有再出现,pendingDTC就清0。
  • 如果连续两个操作循环都出现testFailed,pendingDTC就变成confirmedDTC。

我曾经在一个项目里遇到过一个问题:客户抱怨故障灯偶尔亮一下又灭了,查了半天,发现是pendingDTC的清除条件没写对。ECU在同一个循环内反复置位和清除pendingDTC,导致状态机乱掉了。

避坑指南:pendingDTC的置位和清除,一定要严格按照规范来。不要自己发明逻辑。我曾经见过一个团队把pendingDTC当成「临时故障存储」来用,结果OBD认证死活过不了。

3.2.4 confirmedDTC (Bit 3)

confirmedDTC,已确认故障。这是8个位里最「重」的一个。

它表示:这个故障已经被ECU确认了,需要维修或者用诊断仪清除

confirmedDTC的置位条件通常是:

  • 连续两个操作循环都检测到故障(对于Type A/B故障)
  • 或者一个操作循环内故障持续了足够长时间(对于Type C故障)

一旦confirmedDTC置1,故障指示灯(MIL)通常就会点亮。而且,即使故障消失了,confirmedDTC也不会自动清0。它需要:

  • 用诊断仪发送清除命令($14服务)
  • 或者经过40个无故障的预热循环(OBD要求)

嗯,这里要注意:confirmedDTC不等于「当前有故障」。它只表示「这个故障曾经被确认过」。你读到一个confirmedDTC,不代表现在车还有问题,只代表历史上出过问题。

3.3 辅助状态位详解

3.3.1 testNotCompletedSinceLastClear (Bit 4)

这个位的意思是:自从上次清除DTC之后,这个监测有没有完整地跑过一次

如果ECU上电后,某个监测因为条件不满足(比如发动机没达到工作温度)一直没执行,那TNC就一直为1。

我个人觉得,这个位是诊断工程师的「照妖镜」。它能告诉你:是故障真的不存在,还是监测根本没跑。

3.3.2 testFailedSinceLastClear (Bit 5)

这个位和TFTOC有点像,但范围更大。它记录的是:自从上次清除DTC以来,这个故障有没有出现过

它不会在操作循环结束时复位。它会一直保持为1,直到你手动清除DTC。

你想想看,这个位有什么用?

假设一辆车进店维修,你读DTC发现confirmedDTC=0,但TFSC=1。这说明什么?说明故障曾经出现过,但还没达到确认条件。这能帮你判断故障是偶发的还是持续的。

3.3.3 testNotCompletedThisOperationCycle (Bit 6)

这个位和TNC类似,但范围缩小到本次操作循环。它表示:本次循环内,这个监测是否还没完成

如果监测已经跑完了,不管结果是pass还是fail,TNCTOC都会清0。

我记得有一次调试,发现某个DTC的TNCTOC一直为1,查了半天,原来是监测的使能条件写错了,导致监测永远启动不了。嗯,这种问题在开发阶段很常见。

3.3.4 warningIndicatorRequested (Bit 7)

这个位最直接:要不要点亮故障灯

通常,当confirmedDTC置1时,WIR也会置1。但有些OEM会定义自己的点亮策略,比如某些排放相关的故障,pendingDTC阶段就点亮MIL。

注意:WIR只是「请求」点亮指示灯。最终灯亮不亮,还要看ECU的指示灯驱动逻辑。有些ECU会做灯的自检,或者有延时点亮策略。不要以为WIR=1就一定能看到灯亮。

3.4 状态位的转换逻辑

说了这么多,咱们用一张流程图来总结状态位的转换关系:

监测开始
  |
  +-- testFailed = 当前结果
  |
  +-- 如果testFailed == 1:
  |     +-- TFTOC = 1 (锁存)
  |     +-- pendingDTC = 1 (当前循环)
  |     +-- 如果上一个循环pendingDTC == 1:
  |           +-- confirmedDTC = 1
  |           +-- WIR = 1
  |
  +-- 如果testFailed == 0 且 监测完成:
        +-- 如果TFTOC == 0:
              +-- pendingDTC = 0 (如果上一个循环也为0)
        +-- TNCTOC = 0

这个逻辑看起来简单,但实际项目中,每个OEM都可能有一些微调。比如有的OEM要求连续3个循环才确认,有的要求2个。我建议你在做项目时,先确认客户的具体要求,不要直接套用规范。

3.5 实战中的常见问题

最后,分享几个我在项目中踩过的坑:

  1. 状态位不同步:有一次我发现confirmedDTC已经置1了,但WIR还是0。查了半天,是代码里把WIR的置位条件写成了pendingDTC,而不是confirmedDTC。低级错误,但排查起来很费时间。
  2. 清除逻辑混乱:有些工程师在清除DTC时,只清了confirmedDTC,忘了清TFSC和TNC。结果下次读DTC时,TFSC还是1,误导了诊断分析。
  3. 操作循环定义不清:不同ECU对「操作循环」的定义可能不同。有的用点火开关,有的用CAN唤醒信号。一定要在系统需求文档里明确写清楚。

好了,关于DTC的8个状态位,今天就讲到这里。下一章咱们聊聊DTC的优先级和老化机制,那个也很有意思。

一句话总结:testFailed看当下,TFTOC看本次循环,pendingDTC等确认,confirmedDTC定生死。其他4个位,都是辅助你诊断的「侦探工具」。