文章目录
前言
19服务
04子服务
19 04协议
快照存储设计
快照发送设计
功能验证
分析和应用
总结
前言
近期在一个嵌入式软件开发项目中,要按照UDS标准开发相关功能,期间在翻阅UDS标准时,周围同事都说很多地方晦涩难懂。所以利用晚上和周末时间,把这些内容标注了一下,用大白话把他们解释出来。后面会用若干篇文章把它总结分享出来,一方面备着将来翻看,另一方面也希望能够帮到这一领域的粉丝朋友们。
19服务
在UDS中,诊断仪被认为是客户端,ECU被认为是服务端,所以ECU中的一项UDS功能就被叫做一项服务,19服务是UDS中读取DTC故障相关信息的一类子服务的总称。官方文档中的描述示例如下:
19服务中包含了很多子服务,最常用的其实就只有两个,19 02子服务是读取故障码的,19 04子服务是读取故障码的快照的。本文主要解析19 04这个子服务。
04子服务
快照(Snapshot),从字面上理解意思就是,快门触发的瞬间,记录下来这一时刻的各种信息。放在UDS中来讲就是,发生某一故障(DTC)时,记录并存储这一时刻的ECU信息,比如铅酸供电电压、工作温度、车辆档位、车速、里程、日历时间等等。19 04服务的作用就是支持诊断仪把这一快照信息,按照协议从ECU中读取出来。官方文档中的描述示例如下:
对于我们开发19 04服务而言,就是在ECU中开发这一功能,实现存快照和发送快照的功能。
19 04协议
首先,诊断仪向ECU发送19 04请求指令,格式如下:
其中DTCMaskRecord[]是某个故障的故障码。DTCSnapshotGroupNumber是快照内容的分组号,就像快门中照片九宫格一样,每个部分都有一个编号。01代表第一个分组,02代表第二个分组,依次类推。如果想读取全部的快照内容,把DTCSnapshotGroupNumber设置为FF即可。
然后,ECU向诊断仪发送快照内容,格式如下:
DTCSnapshotRecordNumber这个字节表示快照记录的组号;
DTCSnapshotRecordNumberOfldentifiers这个字节表示后面紧跟的DID的个数,这里如果出现了0x00表示一个未定义的未知个数或者异常个数,比如大于255溢出的数字;
dataldentifier这两个字节表示后面数据的DID;
snapshotData表示快照DID对应的具体数据。
快照存储设计
直接上一段代码,在代码中注释,更加一目了然,示例如下:
main(void)
{
//省略若干行代码
if(Timer100ms == 1){
for(i=0;i++;i<16)//遍历16个故障的状态
{
if((FaultArrayNow[i] == 1)&&(FaultArrayBefore[i] == 0))//如果有新发生的故障
{
FaultMask = setBit(i,1);
}
}
if(FaultMask > 0){
//按顺序存数据,每个Signal都要存在对应的Address上,因为还涉及到分组以及后面的读取解析
SnapData[0] = getByte(FaultMask,0);
SnapData[1] = getByte(FaultMask,1);
SnapData[2] = Signal_01;
SnapData[3] = Signal_02;
SnapData[4] = Signal_03;
//...
SnapAddress += 1024;//与前一个快照的存储作地址偏移
FlashErase(SnapAddress);
FlashWreit(SnapAddress, SnapLength, &SnapData[0]);
}
}
//省略若干行代码
}
注:上述代码是精简后的示意代码,非正式代码。
快照发送设计
直接上一段代码,在代码中注释,更加一目了然,示例如下:
main(void)
{
//省略若干行代码
if(Timer100ms == 1){
if(SnapReadRequest == 1){
switch DTC_Request
case DTC0
DTC_Order = 0;
break;
case DTC1
DTC_Order = 1;
break;
case DTC2
DTC_Order = 2;
break;
case DTC3
DTC_Order = 3;
break;
case DTC4
DTC_Order = 4;
break;
case DTC5
DTC_Order = 5;
break;
case DTC6
DTC_Order = 6;
break;
case DTC7
DTC_Order = 7;
break;
case DTC8
DTC_Order = 8;
break;
case DTC9
DTC_Order = 9;
break;
case DTC10
DTC_Order = 10;
break;
case DTC11
DTC_Order = 11;
break;
case DTC12
DTC_Order = 12;
break;
case DTC13
DTC_Order = 13;
break;
case DTC14
DTC_Order = 14;
break;
case DTC15
DTC_Order = 15;
break;
for(i=128;i--;i>0)//遍历全部的快照存储模块
{
FlashRead(SnapAddress, SnapLength, &SnapData[0]);
if((SnapData[DTC_Order] == 1) || SnapData[getByte-7] == 1))//匹配故障掩码
{
//匹配快照的数据分组
if(Group_Request == 1){
OutputResponse(59,4,DTC_Request,DTC_Staus,1,SignalNum,SignalID1,SnapData[3],SignalID2,SnapData[4],...SignalID497,SnapData[499]);
}else if(Group_Request == 2){
OutputResponse(59,4,DTC_Request,DTC_Staus,2,SignalNum,SignalID1,SnapData[500],SignalID2,SnapData[501],...SignalID998,SnapData[1000]);
}else {
OutputResponse(59,4,DTC_Request,DTC_Staus,0xFF,SignalNum,SignalID1,SnapData[3],SignalID2,SnapData[4],...SignalID998,SnapData[1000]);
}
break;
}
SnapAddress--;
}
}
}
//省略若干行代码
}
注:上述代码是精简后的示意代码,非正式代码。
功能验证
如下是诊断仪向车身控制器请求快照的通信数据,示例如下:
分析和应用
UDS诊断在嵌入式软件中的作用非常强大,特别是汽车领域的ECU软件,大部分都要求必须支持UDS功能,只是对整个UDS中的那么多服务有所裁剪。例如本文提到的0x19服务,官方本来是有24种子服务的,但是大部分车厂只要求ECU开发0x01、0x02、0x4、0x06、0x0A这五个即可,有的ECU甚至只要求开发0x02、0x4这两个。本文着重讲解的0x19 04服务,能够在ECU出现故障时,使工程师使用通用的诊断仪就能获取到更多的故障现场信息,这对分析问题是有很大帮助的。可以更方便地追溯分析问题原因,大大提高工程师的工作效率。
在嵌入式软件中开发0x19 04服务,主要适用于成熟的或者量产化的软件项目,因为它的前提是需要先搭建UDS的网络传输层、会话层、服务层和应用层这一整套的基础框架,需要投入相当大的工作量,这显然不适用于小批量或者功能性的嵌入式软件项目。
总结
以上就是本人在开发UDS 0x19 04服务时,一些个人理解和分析的总结,首先介绍了它的基本概念,然后展示它的设计示例和验证过程,最后分析了该服务的特点和适用场景。
后续还会分享另外几个最近总结的UDS知识点,欢迎评论区留言、点赞、收藏和关注,这些鼓励和支持都将成文本人持续分享的动力。
另外,上述例程使用的Demo工程,可以到笔者的主页查找和下载。
版权声明,原创文章,转载和引用请注明出处和链接,侵权必究!