1、诊断栈概述:车载诊断协议(UDS/OBD)简介、诊断栈在AUTOSAR架构中的位置、诊断栈核心功能模块(DCM/DEM/FIM)

1.1 车载诊断协议:UDS与OBD,到底有什么区别?

做车载嵌入式开发,诊断这块是绕不开的。说白了,诊断就是车跟外界(诊断仪、T-Box、云端)之间的“对话协议”。车出了什么毛病,你得有个标准方法去问它、查它。

目前主流的两大协议是OBD和UDS。我刚开始接触时也混淆过,后来踩了坑才彻底搞明白。

  • OBD(On-Board Diagnostics):最早是为了排放法规而生的。它主要关注发动机、排放系统。协议简单,报文ID固定(比如0x7DF是请求,0x7E8是响应)。说白了,OBD是“法规底线”,只查跟排放相关的故障。
  • UDS(Unified Diagnostic Services):这是真正的“全车诊断”。它基于ISO 14229标准,覆盖了从发动机到车窗、从气囊到娱乐系统的所有ECU。UDS的灵活性很高,你可以自定义会话、安全等级、DID数据标识符等。

我个人习惯:做量产项目时,OBD只用来应付年检和法规检查。真正的故障排查、刷写、标定,全走UDS。你想想看,一个OBD请求只能读几个固定的PID,而UDS可以读任意DID、执行任意Routine,这差距不是一星半点。

举个例子,OBD读车速,只能读0x0D这个PID。而UDS读车速,你可以通过0x22服务读0xF190这个DID,还能同时读转速、水温、里程。这就是“够用”和“好用”的区别。

1.2 诊断栈在AUTOSAR架构中的位置

AUTOSAR架构分三层:应用层(ASW)、运行时环境(RTE)、基础软件层(BSW)。诊断栈就位于BSW层,属于系统服务的一部分。

我画了一张图,帮你理清诊断栈在AUTOSAR中的位置:

应用层(ASW) SWC 1 · SWC 2 · SWC 3 · ... · SWC N 运行时环境(RTE) 基础软件层(BSW) 诊断栈(Diagnostic Stack) DCM · DEM · FIM 通信栈(CAN/ETH) 存储栈(NvM) 系统服务(OS/BSW) 微控制器抽象层(MCAL) 诊断栈位置

从图中可以看到,诊断栈位于BSW层,它上接RTE(与应用层SWC交互),下接通信栈(CAN/ETH驱动)。诊断栈不是孤立的,它需要跟NvM(存储故障码)、OS(任务调度)、通信栈(收发诊断报文)紧密配合。

避坑指南:我曾经在一个项目里,把诊断栈的配置跟通信栈的配置分开做,结果DCM收不到诊断请求。查了两天才发现,是CAN IF模块的PDU路由没配好。记住,诊断栈的“根”在通信栈,报文进不来,一切白搭。

1.3 诊断栈核心功能模块:DCM、DEM、FIM

AUTOSAR把诊断栈拆成了三个核心模块。我习惯这么理解:DCM负责“问与答”,DEM负责“记与报”,FIM负责“管与控”

1.3.1 DCM(Diagnostic Communication Manager)—— 诊断通信管家

DCM是诊断栈的“门面”。所有诊断请求(比如读故障码、写数据、执行例程)都先经过DCM。它负责解析UDS报文,然后分发给对应的处理函数。

DCM的核心职责包括:

  • 报文路由:把CAN/LIN/ETH上收到的诊断请求,转成内部API调用。
  • 会话管理:控制诊断会话(默认会话、扩展会话、编程会话)的切换。
  • 安全访问:实现种子-密钥的解锁机制,防止非法操作。
  • 服务分发:把0x10(诊断会话控制)、0x22(读取数据)、0x2E(写入数据)等请求,路由到对应的处理逻辑。

举个实际例子,诊断仪发了一个0x22 0xF190(读车速),DCM收到后:

1. 检查当前会话是否允许读数据(默认会话允许)
2. 检查安全等级是否满足(读数据通常不需要解锁)
3. 调用DID 0xF190对应的读回调函数
4. 把车速值打包成响应报文发回去

