2. 诊断响应接收与解析
任务目标
编写CAPL程序,通过CANoe的Diagnostic Layer接收ECU返回的诊断响应报文,并从中解析出关键数据——以读取DTC状态为例,提取状态字节并判断当前是否存在故障。
实现原理
诊断请求通过DiagSendRequest发送,响应由事件函数DiagResponse接收。响应数据以参数形式存储,通过DiagGetComplexParameter按字节偏移提取原始数据,再按UDS协议解析DTC状态字节(如0x19 02服务返回的DTC状态掩码)。
关键完整代码
/* 诊断响应接收与解析 - DTC状态提取 */
includes
{
}
variables
{
diagRequest reqReadDTC;
diagResponse respDTC;
byte dtcStatusMask;
char msgStr[100];
}
on start
{
// 创建读取DTC信息的请求 (UDS 0x19 0x02)
reqReadDTC = DiagCreateRequest("ReadDTCInformation");
DiagSetParameter(reqReadDTC, "subFunction", 0x02); // 通过状态掩码读取
DiagSendRequest(reqReadDTC);
}
// 诊断响应事件处理
on diagResponse respDTC
{
byte statusByte;
word dtcHighByte, dtcLowByte;
dword dtcCode;
int i;
int numDTCs;
char dtcStr[20];
// 检查是否为期望的响应
if (DiagGetObjectID(respDTC) != DiagGetObjectID(reqReadDTC))
return;
// 检查响应是否包含肯定响应
if (DiagGetResponseCode(respDTC) == 0x00) // 0x00表示肯定响应
{
// 获取DTC数量(从响应参数中读取)
numDTCs = DiagGetComplexParameter(respDTC, "DTCStatusAvailabilityMask", 0);
write("DTC状态可用性掩码: 0x%02X", numDTCs);
// 遍历所有DTC(最多解析前5个,避免过度处理)
for (i = 0; i < 5; i++)
{
// 尝试读取第i个DTC的高字节
if (DiagGetComplexParameter(respDTC, "DTCAndStatusRecord", i, "DTC", 0) == 0)
break; // 没有更多DTC
// 提取DTC码(3字节)
dtcHighByte = DiagGetComplexParameter(respDTC, "DTCAndStatusRecord", i, "DTC", 0);
dtcLowByte = DiagGetComplexParameter(respDTC, "DTCAndStatusRecord", i, "DTC", 1);
dtcCode = (dtcHighByte << 16) | (dtcLowByte << 8) |
DiagGetComplexParameter(respDTC, "DTCAndStatusRecord", i, "DTC", 2);
// 提取状态字节
statusByte = DiagGetComplexParameter(respDTC, "DTCAndStatusRecord", i, "statusOfDTC");
// 格式化DTC码(如 P0100 -> 0x0100)
snprintf(dtcStr, elcount(dtcStr), "0x%06X", dtcCode);
write("DTC[%d]: %s, 状态=0x%02X", i, dtcStr, statusByte);
// 判断故障状态(bit0 = testFailed)
if (statusByte & 0x01)
write(" -> 当前存在故障");
else
write(" -> 当前无故障");
}
}
else
{
write("诊断响应错误,响应码: 0x%02X", DiagGetResponseCode(respDTC));
}
}
on diagError
{
write("诊断通信错误");
}
运行与验证
环境要求:CANoe 11.0及以上版本,需配置诊断功能(Diagnostic/ISO TP),并加载ECU仿真或真实节点。
- 在CANoe中创建CAPL测试节点,将上述代码粘贴到节点的CAPL Browser中。
- 在Diagnostic/ISO TP配置中,确保已定义名为
ReadDTCInformation的诊断请求对象,且其响应PDU包含DTCAndStatusRecord结构(含DTC三字节和statusOfDTC字段)。 - 编译并运行仿真。触发
on start自动发送读取DTC请求。 - 在Write窗口观察输出。
通过条件:若ECU返回肯定响应,Write窗口应打印DTC状态可用性掩码及每个DTC的编号、状态字节,并正确显示“当前存在故障”或“当前无故障”。若ECU无DTC,则循环正常退出,不报错。
关键点说明
DiagGetComplexParameter的索引参数从0开始,需根据实际诊断数据库(CDD/ODX)中的参数路径调整。- DTC状态字节bit0(testFailed)为1表示当前故障激活,实际项目中可按需解析其他bit位。
- 若响应中DTC数量超过5个,可修改循环上限或使用
DiagGetComplexParameter返回值动态判断。