自学Canoe-Canoe从入门到精通第13章

第13章 仿真工程开发进阶I——CAN+LIN仿真

13.1 工程实例简介

由于LIN总线的低成本、易实现等优点,在安全性和实时性要求不高的模块中得到了广泛应用,如车窗控制、座椅调节和雨刮控制等。

13.1.1网络拓扑图

在这里插入图片描述
在网络拓扑图中,网关与座椅记忆控制模块(Seat ControlMemory Module, SCMM)之间通过LIN总线通信,其中,网关作为Master节点,而座椅记忆控制模块则作为Slave节点。
LIN总线的仿真采用LIN 2.2协议,总线波特率为19.200kb/s。
因为节点HU发出的座椅调节报文通过节点Gateway直接转发,节点SCMM反馈过来的当前座椅位置也是节点Gateway发送给节点HU,所以对于节点SCMM来说,只需要关心节点Gateway发过来的数据。
实例中将把与节点HU座椅相关的部分功能当成节点Gateway的一部分来仿真,影音CAN不再单独需要,节点HU用虚线表示,这样拓扑图简化如图
在这里插入图片描述

13.1.2 实现功能

(1)座椅位置的手动改变:通过控制面板改变LDF文件里面定义的座椅操作Signal的值(模拟在节点HU屏幕上设置座椅前后、左右、上下以及头部靠垫的位置)。
(2)根据Driver信息改变座椅设置:节点Gateway将当前Driver信息的CAN报文转为LIN报文,节点SCMM在接收到该报文后,自动调用预存储的Driver座椅位置信息。
(3)显示座椅位置:通过显示面板指示座椅的位置信息(模拟节点HU屏幕上座椅位置的动态变化)。

13.2 工程实现

新建工程名
在这里插入图片描述
另存工程名
在这里插入图片描述

13.2.1添加LIN总线支持

之前的仿真实例只支持Can总线,需要通过修改相关配置来支持LIN。在CANoe主界面通过Hardware→Channel Usage,将LIN通道由0改为1
在这里插入图片描述
在这里插入图片描述
添加完毕后,将在Simulation Setup窗口右边的系统视图中的Networks下面出现LIN Networks。
在这里插入图片描述
添加LIN网络
在这里插入图片描述
在这里插入图片描述
单击SimulationSetup窗口左下角的网络切换书签LIN,切换到LIN网络视图,可以看到一个没有任何节点的LIN网络
在这里插入图片描述
在这里插入图片描述

13.2.2 数据库LDF文件设计与导入

与CAN总线类似,LIN总线也需要一个数据库文件来管理相关的报文和信号。CANoe利用这个数据库,可以清晰地解析出LIN总线上的数据信息。
在CANoe主界面的Tools功能区单击LDF Explorer,可以打开LDF编辑器Vector LDF Explorer Pro。在编辑器的工具栏中选择New File新建一个LDF 2.2版本的文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
更改LIN_Network名称为Seatdb , 波 特 率 保 持 19.200kb/s 不 变 。
将Node/Frame选项卡中的LIN_Master更名为Gateway,将Slave_1更名为SCMM。
在这里插入图片描述
更改Slave节点的属性
在这里插入图片描述

1.创建一条LIN报文,并命名为Seat_Setting。

Length为1B, ID为0,在Publisher中选择节点Gateway。
在这里插入图片描述
在这里插入图片描述
在报文中添加8个信号。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以查看报文中Signal的排列状况。在bit排列视图中,将光标停留在不同的bit位置,可以查看出该bit所对应的信号。
在这里插入图片描述

2.创建一条LIN报文,并命名为Driver_Info

再创建一个名为Driver_Info的报文,Length为1B, ID为1,在Publisher中选择节点Gateway。该报文包含一条Signal Name为DriverID的信号.
在这里插入图片描述

3.创建一条LIN报文,并命名为Seat_Position

再创建一个名为Seat_Position的报文,Length为2B, ID为2,在Publisher中选择节点SCMM。
在这里插入图片描述

4.创建ScheduleTable 来 规 定 每 条 报 文 的 发 送 周 期

