如何CAPL文件应用到Busmaster软件上进行测试

1、CAPL概述

做汽车电子软件CAN开发的小伙伴应该都用过Canoe,Canalyzer此类Vector系列工具,Canoe自带的二次开发工具CAPL Browser真的是很方便,通过CAPL的编程,我们可以在节点上完成更为复杂的功能需求,CAPL是一种类C语言,熟悉C语言的小伙伴应该都很容易上手,而且CAPL Browser可以直接调用DBC及CDD信号接口,这样做CAN应用测试和诊断测试就大大提升了效率。
在Simuilation菜单界面添加Network Node 或者CAPL Test Module,此处建议添加前者,后面注意事项会有提到。

2、Busmaster软件概述

实际工作中,有Canoe那当然是很好的,但是很多时候Canoe很少,我们只能用Kvaser、PCAN这类CAN工具,这时候开源免费的Busmaster软件我们可能用的就比较多,Busmaster软件功能蛮多的,基础功能就不细叙了,几个特殊的用途如下:

  1. 记录log,存为.log文件,然后可以转化为Canoe支持的asc格式,在Canoe软件上进行回放,分析;
  2. 将DBC文件转化为自身支持的DBF文件格式;
  3. 将CAPL Browser编写的CAPL文件转化为自身支持的CPP文件,进行同样功能的测试;
    本文主要介绍第三种功能;

3、软件环境准备

  1. 安装Canoe软件,做车载软件开发的基本都有(没有就在某鱼上淘一个),要求支持CAPL Browser;
  2. 安装Busmaster软件;
  3. 打开Busmaster Help菜单 View Help搜索GCC,按照指示安装GCC;
    在这里插入图片描述
    我自己电脑装的是 tdm64-gcc-5.1.0-2,可供参考;

4、应用举例一:诊断10服务测试(详细叙述步骤)

这个测试很简单,就是不断发诊断10服务请求,监测ECU响应,如果在规定时间内没有收到响应,就打印错误提示,然后终止测试;

  1. 打开Canoe CAPL Browser编写CAPL文件

variables
{
  msTimer Timer100ms;
  msTimer Timer1s;
  message 0x732  Message_732;
  byte ReceiveTimeoutFlag = 0;
}

on timer Timer100ms
{
  if( 1 == ReceiveTimeoutFlag)
  {
    Message_732.dlc = 8;
    Message_732.byte(0) = 0x02;
    Message_732.byte(1) = 0x10;
    Message_732.byte(2) = 0x03;
    Message_732.byte(3) = 0x00;
    Message_732.byte(4) = 0x00;
    Message_732.byte(5) = 0x00;
    Message_732.byte(6) = 0x00;
    Message_732.byte(7) = 0x00;
    output(Message_732);
    setTimer(Timer1s,1000);
    ReceiveTimeoutFlag = 0;
  }
}
on timer Timer1s
{
  if( 1 != ReceiveTimeoutFlag)
  {
    write("接收超时,终止测试");
  }
}
on Start
{
  Message_732.dlc = 8;
  Message_732.byte(0) = 0x02;
  Message_732.byte(1) = 0x10;
  Message_732.byte(2) = 0x03;
  Message_732.byte(3) = 0x00;
  Message_732.byte(4) = 0x00;
  Message_732.byte(5) = 0x00;
  Message_732.byte(6) = 0x00;
  Message_732.byte(7) = 0x00;
  output(Message_732);
  setTimer(Timer100ms,100);
  write("开始测试");
}

on message 0x612
{
  setTimer(Timer100ms,100);
  cancelTimer(Timer1s);
  ReceiveTimeoutFlag = 1;
  write("收到诊断响应");
}

编写完成之后,要确认Compile成功,没有错误;

  1. 将此文件用Busmaster软件中的Format Convert转化为CPP文件
    在这里插入图片描述
    1)选择.can文件
    2)生成的.cpp文件名称及位置
    3)如果.can文件中运用到了DBC文件中的内容,则此处需要添加DBC文件;
    4)如果你没有将DBC文件转化为DBF格式过,此处需要选择上,只要转化一次就够了,DB没有修改就不需要每次都选择;
    5)开始转化
    此处CAPL文件中没有用到DBC,所以不需要选择dbc;
    在这里插入图片描述
  2. 点击Busmaster的Node Simulation,添加Node,选择上述生成的CPP文件;
    在这里插入图片描述
    在这里插入图片描述
    添加完成之后,点击编译,没有报错,就可以正常使用了;
    在这里插入图片描述
    注意
    编译信息在Output Window
    打印信息在Trace Window

5、应用举例二: 诊断测试27服务自动解锁

此处模拟的是诊断27服务自动解锁,测试CAN诊断的时候,很多服务需要在解锁状态下才支持,测试起来很不方便,我们可以做一个脚本实现收到Seed的时候,自动计算Key,发送到总线上,完成解锁;
基本操作步骤跟上面举例一样,此处运用了DBC接口(可以不用):

