当先锋百科网

首页 1 2 3 4 5 6 7

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

继续学习《CANoe开发从入门到精通》,实现第二个例程。

由于篇幅原因,且在《一步一步动手实现CANoe例程》中有详细的步骤,本例程中数据库文件设计、系统变量及Panel设计就不再面面俱到的展开。

例程主要实现的功能如下:
(1)控制面板:通过调节钥匙锁车/开锁按钮、引擎钥匙旋钮、离合器档位切换、刹车模拟开关、危险警示灯按钮、左转右转按钮、引擎速度滑动条和车速滑动条等控件,模拟IPC需要的测试条件。
(2)显示面板:接收来自总线的报文,显示引擎信息、车速信息、离合器档位信息和车灯的状态等。
(3)添 加 Automation Sequences 功 能 实 现 Signal 和 System Variable的自动变化。
(4)添加Graphic窗口和State Tracker追踪窗口等,便于分析和检测等相关活动。

一、网络拓扑图

网络由仪表单元(IPC)、网关(Gateway)、车身控制器(BCM)三部分组成;
网络拓扑如下图所示:
在这里插入图片描述

二、数据库文件设计

1、以Vector_IL_Basic Template为模板创建一个名称为VehicleSystem的CAN数据库。将它的Protocol设置为CAN。

2、右击Network Nodes,新建BCM、IPC、Gateway三个网络节点。如下图所示:
在这里插入图片描述

3、右击Message,新建报文,参数设置如下所示:
在这里插入图片描述

4、右击Signal,新建信号,参数设置如下所示:
在这里插入图片描述
5、在CANdb++工具栏上,单击Value Tables图标,进入Value Tables界面,在空白处右击,创建Value Table如下:
在这里插入图片描述

在Value Descriptions中参数设置如下所示:
在这里插入图片描述
至此,例程需要的DBC文件已经完成,将其导入仿真工程后如下所示:
在这里插入图片描述
三、设置系统变量
1、在CANoe主界面中选择Environment→System Variables,在左上侧空白窗口中单击鼠标右键系统变量,需要定义的系统变量列表及属性设置如下:
在这里插入图片描述
2、部分变量需要自己实现Value Table,
在这里插入图片描述

以Gear_Status为例,Value Table实现方法如下:
2.1、Values Table下拉选择Custom,如下图所示:
在这里插入图片描述
2.2、点击Value Table Items右侧的图标,进入Value Table编辑界面,如下图所示:
在这里插入图片描述
修改Value和Description为需要设置的值,如下所示:
在这里插入图片描述
完成后如下所示:
在这里插入图片描述

四、Panel设计

需要设计两个面板,用于模拟相关操作和数据的显示。
注意,以下列出的控件属性均为重要属性,未提及的属性将采用默认设置。

1、control面板主要用于模拟来自实际中BCM和Gateway的相关操作,面板的设计效果如下图所示:
在这里插入图片描述
控件列表及重要属性按照《CANoe开发从入门到精通》第292页来设定。

2、IPC面板主要用于模拟实际的仪表盘显示功能,设计效果如下图所示:
在这里插入图片描述
控件列表及重要属性按照《CANoe开发从入门到精通》第297页来设定。
设计时的图片素材在CANoe提供的Sample Configurations 16.4.4文件夹下搜索而来,部分素材和书上例程素材不同,稍作修改即可。
比如,引擎温度显示,书上例程左侧还有个温度刻度表,设计时选择Meter 1。我搜的图片没有,就加个简单的Input/Output Box 1来显示。

五、CAPL代码实现

1、IPC.can
IPC.can主要实现了报文的发送机制。当车在锁车状态时,报文不能通过IL层发送,解锁后周期性报文便可以通过IL层发送出去。

/*@!Encoding:936*/
includes
{
  
}

variables
{
  int busflag = 0;
}

on preStart
{
  ILControlInit();
  ILControlStop();
}

on signal_update LockStatus
{
  if(this!=busflag)
  {
    if(this==1)
    {
      ILControlStart();
    }
    else if(this==0)
    {
      ILControlStop();
    }
    busflag = this;
  }
}

