CAPL针对ECU的诊断,提供了一些基本的函数:
下面结合TestModule 和 诊断的函数,完成ECU的自动化测试
示例1:通过诊断的10服务,进行会话的切换测试
MainTest(){
// 设置后续所有诊断通信所关联的ECU
diagSetTarget("DoorFL"); //DoorFL 从右侧复制
demo1();
}
/*
为什么不使用message直接发送?
因为采用msg,需要自己配置很多的参数信息,需要ID,而diagnostic则有现成的;
理论上,所有发送到can总线的报文,其实都可以使用msg,只不过这里diagnostic更方便
*/
/*
进入扩展会话
*/
void demo1(){
// 创建了一个进入扩展会话的“诊断请求变量”
diagRequest DoorFL.ExtendedDiagnosticSession_Start reqExtendedSession;
// 创建一个变量代表诊断响应返回的响应码
long respCode;
//发送请求
diagSendRequest(reqExtendedSession);
//等待请求发送完毕
if(testWaitForDiagRequestSent(reqExtendedSession, 1000) == 1)
{
write("进入扩展会话的请求发送完毕");
}
else
{
write("进入扩展会话的请求发送失败");
return;
}
//等待接收到诊断的响应
if(testWaitForDiagResponse(reqExtendedSession,1000) == 1){
write("进入扩展会话的响应已经收到");
}
else
{
write("进入扩展会话的响应未收到");
return;
}
respCode = diagGetLastResponseCode(reqExtendedSession);
if(respCode == -1) // 肯定响应
{
write("进入扩展会话的响应为肯定响应");
}
else if(respCode == 0) // 未收到响应
{
write("进入扩展会话的响应还没收到");
}
else
{
write("进入会展会话的响应为否定响应,NRC为:0x%02X", respCode);
}
//把信息写入报告中;
testReportWriteDiagResponse(reqExtendedSession);
}
/*
进入编程会话,和上面的一模一样
*/
void Demo2()
{
// 创建了一个进入编程会话的“诊断请求变量”
diagRequest DoorFL.ProgrammingSession_Start reqProgSession;
// 创建一个变量代表诊断响应返回的响应码
long respCode;
// 发送诊断请求
diagSendRequest(reqProgSession);
// 等待请求发送完毕
if(testWaitForDiagRequestSent(reqProgSession, 1000) == 1)
{
write("进入编程会话的请求发送完毕");
}
else
{
write("进入编程会话的请求发送失败");
return;
}
// 等待收到诊断响应
if(testWaitForDiagResponse(reqProgSession, 1000) == 1)
{
write("进入编程会话的响应已经收到");
}
else
{
write("进入编程会话的响应未收到");
return;
}
// 获取诊断响应的响应码
respCode = diagGetLastResponseCode(reqProgSession);
if(respCode == -1) // 肯定响应
{
write("进入编程会话的响应为肯定响应");
}
else if(respCode == 0) // 未收到响应
{
write("进入编程会话的响应还没收到");
}
else
{
write("进入编程会话的响应为否定响应,NRC为:0x%02X", respCode);
}
}
示例2:车窗位置百分比的写入
/*
写入车窗升降位置的百分比
*/
void Demo3_WriteWindowLift(){
diagRequest DoorFL.DID_WindowLiftRoughPosition_Write reqWindowLiftWrite;
/*
DiagSetPrimitiveByte —— 向诊断请求,设置一个原始字节,一般不会这么干
*/
// DiagSetPrimitiveByte(reqWindowLiftWrite, 0, 0x2E); // 将请求报文中第0个字节设置为0x2E
// DiagSetPrimitiveByte(reqWindowLiftWrite, 1, 0x02); // 将请求报文中第1个字节设置为0x02
// DiagSetPrimitiveByte(reqWindowLiftWrite, 2, 0x01); // 将请求报文中第2个字节设置为0x01
// DiagSetPrimitiveByte(reqWindowLiftWrite, 3, 0x06); // 将请求报文中第3个字节设置为0x06
/*
DiagSetParameterRaw —— 设置诊断请求中指定的参数的原始字节数组
*/
byte position[1] = {0x07};
//最后面这个1,是position的大小
diagSetParameterRaw(reqWindowLiftWrite,"WindowLiftRoughPosition",position,1);
//发送
diagSendRequest(reqWindowLiftWrite);
}
示例3:进入扩展会话状态,并读取响应的参数:当前的会话类型、P2时间、P2Ex时间
void Demo4_ExtendexSession()
{
diagRequest ExtendedDiagnosticSession_Start reqExtendedSession; // 创建一个诊断请求变量
long respCode; // 创建一个响应码变量
diagSendRequest(reqExtendedSession); // 发送诊断请求
if(1 != testWaitForDiagResponse(reqExtendedSession, 1000)) { // 等待收到诊断响应
write("进入扩展会话的诊断请求,未收到响应!");
return;
}
respCode = diagGetLastResponseCode(reqExtendedSession);
if(-1 != respCode)
{
write("进入扩展会话的诊断请求,收到了否定响应,否定响应码为0x%02X", respCode);
return;
}
write("进入扩展会话的诊断请求收到了肯定响应");
/*
diagGetRespParameter —— 获取诊断响应中指定参数的值(数值、字符串)
*/
// {
// int sessionType; // 诊断响应中返回的当前会话类型
// int p2; // 诊断响应中返回的常规超时时间(P2 Server Time)
// int p2ex; // 诊断响应中返回的特殊超时时间(P2 extended Server Time)
//
// sessionType = diagGetRespParameter(reqExtendedSession, 1, "DiagSessionType");
// p2 = diagGetRespParameter(reqExtendedSession, 1, "P2");
// p2ex = diagGetRespParameter(reqExtendedSession, 1, "P2Ex");
// write("当前的会话类型为:%d", sessionType);
// write("P2时间为:%dms", p2);
// write("P2Ex时间为:%dms", p2ex);
// }
/*
diagGetRespParameterRaw —— 获取诊断响应中指定参数的原始字节数组
*/
// {
// byte p2[2];
// int i;
//
// diagGetRespParameterRaw(reqExtendedSession, "P2", p2, elCount(p2));
// for(i=0; i < elCount(p2); i++)
// {
// write("诊断响应中参数P2的第%d个字节的值为:0x%02X", i, p2[i]);
// }
// }
/*
DiagGetRespPrimitiveSize —— 获取诊断响应中的原始报文的字节数量
DiagGetRespPrimitiveByte —— 获取诊断响应中的原始报文中的指定索引上的字节
*/
{
int primitiveSize;
int i;
primitiveSize = DiagGetRespPrimitiveSize(reqExtendedSession);
write("诊断响应的报文原始字节数量为:%d", primitiveSize);
for(i = 0; i < primitiveSize; i++)
{
byte b;
b = DiagGetRespPrimitiveByte(reqExtendedSession, i);
write("诊断响应的原始报文中第%d个字节为0x%02X", i, b);
}
}
}
示例4:读取DTC的列表:19 02服务
void Demo5_ReadDTC()
{
diagRequest DoorFL.FaultMemory_ReadAllIdentified reqReadDTC; // 创建一个诊断请求变量
int respCode; // 创建一个诊断响应的响应码变量
// 设置读取故障码请求的故障码状态掩码参数值为0x01
diagSetParameter(reqReadDTC, "DTCStatusMask", 0x01);
// 发送诊断请求
diagSendRequest(reqReadDTC);
// 等待直到收到诊断的响应
if(1 != testWaitForDiagResponse(reqReadDTC, 1000))
{
write("读取故障码列表的诊断请求,未收到响应!");
return;
}
// 获取诊断响应的响应码
respCode = diagGetLastResponseCode(reqReadDTC);
if(-1 != respCode)
{
write("进入扩展会话的诊断请求,收到了否定响应,否定响应码为0x%02X", respCode);
return;
}
{
int dtcCount;
int i;
// 获取诊断响应中的指定的符合参数的参数值的个数
dtcCount = diagGetRespIterationCount(reqReadDTC, "ListOfDTC");
write("读取故障码请求的响应报文中,返回的故障信息的数量:%d", dtcCount);
// 获取诊断响应中的每一组故障信息的参数值
for(i = 0; i < dtcCount; i++)
{
char dtcText[100];
long dtc;
int status;
diagGetComplexRespParameter(reqReadDTC, "ListOfDTC", i, "DTC", dtcText, elCount(dtcText));
dtc = diagGetComplexRespParameter(reqReadDTC, "ListOfDTC", i, "DTC");
status = diagGetComplexRespParameter(reqReadDTC, "ListOfDTC", i, "StatusOfDTC");
write("读取到的第%d个故障信息的故障码码值为:0x%06X,故障文本为:%s,状态码为:0x%02X", i, dtc, dtcText, status);
}
}
}
示例5:解锁ECU
void Demo6_UnlockECU()
{
/*
进入到扩展会话
*/
{
diagRequest DoorFL.ExtendedDiagnosticSession_Start reqExtendSession;
diagSendRequest(reqExtendSession); // 发送“进入扩展会话”的诊断请求
testWaitForDiagResponse(reqExtendSession, 1000); // 等到收到诊断的响应
if(diagGetLastResponseCode() != -1)
{
write("进入扩展会话的诊断请求,未收到肯定响应");
return;
}
}
/*
申请安全种子 --> 根据种子计算出Key -->发送Key来解锁ECU
*/
{
diagRequest SeedLevel_0x01_Request reqGetSeed; // 获取种子的请求
diagRequest KeyLevel_0x01_Send reqSendKey; // 发送Key的请求
byte seedArray[2];
byte keyArray[255];
dword keyActualSize;
int i;
diagSendRequest(reqGetSeed); // 发送“获取安全种子”请求
testWaitForDiagResponse(reqGetSeed, 1000); // 等待收到诊断的响应
if(diagGetLastResponseCode() != -1)
{
write("获取安全种子的诊断请求,未收到肯定响应");
return;
}
// 获取响应中返回的种子的字节数组
diagGetRespParameterRaw(reqGetSeed, "SecuritySeed", seedArray, elCount(seedArray));
write("获取到的安全种子的字节为:0x%02X 0x%02X", seedArray[0], seedArray[1]);
// 根据种子计算出Key
diagGenerateKeyFromSeed(seedArray, elCount(seedArray), 1, "", "", keyArray, elCount(keyArray), keyActualSize);
write("生成的Key的字节数:%d", keyActualSize);
write("生成的Key的字节为:");
for(i = 0; i < keyActualSize; i++)
{
write("\t0x%02X", keyArray[i]);
}
// 给“发送Key”的请求设置参数(SecurityKey)
diagSetParameterRaw(reqSendKey, "SecurityKey", keyArray, keyActualSize);
// 发送key的请求
diagSendRequest(reqSendKey);
}
}