/*@!Encoding:936*/


variables
{

  message DiagPhyReq message_732;
}


/*06 67 03 xx xx xx xx*/
/*06 27 04 xx xx xx xx*/
on message DiagResponse
{
  byte seed[4];
  byte key[4];
  byte level;
  
  
  level = this.byte(2) +1;
  if(((this.byte(1) == 0x67)&&(this.byte(2) == 0x03))||((this.byte(1) == 0x67)&&(this.byte(2) == 0x01)))
  {
    seed[0] = this.byte(3);
    seed[1] = this.byte(4);
    seed[2] = this.byte(5);
    seed[3] = this.byte(6);
	/***************************/
	/*********caculate key******/
	/***************************/
    message_732.byte(0) = 0x06;
    message_732.byte(1) = 0x27;
    message_732.byte(2) = level;
    message_732.byte(3) = key[0];
    message_732.byte(4) = key[0];
    message_732.byte(5) = key[0];
    message_732.byte(6) = key[0];
    message_732.byte(7) = 0x00;
    output(message_732);
  }
   else if((this.byte(1) == 0x67)&&(this.byte(2) == 0x04))
   {
      write("解锁成功");
   }
}

注意:
1、DiagPhyReq、DiagResponse是DBC里面的message;
2、转化文件的时候需要加载DBC
在这里插入图片描述

6、应用举例三: 模拟车载ECU自动响应

此处模拟的是车身的ECU,收到什么报文信号,反馈什么报文信号,如果不运用的DBC里面直接的信号定义,就得自己去解析信号,所以运用DBC这时候就事半功倍;
直接上代码:

/*@!Encoding:936*/

variables
{
  msTimer Timer500;
  msTimer Timer1000;
  message HS7_VSM_INF_PROFILS  Message_260;
  message HS7_INFO_IHM  Message_268;
  message HS7_CDE_LED_PUSH Message_227;
  message HS7_ETAT_CLIM_AV Message_350;
  message HS7_CDE_IHM_CLIM Message_2AD;
  byte LKACounter;
}

on Start
{
  Message_260.DISPO_PARAM = 1;
  Message_350.DMD_AC = 1;
  Message_350.ENTREE_AIR = 2;
  Message_350.ETAT_MONO = 0;
  Message_350.PULS_AV =5;
  Message_2AD.ETAT_ELEC_IHM_CLIM = 2;
  Message_2AD.CONS_TEMP_CENT = 3;
  setTimer(Timer500,500);
  setTimer(Timer1000,1000);
}

/*06 67 03 xx xx xx xx*/
/*06 27 04 xx xx xx xx*/