on signal_update Gear
{
  @Cluster::Gear_Status = this;
}

2、BCM.can
在BCM.can中主要实现了转向灯的动态闪烁;

/*@!Encoding:936*/
includes
{
  
}

variables
{
  msTimer msTcrank;
  msTimer msTIL;
  int flashPeriod=500;
  
  int turnLightStatus;
  
  msTimer msTleftflash,msTrightflash;
  message Driver_Info Msgdriver;
}

on preStart
{
  ILControlInit();
  ILControlStop();
}

on sysvar_update Vehicle_Key::Key_State
{
  $Ignition_Info::KeyState=@this;
  if(@this==3)
  {
    @Vehicle_Control::Speed_Up=0;
    setTimer(msTcrank, 800);
  }
}

on timer msTcrank
{
  $KeyState=2;
  @sysvar::Vehicle_Key::Key_State=2;
}

on sysvar_update Vehicle_Key::Car_Driver
{
  if(@this==1)
  {
    Msgdriver.byte(0)=0;
  }
  else if(@this==2)
  {
    Msgdriver.byte(0)=0x1;
  }
  output(Msgdriver);
}

on sysvar_update Vehicle_Key::Unlock_Car
{
  if(@this==1)
  {
    ILControlStart();
    $LockStatus=1;
    @Vehicle_Key::Car_Driver=2;
  }
}
on sysvar_update Vehicle_Key::Lock_Car
{
  if(@this==1)
  {
    $LockStatus=0;
    setTimer(msTIL,1500);
  }
}

on timer msTIL
{
  ILControlStop();
}

void LightOFF(void)
{
  $VehicleLight=0;
  turnLightStatus=0;
  $LightStatus=0;
}

on sysvar Vehicle_Control::Left_Turn_Enable
{
  if(@this==1)
  {
    @sysvar::Vehicle_Control::Right_Turn_Enable=0;
    $VehicleLight=1;
    turnLightStatus=1;
    settimer(msTleftflash,flashPeriod);
  }
  else
  {
    if(@Vehicle_Control::Right_Turn_Enable==0 && @Vehicle_Control::Hazards_Enable==0)
    {
      LightOFF();
    }
    cancelTimer(msTleftflash);
    @Cluster::Left_Turn_Indicator=0;
  }
}

on timer msTleftflash
{
  $LightStatus=!$LightStatus;
  @Cluster::Left_Turn_Indicator=!@Cluster::Left_Turn_Indicator;
  setTimer(msTleftflash,flashPeriod);
}

on sysvar Vehicle_Control::Right_Turn_Enable
{
  if(@this==1)
  {
    @sysvar::Vehicle_Control::Left_Turn_Enable=0;
    $VehicleLight=2;
    turnLightStatus=2;
    setTimer(msTrightflash,flashPeriod);
  }
  else
  {
    if(@Vehicle_Control::Left_Turn_Enable==0 && @Vehicle_Control::Hazards_Enable==0)
    {
      LightOFF();
    }
    
    cancelTimer(msTrightflash);
    @Cluster::Right_Turn_indicator=0;
  }
}

on timer msTrightflash
{
  $LightStatus=!$LightStatus;
  @Cluster::Right_Turn_indicator=!@Cluster::Right_Turn_indicator;
  settimer(msTrightflash,flashPeriod);
}

on sysvar Vehicle_Control::Hazards_Enable
{
  if(@this==1)
  {
    $VehicleLight=3;
    @Cluster::Left_Turn_Indicator=1;
    @Cluster::Right_Turn_indicator=1;
    setTimer(msTleftflash,flashPeriod);
    setTimer(msTrightflash,flashPeriod);
  }
  else
  {
    $VehicleLight=turnLightStatus;
    switch(turnLightStatus)
    {
      case 1:
        cancelTimer(msTrightflash);
        @Cluster::Right_Turn_indicator=0;
        break;
      case 2:
        cancelTimer(msTleftflash);
        @Cluster::Left_Turn_Indicator=0;
        break;
      case 0:
        cancelTimer(msTrightflash);
        cancelTimer(msTleftflash);
        $LightStatus=0;
        @Cluster::Right_Turn_indicator=0;
        @Cluster::Left_Turn_Indicator=0;
        break;
    }
  }
}

