1. 说明
在车载诊断中,有时需要对报文的周期进行检测,可能涉及单个报文或多个报文,编写了检测CAN报文周期的通用脚本函数,可以自动对需要的报文进行检测,根据提供的报文周期判据上下限,自动进行判定,并体现在报表中
2. 函数介绍
void CheckMultMsgCyc(long messageID[],float aCycMinCycleTime[],float aCycMaxCycleTime[],int msgNum,dword KTIMEOUT)
参数介绍:
messageID :需要检测的CAN报文ID,数组格式,可以添加多个报文ID;
aCycMinCycleTime : 需要检测的报文周期下限值,数组格式,可以添加对应报文ID的对应判据下限;
aCycMaxCycleTime :需要检测的报文周期上限值,数组格式,可以添加对应报文ID的对应判据上限;
msgNum :需要检测的CAN报文数量;
KTIMEOUT :检测时长,单位为ms;
原理介绍:
使用canoe提供的ChkStart_MsgAbsCycleTimeViolation注册函数进行检测。下图是官方函数说明。
函数体:
//检测多个报文周期
void CheckMultMsgPeriod(long messageID[],float MinPeriodTimes[],float MaxPeriodTimes[],int msgNum,dword KTIMEOUT)
{
float lQueryResultProbeMin[255],lQueryResultProbeMax[255];//声明最小测量时间
dword gCycCheckAllId[255];
int i;
//批量事件注册
for(i=0;i<msgNum;i++)
{
write("id:%x",messageID[i]);
gCycCheckAllId[i] = ChkStart_MsgAbsCycleTimeViolation(messageID[i],MinPeriodTimes[i],MaxPeriodTimes[i]);
TestAddCondition(gCycCheckAllId[i]);//条件设置函数
}
testWaitForTimeout(KTIMEOUT);//等待检测时间
//批量提取结果数值
for(i=0;i<msgNum;i++)
{
//统计最小时间
lQueryResultProbeMin[i] = ChkQuery_StatProbeIntervalMin(gCycCheckAllId[i]);
write("period:%fms",lQueryResultProbeMin[i]);
//统计最大时间
lQueryResultProbeMax[i] = ChkQuery_StatProbeIntervalMax(gCycCheckAllId[i]);
write("period:%fms",lQueryResultProbeMax[i]);
}
//批量结果判定
for(i=0;i<msgNum;i++)
{
if(ChkQuery_NumEvents(gCycCheckAllId[i])>0)
{//异常
TestStepFail("PeriodTest","0x%03x Valid values %.0fms - %.0fms",messageID[i],MinPeriodTimes[i],MaxPeriodTimes[i]);
if((lQueryResultProbeMin[i] >= MinPeriodTimes[i])&&(lQueryResultProbeMin[i] <= MaxPeriodTimes[i]))
TestStepPass("PeriodTest","0x%03x Min cycle time: %fms",messageID[i],lQueryResultProbeMin[i]);
else
TestStepFail("PeriodTest","0x%03x Min cycle time: %fms",messageID[i],lQueryResultProbeMin[i]);
if((lQueryResultProbeMax[i] >= MinPeriodTimes[i])&&(lQueryResultProbeMax[i] <= MaxPeriodTimes[i]))
TestStepPass("PeriodTest","0x%03x Max cycle time: %fms",messageID[i],lQueryResultProbeMax[i]);
else
TestStepFail("PeriodTest","0x%03x Max cycle time: %fms",messageID[i],lQueryResultProbeMax[i]);
}
else
{//正常
TestStepPass("PeriodTest","0x%03x Min cycle time: %fms",messageID[i],lQueryResultProbeMin[i]);
TestStepPass("PeriodTest","0x%03x Max cycle time: %fms",messageID[i],lQueryResultProbeMax[i]);
}
}
//批量事件销毁
for(i=0;i<msgNum;i++)
{
ChkControl_Destroy(gCycCheckAllId[i]);
}
}
3. 调用示例
建立testcase用例,调用周期检测函数,示例如下:
testcase Period_Test_Demo(char messageIDs[],char MinPeriodTimes[],char MaxPeriodTimes[],int MsgNum,double Timeout)
{
long messageIDs_Buffer[255];
float MinPeriodTimes_Buffer[255];
float MaxPeriodTimes_Buffer[255];
Spilt_String_To_Number(messageIDs,",",messageIDs_Buffer);
Spilt_String_To_Number(MinPeriodTimes,",",MinPeriodTimes_Buffer);
Spilt_String_To_Number(MaxPeriodTimes,",",MaxPeriodTimes_Buffer);
CheckMultMsgCyc(messageIDs_Buffer,MinPeriodTimes_Buffer,MaxPeriodTimes_Buffer,MsgNum,Timeout);
}
上面代码中的Period_Test_Demo测试用例函数调用了CheckMultMsgPeriod函数(周期检测函数),参数和周期检测函数中的参数能够对应,具体可以在代码中进行实际对应,当前用例采用的是xml配置形式,所以在xml中也需要配置,然后传递到Period_Test_Demo测试用例中。
XML的配置信息示例如下:
<capltestcase name="Period_Test_Demo" title="雷达CAN报文周期测试">
<caplparam type="string" name="messageIDs">[0x1,0x2,0x3,0x4,0x5,0x6,0x7]</caplparam>
<caplparam type="string" name="MinPeriodTimes">[49,49,49,49,49,49,49]</caplparam>
<caplparam type="string" name="MaxPeriodTimes">[51,51,51,51,51,51,51]</caplparam>
<caplparam type="int" name="MsgNum">7</caplparam>
<caplparam type="float" name="Timeout">10000</caplparam>
</capltestcase>
XML中的报文id、报文周期上下限值使用的是字符串格式,因为通过xml不能配置数组类型的参数,使用字符串可以传递很多自定义的数据,然后在代码中再进行转化,变成需要的数组数据。
4. 总结
通过这个函数,在实际的项目中实测是可以精确进行周期检测的,通用性较高,有需要的同学可以仿照进行测试,有疑问可以评论区或者私信问我。