在前面三篇文章中(vTESTstudio系列3--vTESTstudio自带测试函数对ECU的测试(一)、vTESTstudio系列4--vTESTstudio自带测试函数对ECU的测试(二)、vTESTstudio系列5--vTESTstudio自带测试函数对ECU的测试(三))主要介绍了vTESTstudio工程自带的已经封装好的函数的结构以及如何去使用这些函数,这些自带的函数能满足大部分的测试需求,但是对于某些特殊的需求,我们需要根据需求以及vTESTstudio工程自带的一些函数,去实现比较高级的需求,Let's Go!!!
目录
1.1 Check RollingCounter的CAPL函数的实现逻辑如下:
2.1 Check CheckSum的CAPL函数的实现逻辑如下:
在CAN报文中,Rolling Counter(滚动计数器)和CheckSum(校验和)是用于数据完整性和可靠性验证的重要字段。
1.对Rolling Counter的check:
Rolling Counter是一个4位的字段,用于跟踪发送的CAN报文数量。每当CAN节点发送一个新的报文时,滚动计数器的值就会增加1。这个计数器的作用是确保接收方可以检测到报文丢失或重复。通过比较接收到的报文中的滚动计数器值与上一次接收到的报文的滚动计数器值,接收方可以确定是否有报文丢失或重复。如果接收到的报文的滚动计数器值小于上一次接收到的报文的滚动计数器值,那么可能发生了报文丢失。如果接收到的报文的滚动计数器值等于上一次接收到的报文的滚动计数器值,那么可能发生了报文重复。
1.1 Check RollingCounter的CAPL函数的实现逻辑如下:
export testfunction TF_CheckRollingCounter(char MessageName[], char SignalName[])
{
dword MessageID;
long result;
long Timeout;
float SignalValue;
float storeValue[45];
int i;
result = 0;
Timeout = 5000;
MessageID = GetMessageID(MessageName);
result = TestWaitForMessage(MessageID, Timeout);
if (result == 1)
{
for (i=0;i<45;i++)
{
result = TestWaitForMessage(MessageID, Timeout);
if(result)
{
SignalValue = getSignal(SignalName);
storeValue[i] = SignalValue;
}
else
TestStepFail("INFO","The message has not arrived");
}
}
else if (result == 0)
{
//Timeout occured!
TestStepFail("INFO","The message has not arrived within timeout!");
}
else if(result == -2)
{
TestStepFail("INFO","Constraint violation!");
}
else
{
TestStepFail("INFO","General error!");
}
for (i=0;i<44;i++)
{
if(storeValue[i] ==(storeValue[i+1]-1))
{
TestStepPass("INFO","AliveCounter value is: %f, AliveCounter increased 1",storeValue[i]);
}
else if(storeValue[i]==14 && storeValue[i+1]==0)
{
TestStepPass("INFO","AliveCounter value is: %f, AliveCounter change from 14 to 0",storeValue[i]);
}
else
{
TestStepFail("INFO","AliveCounter value is: %f,AliveCounter Incorrect!",storeValue[i]);
}
}
}
上述代码中,MessageName和SingalName是需要传入的函数参数,SingalName是需要传入的rollingcounter的信号名,MessageName是被测rollingcounter信号所在的报文名,代码的主要逻辑如下:
1.检测到CAN总线上有传入的MessageName是否在发送
2.for循环中获取45次rollingcounter的信号值,并把这45次的信号值存到一个定义好的数组里
3.对存到数组里面的数值进行比较,检测从1-45的信号值是否按照从0-14这样的循环发送的,如果rollingcounter的值是从0开始每次递增+1,然后到达14后翻转为0的循环,则认为该rollingcounter的发送逻辑符合需求。
1.2 vTESTstudio工程中的脚本如下:
1.3 实际测试报告如下:
可以看到报告中的这个函数获取了45帧报文,并将rolling counter的值存储下来,然后进行校验的。
2.对CheckSum的check:
CheckSum是一个8位的字段,用于验证CAN报文的数据完整性。它基于报文中的数据生成,并附加在报文的末尾。发送方在发送报文之前计算校验和,然后将其添加到报文中。接收方在接收到报文后,使用相同的算法重新计算校验和,并将其与报文中的校验和进行比较。如果两者一致,则说明报文在传输过程中没有发生数据损坏;如果不一致,则说明报文可能存在错误或损坏。
2.1 Check CheckSum的CAPL函数的实现逻辑如下:
export testfunction TF_Checksum(char MessageName[], char SignalName[])
{
//result1 is for wait message
long result1;
//result2 is for wait for message content
long result2;
long Timeout;
dword ActualCRC;
dword CalCRC;
int dataLength=8;
int i;
dword MessageID;
message * MsgData;
Timeout = 500;
result1 = 0;
result2 = 0;
//Recieved Singal Checksum
MessageID = GetMessageID(MessageName);
result1 = TestWaitForMessage(MessageID, Timeout);
if (result1 == 1)
{
//get actual checksum value
ActualCRC = getSignal(SignalName);
}
else if (result1 == 0)
{
// Timeout occured!
TestStepFail("INFO","The message has not arrived within timeout!");
}
else if(result1 == -2)
{
TestStepFail("INFO","Constraint violation!");
}
else
{
TestStepFail("INFO","General error!");
}
result2=TestGetWaitEventMsgData(MsgData);
if(result2 == 0)
{
TestStep("INFO","This message rolling counter is %x",MsgData.byte(6));
CalCRC = CalculateCRC( MsgData, MessageID);
}
else
{
TestStepFail("INFO","Data access could not be executed, the last event was not a message event!");
}
//Verify the Checksum
if (CalCRC == ActualCRC)
{
TestStepPass("1.0", "Calculated checksum = %X, and received checksum = %X", CalCRC, ActualCRC);
}
else
{
TestStepFail("1.0", "Calculated checksum = %X, and received checksum = %X", CalCRC, ActualCRC);
}
}
byte CalculateCRC( message* MsgData, dword MessageID)
{
int i;
crc_temp=0x00;
for (i=0;i<7;i++)
{
crc_temp =crc_temp + MsgData.byte(i);
}
crc_value = crc_temp^0xFF;
return crc_value;
}
上述代码中,MessageName和SingalName是需要传入的函数参数,SingalName是需要传入的checksum的信号名,MessageName是被测checksum信号所在的报文名,代码的主要逻辑如下:
1.检测到CAN总线上有传入的MessageName是否在发送
2.然后通过getsingal来获取当前这一帧报文的checksum的信号值
3.获取该帧报文所有的byte数据值
4.通过CalculateCRC这个函数去计算当前该报文的实际checksum的数值
5.比较通过算法计算的CRC值和实际获取的CheckSum信号的实际值来确定CRC是否正确