新建table
在这里插入图片描述
在这里插入图片描述
之 前 创 建 的 Seat_Setting 、Driver_Info和Seat_Position三条报文拖曳到Table_0下面
在这里插入图片描述
在Table_0下面设置当前报文的发送周期,在右侧属性窗口中将每条报文的Delay time都设置成30ms。

5.仿真工程中添加LDF

LDF文件创建完毕后,读者可以将LDF文件导入到仿真工程中。与CAN总线数据库导入相似,在Simulation Setup窗口的系统视图中,鼠标右键单击LIN总线下的Database选择Import Wizard,选择Seatdb.ldf文件并添加SCMM和Gateway两个节点。
可以看到,在LDF文件中创建的两个节点Seat和Gateway已经被添加进LIN总线中。这里需要指出的是,对于Gateway这个节点,由于在CAN总线中也存在节点Gateway,因此该节点有个堆叠效果,表示该节点同时挂在两条不同的总线上。
在这里插入图片描述
在这里插入图片描述

13.2.3 添加环境变量

使用环境变量(Environment Variable)来显示当前座椅位置以及指示调节座椅按键是否有效。利用EmptyTemplate.dbc模板来创建一个只含有EnvironmentVariable的database。
在这里插入图片描述
在这里插入图片描述
在Simulation Setup窗口的系 统 视 图 中 , 将 Env_LINGateway.dbc 添 加 到 LINNetwork→LIN→Database下面。
在这里插入图片描述

13.2.4 面板设计

添加两个面板,一个用于实现可视化的座椅位置显示,另一个用于控制座椅位置的调节。这里将这两个面板分别命名为Seat Display和Seat Control。

1.Panel:Seat Display

此面板模拟HU显示屏端座椅位置的动态变化,同时显示与之对应的LIN总线上报文Seat_Setting中信号的状态。
在这里插入图片描述

2.Panel:Seat Control

此面板模拟节点HU显示屏端控制座椅位置的操作,以及节点BCM端信号driver ID的变化和切换操作。在Seat Control Elements Group里面添加8个Switch/Indicator并关联到创建的LINSignal信号,分别用Static Text控件来添加文字说明。
在这里插入图片描述

13.2.5 CAPL实现

本实例中,使用8个环境变量显示收到的LIN报文中8个信号的状态,同时又使用4个环境变量对应一个37帧图片seat.jpg中不同的帧来表征不同的座椅位置。
在这里插入图片描述

1.Seat.Can

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

variables
{
  // driver1 座椅初始位置
  int horipos1 = 5,vertpos1 = 10,backpos1 = 17,headpos1 = 28;
  // driver2 座椅初始位置
  int horipos2 = 2,vertpos2 = 13,backpos2 = 21,headpos2 = 26;
}

//处理信号DriverID的变化
on signal DriverID
{

  if($Driver_Info::DriverID==1)
  {
    driver2_pos();
  }
  else
  {
    driver1_pos(); 
  }
}

// 切换座椅位置到Driver2,更新LIN报文Seat_Position中的信号
void driver2_pos(void)
{
  $Vertical_Position=vertpos2-8;
  $Horizontal_Position=horipos2;
  $SeatBack_Position=backpos2-16;
  $Head_Position=headpos2-26; 
}

// 切换座椅位置到Driver1,更新LIN报文Seat_Position中的信号
void driver1_pos(void)
{
  $Vertical_Position=vertpos1-8;
  $Horizontal_Position=horipos1;
  $SeatBack_Position=backpos1-16;
  $Head_Position=headpos1-26; 
}

// 处理接收LIN报文Seat_Setting
on linFrame Seat_Setting
{
  // 赋值给环境变量
  putValue(EnvSeat_back_Dsp,$Seat_back);
  putValue(EnvSeat_forward_Dsp,$Seat_forward);
  putValue(EnvSeat_up_Dsp,$Seat_up);
  putValue(EnvSeat_down_Dsp,$Seat_down);
  putValue(EnvSeatback_back_Dsp,$Seatback_back);
  putValue(EnvSeatback_forward_Dsp,$Seatback_forward);
  putValue(EnvSeathead_up_Dsp,$Head_up);
  putValue(EnvSeathead_down_Dsp,$Head_down);
  
  // 更新返回LIN报文Seat_Postion
   if($DriverID==1)
  {
     Driver2_Adjust();
  }
  else
  {
     Driver1_Adjust();
  }
}

