开局一辆豪车,文章精不精彩不重要。
前几天写的那篇关于UDS的基本概念,本来也想一起写一点关于UDS诊断服务的内容,但是感觉内容似乎太多了,自己也没有完全理解,就分开写,趁着周末继续来写一下我当年一脸懵逼的DID、DTC都是怎么回事。
首先还是把上次的基本名词概念拿出来:
SID:ServiceIdentifier诊断服务ID; Subfunction:子服务(SF); PositiveResponse:正响应; NegativeResponse:否响应; NRC:Negative ResponseCode(否定响应码); DID:DataIdentifier数据标识符; DTC:diagnostictrouble code诊断故障码; testFailed:当前故障; confirmedDTC:历史故障;UDS一个最基本规则就是如上图所示的路径,一个请求,然后一个响应,然后响应分为正响应和负响应。
先来说一下UDS请求,请求的格式一般为“SID+一个字节Subfunction+具体的数据”, Subfunction就是对应的这个SID的子服务,对于某些UDS服务,它是没有子服务的,那他的请求格式就是“SID+具体的DID+数据内容”,这里的 DID就是数据标识符的意思,划重点了,DID就是这么来的。
再来讲一下正响应,正响应的首字节回复 [SID+0x40]。
所以对于子服务的正响应就是“SID+0x40+Subfunction+具体的数据”,
对于具体的DID的请求的正响应就是“SID+0x40+DID+具体的数据”。了解了这个基本格式,就大概能看懂诊断报文里面的那些内容了。
具体体现出来就是如下图这样的一个格式了。
最后我们再说一下负响应,负响应就比较特殊了,首先来说一下负响应的基本格式,如果Tester发送的请求报文的格式错误,或者请求发送的条件不符合当前状态,这个时候ECU就会回复负响应,
负响应的格式是: “7F+SID+NRC”。
继续来整个例子(这个也是网上抄来的,我解读一下),第一行和第三行分别是10服务的01子服务和02子服务,对于01子服务,回复的就是正响应,其中00 32 00 C8这四个字节的内容是10服务的回话参数,这个在后面介绍10服务的时候再详细介绍。对于10服务的02子服务,回复的就是负响应,所以格式就是7F+SID+NRC,这个例子中的NRC就是7E,7E代表的意思就是“当前会话下服务不支持”。
说回来负响应,负响应的格式相对较为简单,我个人理解按照汽车的诊断要求, 你要是不支持这个服务,那在回复负响应的时候就得告诉别人我为啥回复负响应,所以NRC就是ECU告诉你我回复负响应的原因。
常用的 NRC如下图所示(我也不知道为啥没有针对10和22的详细说明,回头我再试试看):
11表示服务不支持;
12 subfunction不支持;
13 请求的长度不正确,或者格式不正确;
31 是请求超出范围;
7E 是在当前会话下subfunction不支持;
7F 是在当前会话下服务不支持;
我看了好几篇关于UDS介绍的文章,基本上都是只介绍6种常用的服务,对于其余不常用的服务,介绍内容非常的少。我按照我个人的理解,对那些文章中内容的顺序做一些调整,尽量按照我自己理解的一个步骤来进行介绍。常用的6个UDS服务分别是 10诊断会话控制, 14清除诊断信息, 19读取诊断信息, 22由DID读取数据, 27安全解锁服务, 2E由DID写入数据。
我大概看了一下其他服务,似乎感觉每个服务都曾耳闻或者被用过,但是从我个人的学习和理解,可能按照22/2E、14/19这种顺序来学习的话可能更好理解一点。
1. 用于读/写DID的0x22/0x2E服务22服务是通过ID读取数据,而2E服务是通过ID写入数据。
——22服务——对于22服务,请求格式就是“22+两个字节的DID (DID的长度是2个字节,一般是F1 80,F1 81这种格式)”,它的 正响应是“62+DID+所读取的数据”。
简单举个例子,需要读取DID是F1 86的数据内容,它的正响应是“62+F186+02”,这个02就是F1 86这个DID存储的内容,而这个F1 86代表的意思是“当前会话状态(这个在10服务里面会介绍到)”。02代表当前处于编程会话状态。
DID定义的内容是什么?在ISO14229里面有一些标准推荐的DID以及这些DID的功能,当然还有一些特殊的DID是由主机厂来定义用途的。
22服务也支持NRC,上面也提到了,对于DRC就是告诉Tester为什么我回复的是负响应,在ISO14229里面也提到了22服务所支持的NRC。对于22服务, 负响应回复的就是“7F+22+NRC”。
22服务的NRC的含义分别如下:13是请求格式不正确;14读取的数据已经超过了传输的最大值,就是超限了;31是请求的DID不支持,请求的DID在当前会话下不支持;33要求在解锁状态下,而现在没有处于解锁状态执行了响应的请求。
——2E服务——2E服务,请求格式为“2E+DID+需要写入的数值”,对于2E服务的正响应是“6E+DID”,举个写VIN码的例子,汽车的VIN码是17个字节。
例子里面要写入的VIN码是“01 02 ……10 11”,则2E服务的请求为:
10 14 2E F1 90 01 02 0321 04 05 06 07 08 09 0A22 0B 0C 0D 0E 0F 10 11写入成功后,ECU回复:03 0E F190 AA AA AA AA;
简单解读一下,10 14中的1代表是首帧,而“0 14”代表这个多帧组合共有20个字节。然后是SID:2E占一个字节,DID:F1 90占两个字节,DID的数据内容占17个字节。后两行的21 和22代表连续帧。
同样2E服务也支持NRC,同样支持的NRC也是在ISO14229这个标准里面有体现的,有兴趣的可以自己去看一下原版的相关标准。2E服务支持的NRC如下:
2. 与故障存储相关的0X14/0x19服务——什么是故障码DTC?——在讲0x14和0x19服务之前,首先需要知道什么是故障码,根据之前的名词缩写,故障码就是 Diagnostic Trouble Code—— DTC。
当ECU见到车辆发生某种故障或者错误的时候,会将相应的数值故障码进行存储,这个对应的数值故障码,我们就称为DTC。 与DID类似,DTC也只是一串数字而已,这串数字具体定义的是什么类型的故障,除了ISO的一些标准中推荐的之外,还有一些DTC的定义都是由 主机厂自己内部来制定的。 通过这个DTC就可以反应出来ECU具体什么位置产生了什么样的故障类型。
DTC一般是由3个字节组成,在ISO15031-6里面定义了DTC的格式是由“ 两个字节根基+一个字节的故障类型 ”组成,还是拿一个例子出来,对照例子来讲一下DTC。
举个例子,假设我读到故障码是 C123456(随便杜撰的),那ECU回复的CAN报文应该是 52 34 56,因此显示值是与故障码有一点区别的,而下面这个显示值是C1 23 45,所对应的的DTC应该是U012345。那就来看一下3个字节的DTC是怎么从显示值映射到DTC的。
我们先看一下举例的 C123456这个DTC,其中C代表底盘,1代表有主机厂自己来定义的意思,2代表燃油或者空气部件,后面的34是DTC的编码,而56则是代表故障类型。
对于前2个字节的根基部分,在ISO15031-6中是有详细定义的。第一个字节的前2个bit中,用00/01/10/11分别表示P/C/B/U。
左边第1,2位能反应DTC到底是哪一个系统:
00:P表示Powertrain;
01:C表示底盘;
10:B表示车身;
11:U是网络相关的。
左边第3,4位反应的是DTC到底是由ISO,SAE,这些标准组织所定义的故障,还是由整车厂来定义命名的故障;
因此 DTC报文的前四位bit映射出来的是DTC码的前2位数字,例如U1,P1,B2,C0这种。所以就解释了为什么3个字节的CAN报文对应的是7位的DTC码。
搞清楚了DTC码的含义和解析之后,我们再来讲讲刚刚上面那个例子,在C1 23 45后面有一个08,这个08就是这个DTC的状态信息,其对应的2进制是0000 1000。
重点来了,我们经常所说的当前故障、历史故障就是通过这个状态码定义的,这个字节我们一般也叫它为 DTC状态掩码。
找到一个中文解释的,表格,看这个应该很清楚。当第0位置1时,说明这是一个当前故障,当第3位置1时,说明这是一个历史故障。写到这里,真的是踏踏实实知道了当前故障和历史故障是怎么来的了。
因此整个DTC的信息一共是包含4个字节,除了前三个字节的DTC码之外,第四个字节存储的是DTC的状态值,也是同样的重要。写到这里,我觉得我应该是把DTC是什么以及怎么解析说清楚了。
——19服务——19服务的使用同其他SID类似,具体格式是: 19+SF(子服务)+……。相较于其他服务不同的是在服务后面跟着状态掩码或者其他数据,根据不同的子服务,请求的格式也是有点区别。
19服务一共支持28个子服务(Sub-Function) 。 常用的子服务(帖子上说4种就4种咯 ,我暂时也没用过)有:
19 02由DTC的状态码获取DTC;
请求格式为:03-19-02-状态掩码
正响应的格式为:59 - 02(子功能)- 09(本ECU所支持的掩码条件)- XXXX XX ( DTC,车厂定义) - 01(这个故障码怎么了,01表示当前故障)。
19 04读取DTC的快照数据。在14229里定义的数据叫做快照数据;在Autosar里定义的数据叫做冻结帧,其实他们指的是一类数据。快照数据是指当这个错误发生,或者当这个DTC存储的时候,记录的一些环境数据,比如说车速,水温,发动机转数等这些数据,从而我们读取这些数据之后,能够更好的判断DTC产生的原因以及发生故障原因。
19 06是来获取DTC存储的时候一些扩展数据,这个数据常用的比如说有一些计数器,比如说老化计数器,这样的数据。
19 0A是来读取这个ECU所支持的全部的DTC,ECU支持的哪些DTC是在ECU诊断规范的时候已经定义好的,所以我们通过19 0A读取的DTC是这个ECU应该支持的所有的DTC,即使这个DTC没有产生,也能够被读取的。
请求格式是两个字节“19 + 0A”;
正响应格式“59 + 0A+一个字节的Mask+后面跟ECU支持的所有DTC”。
在 02子服务里面,一共有三种不同类型的DTC status,在上面这个图片里面分别显示为 SM、SAM、States,他们的 解析规则其实都是上面状态码表格中的定义,但是含义却有一点点的不同。
SM:在请求报文里有一个字节的DTCStatus Mask,这个是被Tester用来读取DTC数据的,这个值可以是00到FF之间的任意值,根据所要读取的DTC内容决定。如果你想读取这个ECU产生的所有DTC,你可以用 0xFF.
SAM:在肯定响应中,也有一个字节DTCStatus Availability Mask,这个字节的DTC Status,是ECU诊断规范里定义的。例如上面介绍02子服务的例子,其中的SAM是09,就代表这个ECU支持读取的掩码条件为当前故障和历史故障。
Status:在肯定响应中,读取的DTC后面还有一个字节,是反应的这个DTC,所产生时,对应的状态信息。
——14服务——当诊断故障信息被读取以后,我们解决了这个故障,那后面我们用什么样的方法将这个DTC清除呢?
这里就提到了19服务的孪生兄弟——14服务。用14服务清除诊断信息。
14服务的请求格式是“14 + 3个字节数值”,这3个字节的数值可以是针对单个DTC清除,那这3个字节对应的也就是单个DTC的数值了(前面提到了DTC是3个字节)。也可以是按组来清除DTC,也可以是清除全部DTC。
当3个字节都为FF时,表示将ECU里产生的所有DTC清除。如下图所示就是请求和响应的数据。
当然也可以成组的清除故障码,例如清除Powertrain的所有故障码,或者车身的故障码,相对应的请求就是:
清除Powertrain中P1类型的所有故障:04 141F FF FF AA AA AA;
清除Body中B2类型的所有故障:04 14 AF FF FF AA AA AA;