3、Gateway.can
Gateway.can 中 , 根 据 Automation Sequences 中 System variable的变化,动态改变车速、引擎转速、油温和油量的值。该程序中车速、引擎转速、油温、油量变化因子只是为了配合Panel面板中可变化范围或可视化效果而增加的。

/*@!Encoding:936*/
includes
{
  
}

variables
{
  msTimer msTVehSpeedDown;
  msTimer msTEngSpeedDown;
  dword WritePage;
  int busflag=0;
}

on preStart
{
  ILControlInit();
  ILControlStop();
  writeLineEx(WritePage,1,"--------This demo demonstrated the CAN bus suimulation!!--------");
  writeLineEx(0,1,"Press <1> to start/stop CAN_logging");
}

on key '1'
{
  int flag;
  if(flag==0)
  {
    flag=1;
    write("CAN logging starts");
    startlogging("CAN_Logging",500);
  }
  else
  {
    flag=0;
    write("CAN logging ends");
    stopLogging("CAN_Logging",1000);
  }
}

on signal_update LockStatus
{
  if(this!=busflag)
  {
    if(this==1)
    {
      ILControlStart();
    }
    else if(this==0)
    {
      ILControlStop();
    }
    busflag=this;
  }
}

on sysvar Vehicle_Control::Gear
{
  $Gear=@this;
}

void EngineData_Init(void)
{
  $VehicleSpeed=0;
  $EngSpeed=0;
  $EngTemp=0;
  $PetrolLevel=0;
}

on signal_update KeyState
{
  if(this==0)
  {
    EngineData_Init();
  }
  if(this>0)
  {
    $PetrolLevel=255;
  }
}

on sysvar_update Vehicle_Control::Eng_Speed
{
  if(@Vehicle_Key::Key_State==2)
  {
    $EngineData::EngSpeed=@this;
  }
  else
    $EngineData::EngSpeed=0;
}

on sysvar_update Vehicle_Control::Veh_Speed
{
  if((@Vehicle_Control::Gear==3)&&(@Vehicle_Key::Key_State==2))
  {
    $VehicleData::VehicleSpeed=@this;
  }
  else
  {
    $VehicleData::VehicleSpeed=0;
  }
}

on sysvar_update Vehicle_Control::Speed_Up
{
  if(@this<50)
  {
    $EngTemp=@this*1.5;
  }
  else
  {
    $EngTemp=75;
  }
  if(@this<30)
  {
    $PetrolLevel=@this*8.5;
  }
  else
  {
    $PetrolLevel=255;
  }
  $VehicleSpeed=@this;
  $EngSpeed=@this*40;
  if(@this>120)
  {
    @this=60;
  }
}

on sysvar Vehicle_Control::Brake
{
  int i;
  if(@this==1)
  {
    $GearLock=0;
    setTimer(msTVehSpeedDown,20);
    setTimer(msTEngSpeedDown,2);
  }
  else
  {
    $GearLock=1;
    cancelTimer(msTVehSpeedDown);
    cancelTimer(msTEngSpeedDown);
  }
}

on timer msTVehSpeedDown
{
  @Vehicle_Control::Veh_Speed=@Vehicle_Control::Veh_Speed-1;
  setTimer(this,50);
  if(@Vehicle_Control::Veh_Speed<=0)
  {
    cancelTimer(msTVehSpeedDown);
    @Vehicle_Control::Veh_Speed=0;
  }
}

on timer msTEngSpeedDown
{
  @Vehicle_Control::Eng_Speed=@Vehicle_Control::Eng_Speed-40;
  setTimer(this,50);
  if(@Vehicle_Control::Eng_Speed<=0)
  {
    cancelTimer(msTEngSpeedDown);
    @Vehicle_Control::Eng_Speed=0;
  }
}