// Driver1:更新座椅位置并更新LIN报文Seat_Position
void Driver1_Adjust(void)
{
  //更新水平位置
  if (horipos1 < 7 && $Seat_back)
  {
    horipos1 = horipos1 + 1;
  }
  if (horipos1 > 0 && $Seat_forward)
  {
    horipos1 = horipos1 - 1;
  }
    
  //更新垂直位置
  if (vertpos1 < 15 && $Seat_up)
  {
    vertpos1 = vertpos1 + 1;
  }
  if (vertpos1 > 8 && $Seat_down)
  {
    vertpos1 = vertpos1 - 1;
  }
  
  //更新座椅靠背位置
  if (backpos1 < 25 && $Seatback_back)
  {
    backpos1 = backpos1 + 1;
  }
  if (backpos1 > 16 && $Seatback_forward)
  {
    backpos1 = backpos1 - 1;
  }
   
  //更新座椅靠枕位置
  if(headpos1 < 29 && $Head_up)
  {
    headpos1 = headpos1 + 1;
  }
  if(headpos1 > 26 && $Head_down)
  {
    headpos1 = headpos1 - 1;
  } 
  
  // 更新LIN报文Seat_Position
  $Vertical_Position=vertpos1-8;
  $Horizontal_Position=horipos1;
  $SeatBack_Position=backpos1-16;
  $Head_Position=headpos1-26; 
}