on message HS7_ECRAN_INFO_PROFILS
{
    byte temp;
  
  
    temp = this.ECLAIRAGE_ACCOM;
    //伴我回家
    Message_260.ECLAIRAGE_ACCOM = temp;
  
  
    //伴我回家时间
    temp = this.TEMPO_EXT_PHARE;
    Message_260.TEMPO_EXT_PHARE = temp;
  
  
    //迎宾灯
    temp = this.ECL_DECONDA;
    Message_260.ECL_DECONDA = temp;
  
  
    //迎宾灯时间
    temp = this.TEMPO_ECL_DECONDA;
    Message_260.TEMPO_ECL_DECONDA = temp;
  
  
    //远近光
    temp = this.FCT_ECLX_ECL_CAFR;
    Message_260.FCT_MENU_ECLX_ECL_CAFR = temp;
  
  
    //情景照明/氛围灯
    temp = this.ECLAI_AMBI;
    Message_260.ECLAI_AMBI = temp;
  
  
    //氛围灯等级
    temp = this.NIV_AMBIANCE;
    Message_260.NIV_AMBIANCE = temp;
  
  
    //自动大灯
    temp = this.ECLAIRAGE_AUTO;
    Message_260.ECLAIRAGE_AUTO = temp;
  
  
    //紧急制动
    temp = this.ARC_SENS;
    Message_260.ARC_SENS = temp;
  
  
    //紧急制动等级
    temp = this.ARC_SENS_NIV;
    Message_260.ARC_SENS_NIV = temp;
  
  
    //疲劳驾驶
    temp = this.DMD_MENU_DAA_ACTIV;
    Message_260.FCT_MENU_DAA_ACTIV = temp;
  
  
    //泊车辅助
    temp = this.AAS_STATUS;  
    Message_260.AAS_STATUS = temp;  
  
  
    //车门解锁
    temp = this.SELEC_OUV_PLIP;
    Message_260.SELEC_OUV_PLIP = temp;
  
  
    //后备箱解锁
    temp = this.SELEC_ARRIERE;
    Message_260.SELEC_ARRIERE = temp;
  
  
    //自动后雨刮
    temp = this.ESSUI_VIT_MAR;
    Message_260.ESSUI_VIT_MAR = temp;
  
  
  
  output(Message_260);
}
//message 329
on message HS7_DEMANDES_IVI_2
{
  byte temp;
  
  temp = this.DMD_FREIN_ASR_TACT_INHIB;
  //牵引力控制系统
  if( Message_268.P_INFO_ESP_INHIB_ASR != temp)
  {
    Message_268.P_INFO_ESP_INHIB_ASR = temp;
    output(Message_268);
  }
  //车道保持辅助
  
  
  temp = this.ENT_PUSH_LKA;
  if(temp)
  {
    if(LKACounter != 3)//会受到3帧,只处理一帧
    {
	  if(LKACounter == 0)
	  {
		  if(Message_227.SORTIE_PUSH_LKA == 0)
		  {
			Message_227.SORTIE_PUSH_LKA = 1;
		  }
		  else
		  {
			Message_227.SORTIE_PUSH_LKA = 0;     
		  }
		  output(Message_227);
	  }
	  LKACounter++;
    }
    else if(LKACounter == 3)
    {
      LKACounter = 0;
    }
  }
}
on message HS7_ETAT_PUSH_TACT
{
  byte temp;
  dword time;
  byte SendFlag = 0;
  
  //左温度
  temp = this.DMD_NIV_TEMP_AVG;
  if( Message_350.VAL_CONS_TEMP_AVG != temp)
  {
    write("调节左温度");
    Message_350.VAL_CONS_TEMP_AVG = temp;
    SendFlag = 1;
  }
   //左温度
  temp = this.DMD_NIV_TEMP_AVD;
  if( Message_350.VAL_CONS_TEMP_AVD != temp)
  {
    write("调节右温度");
    Message_350.VAL_CONS_TEMP_AVD = temp;
    SendFlag = 1;
  } 
  
  //AC
  temp = this.DMD_PUSH_AC;
  if(temp)
  {
    write("     AC Pressed");
    if(Message_350.DMD_AC == 1)//open
    {
      Message_350.DMD_AC = 2;//close
    }
    else
    {
      Message_350.DMD_AC = 1;//open
    }
    SendFlag = 1;
  } 
  //Recycle
  temp = this.DMD_ENTREE_AIR;
  if(temp)
  {
     write("Recycle Pressed");
    if(Message_350.ENTREE_AIR == 2)//open
    {
      Message_350.ENTREE_AIR = 3;//close
    }
    else
    {
      Message_350.ENTREE_AIR = 2;//open
    }
    SendFlag = 1;
  }   
  //SYNC
  temp = this.DMD_MONO;
  if(temp)
  {
     write("SYNC Pressed");
    if(Message_350.ETAT_MONO == 0)//open
    {
      Message_350.ETAT_MONO = 1;//close
    }
    else
    {
      Message_350.ETAT_MONO = 0;//open
    }
    SendFlag = 1;
  }  
  //blower  
  temp = this.DMD_NIV_PULSEUR_AV;
  if(Message_350.PULS_AV != temp)
  {
    write("调节风量:%d",temp);
    Message_350.PULS_AV = temp;
    SendFlag = 1;
  } 
  //blower +
  temp = this.DMD_PULSEUR_AV_PLUS;
  if(temp)
  {
     write("Blower + Pressed");
    if(Message_350.PULS_AV <9)//open
    {
      Message_350.PULS_AV++;//close
    }
    SendFlag = 1;
  }  
  //blower - 
  temp = this.DMD_PULSEUR_AV_MOINS;
  if(temp)
  {
    write("Blower- Pressed");
    if(Message_350.PULS_AV >1)
    {
      Message_350.PULS_AV--;
    }
    SendFlag = 1;
  }  
  
  
  
  if(SendFlag)
  {
     output(Message_350);
    SendFlag = 0;
  }
  
  
  
}
on timer Timer500
{
  output(Message_260);
  output(Message_227);
  output(Message_350);
  output(Message_2AD);
  setTimer(Timer500,500);
}
on timer Timer1000
{
  output(Message_268);
  setTimer(Timer1000,1000);
}



7、注意事项

这个功能最近用下来,其实也不是什么样格式的CAPL都可以直接转化来用,但是一些基本的测试其实都还OK,我把我调试过程中的一些注意事项列出来:

  1. CAPL 编程不要存在空白区域 例如:
Include
{
/*空白,没有实际代码*/
}

  1. DBC文件名不要过长,简单就好,例如Test.dbc
  2. CAPL中应定义 On Start ,不要用On Prestart ,On start 中就是初始化做的事情;
  3. on message 中 不能直接调用this.signal,否则cpp编译的时候会报错,例如:
on message message1
{
Message0.signal0= this.signal0;
}

应该写成如下格式:

on message message1
{
   byte temp;
   temp = this.signal0;
   Message0.signal0= temp ;
}

  1. 在Simuilation菜单界面添加Network Node,不要添加CAPL Test Module,二者代码框架不太一样;

7、结尾语

我这些总结有些地方也太片面了,不过总体上步骤没啥问题,有啥问题,欢迎指正;

  • 11
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lseyer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值