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中的位置:
从图中可以看到,诊断栈位于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