// Driver1:更新座椅位置并更新LIN报文Seat_Position
void Driver2_Adjust(void)
{
 //更新水平位置
  if (horipos2 < 7 && $Seat_back)
  {
    horipos2 = horipos2 + 1;
  }
  if (horipos2 > 0 && $Seat_forward)
  {
    horipos2 = horipos2 - 1;
  }
    
   //更新垂直位置
  if (vertpos2 < 15 && $Seat_up)
  {
    vertpos2 = vertpos2 + 1;
  }
  if (vertpos2 > 8 && $Seat_down)
  {
    vertpos2 = vertpos2 - 1;
  }
  
 //更新座椅靠背位置
  if (backpos2 < 25 && $Seatback_back)
  {
    backpos2 = backpos2 + 1;
  }
  if (backpos2 > 16 && $Seatback_forward)
  {
    backpos2 = backpos2 - 1;
  }
   
  //更新座椅靠枕位置
  if(headpos2 < 29 && $Head_up)
  {
    headpos2 = headpos2 + 1;
  }
  if(headpos2 > 26 && $Head_down)
  {
    headpos2 = headpos2 - 1;
  } 
  
  // 更新信号到报文Seat Position
  $Vertical_Position=vertpos2-8;
  $Horizontal_Position=horipos2;
  $SeatBack_Position=backpos2-16;
  $Head_Position=headpos2-26; 
}`
2.更新Gateway代码

更新LIN总线发送的控制,以及Gateway上CAN信号触发LIN信号的变化,以及LIN信号更新环境变量的函数。

/*@!Encoding:1252*/
includes
{
  //To add the head files
}

variables
{
  msTimer msTVehSpeedDown; //define the timer(ms) for Vehicle Speed down
  msTimer msTEngSpeedDown; //define the timer(ms) for Engine Speed down
  dword WritePage;
  int busflag=0; //current bus status: 0 - Deactivate CANoe IL ; 1 - Activate CANoe IL 
}

on preStart
{
  ILControlInit(); //Initialize CANoe IL 
  ILControlStop(); //Deactivate CANoe IL 
  LINStopScheduler();// Stop LIN scheduler before measurement starts
  //Write simulation information in write window
  writeLineEx(WritePage,1,"--------This demo demonstrated the CAN bus simulation!!--------"); 
  writeLineEx(0,1,"Press <1> to start/stop CAN_logging");  
}

on key '1'
{
  int logflag;

  if(logflag==0)
  {
    logflag=1;
    write("CAN logging starts");
    //start logging Logging CAN with a pretrigger with 500ms
    startlogging("CAN_Logging",500);
  }
  else 
  {
    logflag=0;
    write("CAN logging ends");
    //stop logging Logging CAN with a posttriggre with 1000ms
    stoplogging("CAN_Logging",1000);
  }   
}


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

on sysvar Vehicle_Control::Gear
{
  $Gear=@this;      //Change Gear status based on user operation
}

void EngineData_Init(void)
{
  //Initialize the data of Engine
  $VehicleSpeed=0;
  $EngSpeed=0;
  $EngTemp=0;
  $PetrolLevel=0;
}

on signal_update KeyState
{
  if(this==0)
  {
    EngineData_Init();   //Init engine data based on KeyState
  }
  if(this>0)
  {
    $PetrolLevel=255;    //Init PetrolLevel based on KeyState
  }
}

on sysvar_update Vehicle_Control::Eng_Speed     
{
  //Engine speed only available when Key is ON
  if(@Vehicle_Key::Key_State==2)
  {
    $EngineData::EngSpeed=@this;
  }
  else
  {
    $EngineData::EngSpeed=0;
  }
}

on sysvar_update Vehicle_Control::Veh_Speed
{
  //Vehicle speed only available when Gear is Drive and Key is ON
  if((@Vehicle_Control::Gear==3)&&(@Vehicle_Key::Key_State==2))
  {
    $VehicleData::VehicleSpeed=@this;
  }
  else
  {
    $VehicleData::VehicleSpeed=0;
  }
}

//only for simulation
on sysvar_update Vehicle_Control::Speed_Up  //Speed up when sysvar speed_up enabled
{
  if($EngTemp<90)
  {
    $EngTemp=@this*1.5;
  }
  else
  {
    $EngTemp=90;
  }
  if($PetrolLevel<255)
  {
    $PetrolLevel=@this*8.5;
  }
  else
  {
    $PetrolLevel=255;
  }
  @Vehicle_Control::Veh_Speed=@this;
  @Vehicle_Control::Eng_Speed=@this*40;
  if(@this>120)
  {
    @this=60;
  }
}

on sysvar Vehicle_Control::Brake    //Speed down when Brake is enable
{
  int i;
  if(@this==1)
  {
    $GearLock=0;
    setTimer(msTVehSpeedDown,50);
    setTimer(msTEngSpeedDown,50);
  }
  else
  {
    $GearLock=1;
    cancelTimer(msTVehSpeedDown);
    cancelTimer(msTEngSpeedDown);
  }
}

on timer msTVehSpeedDown      //Implement speed down function
{
  @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    //Implement engine speed down function
{
  @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;    
  }
}

// to process the CAN Signal Driver_Info::Driver Update
on signal_update Driver
{
  $Driver_Info::DriverID = $Driver;
}

//To process the receiving of LIN Frame of Seat_Position
on linFrame Seat_Position
{
  @EnvSeatvert_Dsp=$Vertical_Position+8;
  @EnvSeathori_Dsp=$Horizontal_Position;
  @EnvSeatback_Dsp=$SeatBack_Position+16;
  @EnvSeathead_Dsp=$Head_Position+26; 
}

13.2.6 Trace窗口与Logging

在这里插入图片描述

13.2.7 设置Desktop布局

1.添加LIN

添加LIN的Desktop以后,可以将Seat Control和Seat Display两个面板添加到该Desktop中。为了便于观察LIN总线上的活动,可以同时添加Write窗口和LIN_Trace窗口
在这里插入图片描述

2.修改Trace

在Trace布局中可以将Trace窗口移除,将LIN_Trace窗口添加到布局中,这样既可以在CAN_Trace窗口中观察CAN上的总线信息,也可以在LIN_Trace窗口查看LIN的报文和变量等信息。
在这里插入图片描述

13.3 工程运行测试

操作LIN的面板前需要在CAN的Desktop布局中操作Control面板,钥匙解锁并将引擎钥匙置于RUN状态。节点SCMM会根据车钥匙上驾驶员(Car_Driver)信息的不同,调整座椅至相对应的位置。在SeatControl面板中,读者可以单击不同的箭头按钮来调节座椅位置,同时在Seat Display窗口中显示出座椅的位置,并用LED指示当前调节的方向。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值