关于DTC诊断故障码的获取与清除

汽车安全 3年前 (2021) admin
1,671 0 0
1、19服务——读取诊断故障码信息(ReadDTCInformation)
1、01子服务
通过状态掩码去查找与其相匹配的故障个数。
通过该服务诊断仪能够请求ECU中DTC状态与DTC状态掩码相匹配的故障码个数。如果某一个故障码的实际状态位为1,并且DTC状态掩码中的相应位也为1,那么就认为该故障码的状态与DTC状态掩码相匹配(即:如果DTC状态掩码字节与DTC实际状态字节进行逻辑“位与”运算后的结果为非零值,那么两者就相匹配);此时则将故障数+1。如果诊断仪定义了一个状态掩码,其中包含ECU不支持的位,那么ECU仅使用本身支持的位进行处理故障信息。请求格式如下:
关于DTC诊断故障码的获取与清除
收到请求后,ECU的响应报文格式如下:
关于DTC诊断故障码的获取与清除
关于19 01服务代码部分示例如下(帮助理解,仅供参考):
uint16 DTC_GetDtcCountByStatusMask(uint8 status_mask)               /*按照状态掩码统计ECU中与之匹配的DTC数*/    {    uint16 Dtc_count = 0;    uint8 Record_count;
for(Record_count = 0; Record_count < DTC_CODE_MAX_NUM; Record_count++)/*检索所有的DTC*/ { if((Dtc_dtc_status_record[Record_count].dtc_status.status_byte & status_mask) != 0) { Dtc_count++; } } return Dtc_count;}
FUNC(void,DCM_CODE) App_Fault_Memory_Read_Number(P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_APPL_DATA) pMsgContext){ uint16 Counter = 0U; uint8 DtcStatus_Temp; DtcStatus_Temp = pMsgContext->reqData[DCM_INDEX_2]; /*通过19 01服务第3个字节发送状态掩码;*/ Counter = DTC_GetDtcCountByStatusMask(DtcStatus_Temp); /*按照状态掩码统计ECU中与之匹配的DTC数(代码如上)*/ pMsgContext->resData[DCM_INDEX_2] = DTCStatusAvailabilityMask; /*返回ECU支持的状态位*/ /* Change below data if necessary */ /* 0x00 ISO15031-6Format,0x01 ISO14229-1Format,0x02 J1939 Format */ pMsgContext->resData[DCM_INDEX_3] = 0x00U; /*返回ECU使用的DTC格式标识符, 00:15031-6;01:14229-1;02:J1939*/ pMsgContext->resData[DCM_INDEX_4] = (uint8)(Counter >> 8U); /*返回按照状态掩码统计出来的DTC数*/ pMsgContext->resData[DCM_INDEX_5] = (uint8)(Counter); /* Always equals 6, don't change it */ pMsgContext->resDataLen = 6U; DsdInternal_ProcessingDone(pMsgContext); }

Ps:DTC状态掩码参数包含8个DTC状态位,其位定义如下:

关于DTC诊断故障码的获取与清除

2、02子服务

按照定义的状态掩码的形式去查找匹配的故障,将匹配的DTC标识符(3个字节)、DTC状态(1个字节)信息返回。上一小节的01子服务只统计与状态掩码相匹配的DTC个数,02子服务则会将这些匹配的DTC信息返回。请求格式如下:

关于DTC诊断故障码的获取与清除

收到请求后,ECU的响应报文格式如下:

关于DTC诊断故障码的获取与清除

关于19 02服务代码部分示例如下(帮助理解,仅供参考):

uint16 DTC_GetDtcByStatusMask(uint8 *p_dtc, uint8 status_mask)  /*按照状态掩码统计ECU中与之匹配的DTC,返回该DTC信息*/{    uint16 dtc_count = 0;    uint8 record_count;
for(record_count = 0; record_count < DTC_CODE_MAX_NUM; record_count++) { if((Dtc_dtc_status_record[record_count].dtc_status.status_byte & status_mask) != 0) { *p_dtc++ = Dtc_dtc_code_data[record_count].dtc_high_byte; *p_dtc++ = Dtc_dtc_code_data[record_count].dtc_middle_byte; *p_dtc++ = Dtc_dtc_code_data[record_count].dtc_low_byte; *p_dtc++ = Dtc_dtc_status_record[record_count].dtc_status.status_byte; dtc_count++; } } return dtc_count;}
FUNC(void,DCM_CODE) App_Fault_Memory_Read_identified_errors(P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_APPL_DATA) pMsgContext){ uint16 counter = 0U; uint8 DtcStatus_Temp; DtcStatus_Temp = pMsgContext->reqData[DCM_INDEX_2]; /*通过19 02服务第3个字节发送状态掩码;*/
/*按照状态掩码统计ECU中与之匹配的DTC,返回其DTC信息(代码如上)*/ counter = DTC_GetDtcByStatusMask(&(pMsgContext->resData[DCM_INDEX_3]),DtcStatus_Temp); pMsgContext->resData[DCM_INDEX_2] = DTCStatusAvailabilityMask; /*返回ECU支持的状态位*/ pMsgContext->resDataLen = DCM_INDEX_3 + (counter * 4U); /*更新响应报文的长度;*/ DsdInternal_ProcessingDone(pMsgContext);}

3、04子服务

为了方便找到故障的原因,车厂一般会在诊断调查表中定义一些信息作为快照信息,例如故障的发生时间、电压、行驶里程数、车速等。在对应故障发生时,ECU端要记录发生故障时的快照信息;而04服务就是用于请求指定故障码(DTC)的快照信息,通过查找故障发生时刻的这些数据,来分析故障原因。请求格式如下:

关于DTC诊断故障码的获取与清除

其中,DTCSnapshotRecordNumber表示DTC快照记录码,占一个字节,表示特定的 DTC快照数据记录编号。例如当我们需要记录某个DTC第一次发生(假设用1表示)和最近一次发生的快照数据时(假设用2表示);那么当DTCSnapshotRecordNumber为1时,则表示请求该DTC第一次发生时的快照信息。

如果ECU支持多个DTC快照数据记录,那么该纪录码应使用0x01~0xFE范围内的数值。当该参数值为FF hex时,要求ECU一次性报告所有存储的DTC快照数据记录。

收到请求后,ECU的响应报文格式如下:

关于DTC诊断故障码的获取与清除

如上,响应报文中DTCSnapshotRecordNumber表示返回的是该DTC的哪一个快照记录;DTCSnapshotRecordNumberOfIdentifiers表示快照信息中定义的成员量;如定义的快照数据有车速、电压、转速、里程这四项信息;则该值为4。

如下,假设有两个快照记录信息,快照记录的成员数有4个;则对应的19 04服务的诊断代码设计如下(帮助理解,仅供参考):

FUNC(void,DCM_CODE) App_Fault_Memory_Read_snapshot(P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_APPL_DATA) pMsgContext){    uint8 error = 0U;    uint32 Dtc;    uint32 i;    uint8 DTCSnapshotRecordNumber;    uint8 DTCSnapshotRecordLength = 0U;    uint8 status = 0U;    uint8 snap_data_len = 0U;
DTCSnapshotRecordNumber = pMsgContext->reqData[DCM_INDEX_5];
Dtc = Make32Bit(pMsgContext->reqData[DCM_INDEX_2], pMsgContext->reqData[DCM_INDEX_3], pMsgContext->reqData[DCM_INDEX_4]); /* Check DTC */ error = DTC_GetStatusByDtcNumber(Dtc, &status); /*获取DTC的状态位,存放到status*/ if(error == 0U) { pMsgContext->resData[DCM_INDEX_5] = status; /*返回该DTC的状态位*/ if(Dtc_Fault_IsConfirmed(status)) { switch(DTCSnapshotRecordNumber) { /* Add your code here. Below codes should be changed as Spec */ case 0x01: /*返回对应编号的快照记录信息*/ case 0x02: { pMsgContext->resData[DCM_INDEX_6] = DTCSnapshotRecordNumber; /* 快照记录码数*/ pMsgContext->resData[DCM_INDEX_7] = 4U; /* 定义的快照成员数*/ /*获取快照成员的ID信息、数值信息;从pMsgContext->resData[DCM_INDEX_8]这个地址开始存储*/ DTC_GetDtcSnapData(DTCSnapshotRecordNumber, &pMsgContext->resData[DCM_INDEX_8], Dtc, &snap_data_len); DTCSnapshotRecordLength = DCM_INDEX_8 + snap_data_len;/*更新响应报文的长度*/ break; }
case 0xFF: /*返回所有快照记录信息*/ { pMsgContext->resData[DCM_INDEX_6] = 0x01; /* 第一个快照记录*/ pMsgContext->resData[DCM_INDEX_7] = 4U; /* 定义的快照成员数*/ DTCSnapshotRecordLength = DCM_INDEX_8; /*获取第一个快照成员的ID信息、数值信息;*/ DTC_GetDtcSnapData(0x01, &pMsgContext->resData[DTCSnapshotRecordLength], Dtc, &snap_data_len); DTCSnapshotRecordLength += snap_data_len; pMsgContext->resData[DTCSnapshotRecordLength++] = 0x02; /* 第二个快照记录*/ pMsgContext->resData[DTCSnapshotRecordLength++] = 4U; /*获取第二个快照成员的ID信息、数值信息;*/ DTC_GetDtcSnapData(0x02, &pMsgContext->resData[DTCSnapshotRecordLength], Dtc, &snap_data_len); DTCSnapshotRecordLength += snap_data_len;/*更新响应报文的长度*/ break; } default: { DsdInternal_SetNegResponse(pMsgContext,DCM_E_REQUESTOUTOFRANGE); error = 1U; break; } } } else { DTCSnapshotRecordLength = 6u; } } else { DsdInternal_SetNegResponse(pMsgContext,DCM_E_REQUESTOUTOFRANGE); } if(error == 0U) { pMsgContext->resDataLen = DTCSnapshotRecordLength; DsdInternal_ProcessingDone(pMsgContext); } else { DsdInternal_ProcessingDone(pMsgContext); }}

4、06子服务

除了前面04服务中介绍到的快照信息;一般还会再定义一个扩展信息,用于记录故障的一些其他信息,比如故障发生的次数、老化次数、已老化次数等。而将下来介绍的06服务就是用于请求指定故障码(DTC)的扩展信息。请求格式如下:

关于DTC诊断故障码的获取与清除

其中,DTCExtendedDataRecordNumber表示扩展数据记录码,占一个字节,表示诊断仪请求的指定故障码扩展数据记录的编号。(即要请求的故障码中指定的第几个的扩展数据)

收到请求后,ECU的响应报文格式如下:

关于DTC诊断故障码的获取与清除

以返回第一个扩展数据记录为例,关于19 06服务代码部分示例如下(帮助理解,仅供参考):

FUNC(void,DCM_CODE) App_Fault_Memory_Read_DTC_Extended_Data_Records_By_DTC_Number(P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_APPL_DATA) pMsgContext){    uint8 error = 0U;    uint32 Dtc;    uint8 status = 0;    uint8 extern_data_len = 0;        /* change below length according to App*/    if(pMsgContext->reqData[DCM_INDEX_5] >= 1U)     {        Dtc = Make32Bit(pMsgContext->reqData[DCM_INDEX_2], pMsgContext->reqData[DCM_INDEX_3], pMsgContext->reqData[DCM_INDEX_4]);        /* Check DTC */        error = DTC_GetStatusByDtcNumber(Dtc, &status);/*获取DTC的状态位,存放到status*/
if(error == 0U) { pMsgContext->resData[DCM_INDEX_5] = status;/*返回该DTC的状态位*/
} else { DsdInternal_SetNegResponse(pMsgContext,DCM_E_REQUESTOUTOFRANGE); } } else { error = 1U; DsdInternal_SetNegResponse(pMsgContext,DCM_E_REQUESTOUTOFRANGE); }
if(error == 0U) { pMsgContext->resData[DCM_INDEX_6] = 0x01; /* 扩展数据记录码,DTCExtendedDataRecordNumber */ DTC_GetDtcExternData(&(pMsgContext->resData[DCM_INDEX_7]), Dtc, &extern_data_len);/*该函数里去获取扩展数据信息,自己定义*/ pMsgContext->resDataLen = DCM_INDEX_7 + extern_data_len; /* 更新返回报文的长度*/ DsdInternal_ProcessingDone(pMsgContext); } else { DsdInternal_ProcessingDone(pMsgContext);     }}


5、0A子服务

该服务用于请求所有支持的DTC信息(3字节的DTC标识符+1字节的DTC状态位),其响应报文与02服务一致;但要区分,该服务返回的是所有DTC的信息;而02服务是返回与请求时状态掩码相与不为0 的DTC信息。请求格式如下:

关于DTC诊断故障码的获取与清除

收到请求后,ECU的响应报文格式如下:

关于DTC诊断故障码的获取与清除

关于19 0A服务代码部分示例如下(帮助理解,仅供参考):

void DTC_GetSupportedDtc(uint8 *p_dtc, uint16 *pCount)      /*返回所有支持的DTC信息*/{    uint8 record_count;    uint8 *pDtc = NULL;        if((p_dtc == NULL) || (pCount == NULL))    {        return;    }
pDtc = p_dtc; *pCount = 0; for(record_count = 0; record_count < DTC_CODE_MAX_NUM; record_count++) { *pDtc++ = DTC_dtc_code_data[record_count].dtc_high_byte; *pDtc++ = DTC_dtc_code_data[record_count].dtc_middle_byte; *pDtc++ = DTC_dtc_code_data[record_count].dtc_low_byte; *pDtc++ = DTC_dtc_status_record[record_count].dtc_status.status_byte; (*pCount)++; }}
FUNC(void,DCM_CODE) App_Fault_Memory_Read_supported_errors(P2VAR(Dcm_MsgContextType,AUTOMATIC,DCM_APPL_DATA) pMsgContext){ uint16 count = 0;
pMsgContext->resData[DCM_INDEX_2] = DTCStatusAvailabilityMask; /*返回ECU支持的状态位*/ DTC_GetSupportedDtc(&pMsgContext->resData[DCM_INDEX_3], &count);/*返回所有支持的DTC信息*/ pMsgContext->resDataLen = 3U + count * 4U; /*更新响应报文的长度*/ DsdInternal_ProcessingDone(pMsgContext);}

2、14服务-——清除故障信息 (ClearDiagnosticInformation)

14服务用于清除存储的故障诊断信息,该服务内容很简单。其请求格式如下:

关于DTC诊断故障码的获取与清除

groupOfDTC表示要清除的某一个类别的诊断故障码(例如动力P、车身B以及底盘C等类别),或者是要清除的某一个特定的故障码;由3个字节组成。

收到请求后,ECU的响应报文格式如下:

关于DTC诊断故障码的获取与清除

总结

19服务用于故障码信息的读取;14服务则用于对故障码信息的清除。14服务的操作简单,但关于19服务,包含了比较多的子服务功能,其中,比较常用的子服务如下:

关于DTC诊断故障码的获取与清除


————————————————

阅读原文,关注作者博客
版权声明:本文为CSDN博主「第55号小白鸭」的原创文章,遵循CC 4.0 BY-SA版权协议,本文已获作者转载权限。

推荐阅读

沃尔沃:敏捷开发中满足ISO26262的软件安全分析

近万字的NvM学习笔记

特斯拉最新的12V蓄电池有什么不同?

特斯拉最新中央计算模块(CCM)解析

关于对自动驾驶传感器的理解

特斯拉的电池管理系统 (BMS) 相比其他电动车有哪些优势?

2021款特斯拉Model Y ECU接口梳理

详解CANoe之CAPL编程

关于CAN时间同步的理解

dbc文件的格式以及创建详解

大众ID.4 X网络架构详解

学习笔记——NVM数据处理机制

学习笔记——AUTOSAR NVM基础知识

基于UDS的Bootloder详解

关于整车上下电流程的理解

一文详解CAN总线错误帧|附下载

DoIP协议介绍,资料分享!

详解车载网络 OTA系统的开发|文末附下载

一文了解汽车嵌入式AUTOSAR架构|附下载

特斯拉Autopilot系统安全研究|附dbc下载

分享不易,恳请点个【在看】

原文始发于微信公众号(汽车ECU开发):关于DTC诊断故障码的获取与清除

版权声明:admin 发表于 2021年11月23日 上午12:19。
转载请注明:关于DTC诊断故障码的获取与清除 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...