我建议:DCM的配置一定要跟OEM的诊断规范对齐。每个DID的读写权限、会话依赖、安全等级,差一个bit都可能被客户拒收。我之前有个同事,把DID的读权限配成了“仅编程会话”,结果产线刷写时读不到版本号,整批车返工,教训深刻。

1.3.2 DEM(Diagnostic Event Manager)—— 诊断事件管家

DEM是诊断栈的“记忆体”。它负责管理故障事件(DTC,Diagnostic Trouble Code)。说白了,车上的传感器、执行器出了什么毛病,DEM负责记录、计数、老化、清除。

DEM的核心机制:

  • 事件监控:应用层SWC通过RTE调用DEM接口,上报“事件发生”或“事件恢复”。
  • DTC状态管理:每个DTC有8个状态位(比如“测试失败”、“已确认”、“当前存在”等),DEM负责维护这些状态。
  • 老化与清除:故障如果长时间不再出现,DEM会逐渐“老化”掉这个DTC。如果用户用诊断仪清码,DEM会清除所有DTC。
  • 快照与扩展数据:故障发生时,DEM会记录当时的工况(车速、水温、里程等),方便后续分析。

你想想看,如果没有DEM,故障码就是“一次性”的——熄火再启动就丢了。有了DEM,故障码可以持久化存储到NvM里,下次上电还能读出来。

注意:DEM的存储策略很讲究。我曾经遇到一个项目,故障码存储太频繁,导致NvM擦写寿命提前耗尽。后来我们加了“去抖”逻辑——同一个DTC在10秒内只存一次。嗯,这里要注意,不是所有故障都需要立即存盘,频繁的瞬态故障会“撑爆”存储空间。

1.3.3 FIM(Function Inhibition Manager)—— 功能抑制管家

FIM是诊断栈的“刹车片”。它的职责很简单:当某个故障发生时,禁止相关功能继续运行

举个例子:

  • 如果发动机水温传感器故障(DEM上报了DTC),FIM可以禁止“高功率输出”这个功能。
  • 如果雷达模块故障,FIM可以禁止“自适应巡航”功能。

FIM的工作流程:

1. DEM上报故障事件(比如:P0118 - 水温传感器电压过高)
2. FIM查表,找到该故障对应的“抑制功能列表”
3. FIM调用BswM(模式管理)或直接通知SWC:禁止功能X、Y、Z
4. 当故障恢复后,FIM解除抑制,功能恢复正常

FIM的配置通常是一张“故障-功能映射表”。我习惯用Excel管理,然后通过工具生成代码。这张表在项目前期就要跟系统工程师对齐,否则后期改起来很痛苦。

个人经验:FIM的抑制策略要“适度”。我曾经见过一个项目,一个轻微的传感器故障,FIM直接禁掉了整车的动力输出。客户试驾时吓出一身冷汗。后来我们改成了“降级模式”——故障时限制功率,但不完全禁止。记住,FIM的目的是“安全降级”,不是“一刀切”。

1.4 三个模块的协作关系

DCM、DEM、FIM不是各自为战的。它们之间的协作,构成了诊断栈的完整闭环:

场景 DCM DEM FIM
诊断仪读故障码 接收0x19请求,调用DEM接口 返回DTC列表及状态 无动作
传感器上报故障 无动作 记录DTC,更新状态,存NvM 查表,抑制相关功能
诊断仪清码 接收0x14请求,调用DEM接口 清除DTC,通知FIM解除抑制 解除功能抑制
故障恢复 无动作 更新DTC状态(当前不存在) 延迟解除抑制(防抖)

说白了,DCM是“外交官”,负责跟诊断仪打交道;DEM是“档案员”,负责记录故障历史;FIM是“保安队长”,负责在出问题时限制危险行为。三个模块缺一不可。

总结一下:诊断栈不是简单的“收报文-回报文”。它背后有一套完整的事件管理、存储、抑制机制。做诊断开发,不能只盯着UDS协议栈,要把DCM、DEM、FIM当成一个整体来设计。我见过太多项目,DCM调通了就以为诊断做完了,结果DEM和FIM的配置一塌糊涂,最后在客户验收时被怼得体无完肤。

好了,这一章我们聊了诊断栈的“骨架”——协议、位置、模块。下一章开始,我会带你深入DCM的细节,看看诊断请求到底是怎么被“消化”掉的。


公众号:蓝海资料掘金营,微信deep3321