关于DTC诊断故障码的获取与清除(ISO14229系列之14、19服务)

1、19服务-——读取诊断故障码信息(ReadDTCInformation)

1、01子服务

        通过状态掩码去查找与其相匹配的故障个数
        通过该服务诊断仪能够请求ECU中DTC状态与DTC状态掩码相匹配的故障码个数。如果某一个故障码的实际状态位为1,并且DTC状态掩码中的相应位也为1,那么就认为该故障码的状态与DTC状态掩码相匹配(即:如果DTC状态掩码字节与DTC实际状态字节进行逻辑“位与”运算后的结果为非零值,那么两者就相匹配);此时则将故障数+1。如果诊断仪定义了一个状态掩码,其中包含ECU不支持的位,那么ECU仅使用本身支持的位进行处理故障信息请求格式如下
在这里插入图片描述
        收到请求后,ECU的响应报文格式如下:
在这里插入图片描述

        关于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状态位,其位定义如下:

在这里插入图片描述
        

2、02子服务

        按照定义的状态掩码的形式去查找匹配的故障,将匹配的DTC标识符(3个字节)、DTC状态(1个字节)信息返回。上一小节的01子服务只统计与状态掩码相匹配的DTC个数,02子服务则会将这些匹配的DTC信息返回。请求格式如下:
在这里插入图片描述
        收到请求后,ECU的响应报文格式如下:
在这里插入图片描述
        关于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)的快照信息,通过查找故障发生时刻的这些数据,来分析故障原因。请求格式如下:
在这里插入图片描述

        其中,DTCSnapshotRecordNumber表示DTC快照记录码,占一个字节,表示特定的 DTC快照数据记录编号。例如当我们需要记录某个DTC第一次发生(假设用1表示)和最近一次发生的快照数据时(假设用2表示);那么当DTCSnapshotRecordNumber为1时,则表示请求该DTC第一次发生时的快照信息
        如果ECU支持多个DTC快照数据记录,那么该纪录码应使用0x01~0xFE范围内的数值。当该参数值为FF hex时,要求ECU一次性报告所有存储的DTC快照数据记录。

        收到请求后,ECU的响应报文格式如下:
在这里插入图片描述

        如上,响应报文中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)的扩展信息请求格式如下:
在这里插入图片描述

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

        收到请求后,ECU的响应报文格式如下:
在这里插入图片描述

        以返回第一个扩展数据记录为例,关于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信息。请求格式如下:
在这里插入图片描述

        收到请求后,ECU的响应报文格式如下:
在这里插入图片描述

        关于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服务用于清除存储的故障诊断信息,该服务内容很简单。其请求格式如下:
在这里插入图片描述

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

        收到请求后,ECU的响应报文格式如下:
在这里插入图片描述
        

总结

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

Sub-functionDescription
01reportNumberOfDTCByStatusMask/通过状态掩码报告DTC数量
02reportDTCByStatusMask/通过状态掩码报告DTC信息
04reportDTCSnapshotRecordByDTCNumber/获取指定DTC的快照记录
06reportDTCExtendedDataRecordByDTCNumber/获取指定DTC的扩展数据记录
0AreportSupportedDTC/获取ECU支持的所有DTC
  • 95
    点赞
  • 722
    收藏
    觉得还不错? 一键收藏
  • 44
    评论
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值