书上的程序,下图红框的判断觉得有点问题,做了修改
在这里插入图片描述

六、Automation Sequences

利用Automation Sequences,可以方便地实现system variables、environment variables或者signals的变化事件序列,同时也可以检查、判断当前变量或信号的值。在本实例中,创建一个名为Vehicle的Automation Sequences,其主要功能是改变变量的值来触发特定的功能。

在CANoe主界面,选择Simulation→Automation,在弹出的菜单Visual Sequences下空白处单击鼠标右键并在菜单中选择New,输入该Sequences的名称为Vehicle。单击工具栏中的Edit图标,开始编辑该Sequence。按照下表参数来设定:
在这里插入图片描述
在工具栏中单击RepeatSequence periodically图标在这里插入图片描述和Start Sequence on measurement start图标在这里插入图片描述使Vehicle自动序列能够在开始测量后自动循环运行。

七、分析窗口设置

1.Graphics窗口
在 CANoe 主界面选择 Analysis→Graphics→New GraphicWindow,输入名称为Signal Observe。该窗口左边信号列表栏中单
击选择Add Signals,在弹出的窗口中选择信号KeyState,同样地加入信号VehicleLight和VehicleSpeed。在Signal Observe窗口工具栏中单击Select y-axis view图标在这里插入图片描述 ,在下拉表中选中Show All Y-Axis,这样上面添加的三个Signal就将显示在同一窗口中,如下图所示:
在这里插入图片描述
鼠标滚轮可以放大缩小坐标刻度,调整好坐标,方便后续观察。

2、State Tracker窗口

在 CANoe 菜 单 栏 中 选 择 Analysis→State Tracker→New State Tracker Window,输入名称为Signal State。在该窗口左边信号列表栏中单击鼠标右键并在菜单中选择Add Variables,添加系统变量Vehicle_Control中的Gear和Brake。在该窗口左边信号列表栏中单击鼠标右键并在菜单中选择Add Database Objects→Signals,添加信号VehicleLight ,如下图所示:
在这里插入图片描述
3、Data窗口
Data窗口中可以添加信号和系统变量,此例添加了Driver、EngSpeed、EngTemp、KeyState和VehicleSpeed五个信号,以及Left_Turn_Enable、
Right_Turn_Enable、Key_State和Gear_Status四个系统变量,如下图所示:
在这里插入图片描述

八、Trace窗口与Logging

Trace窗口帮助用户实时查看和分析总线上的数据。Logging记录下了整个仿真过程中的数据,在大数据量或长时间的测试情况下,使得用户可以在离线状态下查看总线的活动情况,同时,Logging功能记录的数据可以在CANoe中进行回放,对于总线上问题的复现起到了十分重要的作用。

在CANoe主界面下,进入Analysis选项卡,在Measurement Setup窗口中设置Trace窗口、Logging窗口。

1、右键Logging,选择Name,更名为CAN_Logging。设置Configuration,设置参数如下:
在这里插入图片描述
Logging右侧箭头指向一个Logging文件加,可以设置Logging文件保存位置。

2、创建CAN_Trace的Trace模块。

九、Desktop布局

点击下图红箭头所指,可以新增Desktop。
在这里插入图片描述
1、添加一个名为CAN的Desktop布局,将Control和IPC两个面板加进去,并设定为MDI Windows模式。同时添加Write窗口和Test Automation Sequences窗口,都设定为MDI Windows模式。布局好后效果图如下:
在这里插入图片描述

2、在Analysis的Desktop布局中添加Data、CAN Statistics、Signal State Tracker和Signal Observe等窗口
在这里插入图片描述
3、在Configuration的Desktop布局视图中保留Simulation Setup和Measurement Setup窗口,如下图所示:
在这里插入图片描述
4、在Trace的Desktop布局视图中保留Write、CAN Trace和Trace窗口,如下图所示:
在这里插入图片描述

十、工程运行测试

回到CANoe的Home界面,设置为仿真环境,点击Start开始仿真测试,结果如下: