1. 应用层如何定义
接下来所解读的应用层协议主要是ISO15031这几个协议,ISO15031有7个协议,如下图所示。
它们分别定义什么内容很清晰,按照我们的学习风格只看对我们项目有用的协议,其它可以暂时不用看。其中红色框第五部分和第六部分是我们必须要研究的。第五部分是ISO15031-5定义排放相关的诊断服务,第六部分是ISO15031-6是定义诊断故障码的。功能性描述的协议主要还是看ISO15031-5协议,如下图所示ISO15031-5目录。
当前我们解读的ISO15765-4协议应用层主要是看目录第七章内容,其中我们的C300开发板第一版软件使用到的协议主要是小红色框圈起来部分内容,分别是Service$01当前动力总成诊断数据,Service$03排放相关故障码,Service$09 车辆信息中的车架号,所以小红色框圈起来的内容C300开发板也没完全使用完,比如车量信息中只使用了车架号这个协议。第一版软件用到什么内容我们先讲解什么内容。其它协议我们会在后续版本软件中继续解读。
Service$01当前动力总成诊断数据(以下简称“当前数据流”),在具体讲解当前数据流的定义前,先了解下什么是Supported PID。
上图所示,前面讲解中我们提到过ISO15765-4协议初始化命令采用SID(服务字节)是0x01,PID(参数识别号)是0x00。这里的PID=0x00是作为Supported PIDs来使用。Supported PIDs顾名思义就是识别支持的数据流参数。Supported PIDs在C300开发板第一版软件中并没有具体实现代码,它被定于第二版本软件中使用。这里提前解读,对大家自行阅读协议有比较大的帮助。对比初始化命令EntCmd15765和数据流命令DSCmd15765的值是完全一样的,其实DSCmd15765命令的PID就是第三个字节0x00,是随着请求具体数据流的不同,程序自动对其赋值,所以它的PID并不是0x00。但是这两个命令使用相同的SID=0x01,请求的是相同的服务,即当前数据流。下面我们看下当前数据流是如何请求和响应的。
请求Supported PIDs,如下图所示。
读当前数据流之前,可以先读Supported PIDs,这是诊断仪最标准做法。表格中列出了请求命令的应用层数据。第一字节 0x01 是当前数据流的SID。第二字节是PID,但是这个PID是用于请求Supported PIDs 。这些PID的值有哪些呢?表中告诉我们可以看Annex A 这个列表。从协议截图出来如下图所示。
Supported PIDs的PID取值范围从0x00到0xE0。这个表格我们暂时只看PID取值,其它内容接下来再继续讲。回到Table125表格,第三字节往后也是Supported PIDs的PID,但是表格中有一列Cvt,标注是M表示不可或缺的,标注U表示用户可选的,从第三字节开始就是用户可选项。U = User Optional — PID may be included to avoid multiple PID supported request messages.
意思就是这些Supported PIDs的PID可以被包含在命令里以避免太多的Supported PIDs的请求信息。根据这个协议的定义可以构建下面两种请求命令。方便起见,我以标准CAN为例写出这些命令。
第一种,以SingleFrame依次请求命令如下
7DF 8 02 01 00 00 00 00 00 00
7DF 8 02 01 20 00 00 00 00 00
7DF 8 02 01 40 00 00 00 00 00
7DF 8 02 01 60 00 00 00 00 00
7DF 8 02 01 80 00 00 00 00 00
7DF 8 02 01 A0 00 00 00 00 00
7DF 8 02 01 C0 00 00 00 00 00
7DF 8 02 01 E0 00 00 00 00 00
第二种,以MultipleFrame传输一次性请求命令如下
7DF 8 10 09 01 00 20 40 60 80
7E0 8 21 A0 C0 E0 00 00 00 00 (如果流控帧标识符是7E8,此帧标识符是7E0)
SingleFrame请求,必须发送一帧SingleFrame请求获得一次响应,总共8帧请求分别8次响应。如果以MultipleFrame请求,就会获得一次性响应。关于响应的数据格式和规则如下图所示。
第一字节是当前数据流的响应SID=0x41,接下来每5个字节对应一个Supported PIDs的PID的响应。当然如果您是以SingleFrame请求获得的响应也是SingleFrame的响应。以MultipleFrame请求就会获得多组5个字节的Supported PIDs的PID的响应。这5个字节的第1字节是Supported PID,后4个字节表示支持的数据流,怎么表示呢?看下图的举例。
表中PID=0x00响应的数据第三字节为0xBF,转换为二进制是10111111,在Annex A表格中定义1表示支持,0表示不支持,而表示的PID值按照从高字节到低字节,从高位到低位表示PID=0x01,0x02,0x03,0x04,0x05,0x06...... 第三字节的10111111分别表示PID=0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08。而支持与否的结果是PID=0x01,0x03,0x04,0x05,0x06,0x07,0x08支持,但是PID=2不支持。第四字节一样是0xBF,这时候PID=0x09,0x0B,0x0C,0x0D,0x0E,0x0F,0x10支持,但是PID=0x0A不支持。以此类推剩下两个字节表示PID=0x11到0x20是否支持的情况。接下来是PID=0x20响应的Supported PIDs的情况。从而可以知道一个Supported PIDs的PID的响应由四个字节表示,每一个比特位表示一个PID是否支持的情况,也就是一个Supported PIDs的PID的响应可以获知32个PID是否支持的情况。上面的表格如果是实际通信的数据是怎么样的呢?我们下面还原下帮助大家整体理解,以标准CAN,汽车由ECU#1响应为例。
7DF 8 03 01 00 20 00 00 00 00 <---这是C300开发板发送的请求
7E8 8 10 00 41 00 BF BF A8 91 <---这是汽车ECU#1响应
7E0 8 30 00 00 00 00 00 00 00 <---这是C300开发板发动的流控帧
7E8 8 21 20 80 00 00 00 00 00 <---这是汽车ECU#1响应
在读取PID支持列表后,就可以按照支持的情况直接读取当前系统支持的数据流了。这里以发动机转速和车速为例告诉大家如何读取这两个数据流数值。首先在Annex B 中找到发动机转速和车速的定义。如下图所示。
它们的PID分别是0x0C和 0x0D,这时候就可以构建它们的请求命令。以标准CAN为例。
发动机转速请求命令: 7DF 8 02 01 0C 00 00 00 00 00
车速请求命令: 7DF 8 02 01 0D 00 00 00 00 00
下面我们从C300开发板和模拟器通信数据看下响应数据是否与上面表格定义一致。
设置模拟器发动机转速为1820.50 RPM,车速为117KM/H.
C300开发板服务器网站显示值如下图所示,与模拟器模拟值一致。
OBD分析仪采集到的通信数据如下图所示。
发动机转速响应数据 7E8 8 07 41 0C 1C 72 00 00 00
数据中应用层数据为 41 0C 1C 72, 41是响应SID,0C是发动机转速PID,转速值就是1C72.
按照上面TableB.13表格定义换算 1/4rmp/bit,且 DataByte值是AB,意思是将两个字节取值除以4即可得到发动机转速。将0x1C72转换成十进制是7282,7282/4=1820.5.
与C300读到的值一致。
车速响应数据 7E8 8 07 41 0D 75 00 00 00 00
数据中应用层数据为41 0D 75, 41是响应SID,0D是车速PID,车速值就是75.按照上面TableB.14表格定义换算1km/h per bit, DataByte值是A,意思就是一个字节取值乘以1,其实就是0x75十进制的值117.