欢迎大家学习我的《带你玩转车载测试——CAPL入门篇》系列课程,我是分享人M哥,目前从事车载控制器的软件开发及测试工作。
学习过程中如有任何疑问,可底下评论!
如果觉得文章内容在工作学习中有帮助到你,麻烦点赞收藏评论+关注走一波!感谢各位的支持!
CANoe中的诊断库函数主要有两类:一类是依据CDD文件使用的函数;另一类是依据传输层动态库(cantp.dll)来实现诊断功能的函数。第一类函数的使用需要制作完整的CDD文件,适用于编程能力一般且简单地诊断场合,而第二类函数通过cantp.dll来实现诊断,对编程能力有一定的要求,适用于复杂的诊断场合,如flash流程。后续M哥将对两种形式的诊断库函数分别介绍,今天先来介绍基于CDD文件的诊断库函数。
常用函数如下表1所示:
函数名 | 功能 |
diagSetTarget | 设置诊断的目标ECU |
diagSendRequest | 向目标ECU发送诊断请求 |
diagStartTesterPresent | 向目标ECU开始发送TesterPresent请求 |
diagStopTesterPresent | 向目标ECU开始发送TesterPresent请求 |
diagSendFunctional | 向目标ECU发送功能寻址诊断请求 |
diagSetTimeout | 设定诊断请求超时时间 |
diagSetTimeoutHandle | 创建回调函数用于诊断请求超时调用 |
(1)diagSetTarget:用于设置诊断的目标ECU名,使之与目标ECU建立诊断通信,其参数为ECU名,即CDD文件中的 “ECU qulifier”,如下图所示:
下面代码表示当按下‘b’键时,所建立的目标ECU是否正确:
on key 'b'
{
if( 0 == diagSetTarget( "Vector_Seat"))
write( "Correct setting target!");
}
(2)diagSendRequest:向目标ECU发送诊断请求,比如:按下按键‘b’,发送进入拓展会话请求;
includes
{
}
variables
{
diagRequest Vector_Seat.ExtendedDiagnosticSession_Start ExtendSessionReq;
}
on key 'b'
{
long ret;
ret = diagSendRequest(ExtendSessionReq);
if(ret == 0){
write("Request Succeed!");
}
}
(3)diagStartTesterPresent和diagStopTesterPresent: 用于向设定目标ECU发送/停止TesterPresent请求,如按下按键‘a’,发送TesterPresent请求,按下按键‘b’,停止TesterPresent请求;
includes
{
}
variables
{
}
on key 'a'
{
long ret;
ret = diagStartTesterPresent("Vector_Seat");
if(ret == 0){
write("发送TesterPresent请求!");
}
}
on key 'b'
{
long ret;
ret = diagStopTesterPresent("Vector_Seat");
if(ret == 0){
write("停止TesterPresent请求!");
}
}
(4) diagSendFunctional:上述diagSendRequest向目标ECU发送请求是以物理寻址的方式,而diagSendFunctional则是以功能寻址的方式向ECU发送请求(功能寻址ID:0x750),如下所示:
includes
{
}
variables
{
diagRequest Vector_Seat.ExtendedDiagnosticSession_Start ExtendSessionReq;
}
on key 'a'
{
long ret;
ret = diagSendFunctional(ExtendSessionReq);
if(ret == 0){
write("功能寻址请求进入拓展会话!");
}
}
(5)diagSetTimeout和diagSetTimeoutHandle:这两个函数主要用于诊断请求超时设置及其超时处理,进行超时处理时是通过回调函数的方式进行执行,如下所示:
variables
{
}
on start
{
diagSetTimeout (10); // Set timeout to 200 ms
diagSetTimeoutHandler("Request_Timeout");
}
on key 'a'
{
diagRequest Vector_Seat.ExtendedDiagnosticSession_Start ExtendSessionReq;
diagSendRequest(ExtendSessionReq);
}
void Request_Timeout()
{
write("No response received within expected time frame!");
}
Miscellaneous库函数通常为安全访问函数,常用的如下所示:
函数名 | 功能 |
diagGenerateKeyFromSeed | 通过种子计算生成密钥 |
diagSetCurrentSession | 用于设置ECU当前的诊断会话 |
diagStartGenerateKeyFromSeed | 通过种子计算生成密钥 |
_Diag_GenerateKeyResult | 返回diagStartGenerateKeyFromSeed计算出的密钥结果 |
(1)diagGenerateKeyFromSeed:此函数主要通过CDD中添加的seed_key.dll文件来计算ECU解锁密钥并返回计算结果,一般用于test module模块,如下:
includes
{
}
variables
{
//actual size of Seed and Key Arrays depend on ECU
byte gSeedArray[2];
int gSeedArraySize = 2;
int gSecurityLevel = 0x01;
char gVariant[200] = "Variant1";
char gOption[200] = "option";
byte gKeyArray[2];
int gMaxKeyArraySize = 2;
dword gActualSizeOut = 2;
char gDebugBuffer[2000];
diagRequest DoorFL.ExtendedDiagnosticSession_Start gExtendSessionReq;
diagRequest DoorFL.SeedLevel_0x01_Request gSeedReq;
diagResponse DoorFL.SeedLevel_0x01_Request gSeedResp;
diagRequest DoorFL.KeyLevel_0x01_Send gKeyReq;
}
//Unlock ECU by calling customer specific SeedKey DLL (e.g. in a CAPL test module)
testcase UnlockEcu()
{
long ret;
diagSendRequest(gExtendSessionReq);
//Request seed from ECU
diagSendRequest(gSeedReq);
//Wait until request has been sent completely
testWaitForDiagRequestSent(gSeedReq, 1000); //Wait for response and write seed from response parameter to array
testWaitForDiagResponse(gSeedReq, 1000);
diagGetLastResponse (gSeedReq, gSeedResp);
diagGetParameterRaw (gSeedResp, "SecuritySeed", gSeedArray, elcount(gSeedArray)); //Calculate key
ret = diagGenerateKeyFromSeed ( gSeedArray, gSeedArraySize, gSecurityLevel, gVariant, gOption, gKeyArray, gMaxKeyArraySize, gActualSizeOut);
if( 0 == ret) //diagGenerateKeyFromSeed successful
{
//Write result to diagnostic request
diagSetParameterRaw(gKeyReq, "SecurityKey", gKeyArray, gActualSizeOut);
//Send Key to unlock ECU
gKeyReq.SendRequest();
testWaitForDiagRequestSent(gKeyReq, 1000);
}
}
void MainTest ()
{
UnlockEcu();
}
(2)diagSetCurrentSession:用于设定ECU的当前诊断会话。
(3)diagStartGenerateKeyFromSeed和_Diag_GenerateKeyResult:diagStartGenerateKeyFromSeed函数用来计算生成的密钥,而密钥计算的结果通过回调函数_Diag_GenerateKeyResult来返回,如下所示:
_Diag_GenerateKeyResult( long result, BYTE computedKey[])
{
diagRequest DoorFL.SeedLevel_0x01_Request rqSendKey;
if( 0 != result)
{
write( "Error: computing key returned %d", result);
return;
}
// Success, i.e. a key was computed, so send it to the ECU
rqSendKey.SetParameterRaw( "SecurityKey", computedKey, elcount(computedKey));
rqSendKey.SendRequest();
}
on diagResponse DoorFL.SeedLevel_0x01_Request
{
BYTE seed[2];
long count;
count = this.GetParameterRaw( "SecuritySeed", seed, elcount(seed));
diagStartGenerateKeyFromSeed(seed, elcount( seed), 1, "variant", "option");
}
on key 'u' // unlock
{
diagRequest DoorFL.ExtendedDiagnosticSession_Start ExtendReq;
diagRequest DoorFL.SeedLevel_0x01_Request rqRequestSeed;
ExtendReq.SendRequest();
rqRequestSeed.SendRequest();
}
由于诊断库函数众多,后续将继续进行讲述,敬请期待............
感谢对本期内容不遗余力的学习,下期内容即将奉上,欢迎下次光临!