按照仿真工程流程,和功能需求,分为以下步骤:创建仿真工程,DBC文件设计与导入,系统变量,面板设计,CAPL代码实现,自动序列,分析窗口(Graphics,State Tracker窗口,Data窗口),Trace窗口与Logging,Desktop布局,工程运行测试。下面逐一进行
目录(剩余步骤请跳转https://blog.csdn.net/lamanchas/article/details/122331103)
1. 创建仿真工程
2.DBC文件设计,导入
2.1 模板创建DBC
2.2通用属性设置
2.3 Node节点设置
2.4 添加报文
2.5 添加ValueTable
2.6 添加信号,关联message、ValueTable
2.8 配置节点的报文接收
2.9 将数据库文件导入工程
2.10 导入全部节点
3. 创建系统变量
4 面板设计
4.1 控制面板(模拟BCM,Gateway相关操作)
4.2 显示面板 IPC面板
5 CAPL代码
5.1 IPC代码
5.2 BCM代码
5.3 GateWay代码
打开CANoe,选择File→New,在可选的模板中选择CAN500kBaud 1ch(波特率为500kBaud,1通道)。
保存该工程文件,取名为 Vehicle System CAN,保存在文件夹Vehicle_System_Simulation下。在该文件夹下创建以下几个子文件夹:CANdb、Logging、Nodes和Panels等。
按照ECU的正常开发流程,DBC文件一般由整车厂提供,只有极少数情况下需要ECU供应商根据Signal Matrix来自行创建DBC文件。
在此处根据信号矩阵创建。
以 Vector_IL_Basic Template 为模板创建一个名称为VehicleSystem的CAN数据库。该网络的Networks name 也将被定义为VehicleSystem,并将它的Protocal设置为CAN。
根据vehicleSystem数据库的Attribute列表来设定
本实例有中三个ECU节点,NodeLayerModules均采用CANoeILNLVector.dll来提供周 期性和事件驱动的报文发送方式。为了增加DBC文档的可读性,节点的Comment中可以 添加相关说明或者节点名称的英文全称,如表12.2所示。
具体的值说明如下图:
Cluster_Info报文的信号(IPC发出)
Driver_Info报文信号(BCM发出)
Ignition_Info报文信号(BCM发出)
Light_Info报文信号(BCM发出)
Lock_Info报文信号(BCM发出)
EngineData报文信号(GateWay发出)
VehicleData报文信号(Gateway发出)
Gear_Info报文信号(Gateway发出)
信号Signal与message关联完毕后,配置节点的报文接收情况:
示例:Cluster——Gear_Status
同样的,按下边的配置其余系统变量
4.1.1 钥匙模块——图片
图片地址: C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\LIN\LINGateway\Panels\Bitmaps\key.bmp
4.1.1 钥匙模块——锁车开关
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\LIN\LINGateway\Panels\Bitmaps\CarClosed_2.bmp
4.1.1 钥匙模块——开锁开关
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\LIN\LINGateway\Panels\Bitmaps\CarOpen_2.bmp
4.1.1钥匙模块—— Driver1,Driver2
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\LIN\LINGateway\Panels\Bitmaps\ID1_2.bmp
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\LIN\LINGateway\Panels\Bitmaps\ID2_2.bmp
4.1.2 点火模块-GroupBox
4.1.2 点火模块-文本模块
4.1.2 点火模块-钥匙孔
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\CANopen\CANopenGateway\BITMAPS\Ignit_4.bmp
4.1.3 档位模块-GroupBox
4.1.3 档位模块-档位控制
4.1.3 档位模块-档位文本(4个)
以D为例:
4.1.4 刹车模块-GroupBox
4.1.4 刹车模块-刹车控制
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\FlexRay\Scope\FlexRayBitMaskAnalysis\Panels\BITMAPS\brake.bmp
4.1.5 车速模块-GroupBox
4.1.5 车速模块-车速控制
4.1.6 引擎速度模块-GroupBox
4.1.6 引擎速度模块-控制
4.1.7 警示灯模块 - 静态文本
4.1.7 警示灯模块 - 警示信号展示\控制
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\CANopen\CANopenGateway\BITMAPS\bmp_2\Warnb_2.bmp
4.1.8转向灯模块 - 左右转向 文本
4.1.8转向灯模块 - 展示、控制
button behaviour要设置为False:
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\CANopen\CANopenGateway\BITMAPS\bmp_2\Blkl_2.bmp
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\CANopen\CANopenGateway\BITMAPS\bmp_2\Blkr_2.bmp
4.2.1 背景图-picture box
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\IO_HIL\VTSystem\User_FPGA\VT7820Demo\Panel\Bitmaps\DashboardCombi.bmp
4.2.2 时间展示
4.2.3 档位展示
4.2.4 车速数值展示
数值展示:
文字(km/h)
4.2.5 转向灯展示--左、右
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\Programming\Bitmap_Library\Automotive\Indicator_2States\lGreenBlinkerLeft_2.bmp
C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\Programming\Bitmap_Library\Automotive\Indicator_2States\lGreenBlinkerRight_2.bmp
4.2.6 引擎温度展示
4.2.7 引擎速度展示
4.2.8 车辆速度展示——仪表盘
4.2.9 油量展示——仪表盘
在本实例中,采用仿真模式来测试IPC,实际测试中IPC为待测ECU,因此需要将该节点设置为Inactive状态。(节点是Inactive状态,为什么设置总线状态busflag为0?全局变量busflag带表IPC的状态,而不是外部总线的状态吧)
在IPC.can中,CAPL主要实现了报文的发送机制。当车在锁车状态时,报文不能通过IL层发送,解锁后周期性报文便可以通过IL层发送出去。(IL层是什么?周期性报文是由谁发送的?)
主要使用了ILControlStart)和ILControlStopO两个函数,实现了节点与总线的连接。
/*@!Encoding:936*/
includes
{
}
variables
{
int busflag = 0;
//总线状态:0-Deactivate CANoe 1L;1-Activate CANoe 1L
}
on preStart
{
ILControlInit();//初始化CANoe IL
ILControlStop();//禁止CANoe IL报文发送
}
on signal_update LockStatus
{
if(this!=busflag)
{
if(this==1)
{
ILControlStart();//激活CANoe IL报文发送
}
else if(this == 0)
{
ILControlStop();//禁止CANoe IL报文发送
}
busflag = this;
}
}
//在PIC上显示档位信息
on signal_update Gear
{
@Cluster::Gear_Status = this;
}
/*@!Encoding:936*/
includes
{
}
variables
{
msTimer msTcrank;//定义一个毫秒定时器,用于Crank延时
msTimer msTIL;//用于关闭IL
int flashPeriod = 500;//Hazards跳闪周期
//转向灯状态:0-both off、1- left flash
//2-Right Flash,3- Hazards on
int TurnLightStatus;
msTimer msTleftflash,msTrightflash;//实现左右转向
message Driver_Info Msgdriver;//定义报文用于发送Driver信息
}
on preStart
{
ILControlInit();//初始化CANoe IL
ILControlStop();//禁止CANoe IL报文发送
}
//处理钥匙位置
on sysvar_update Vehicle_Key::Key_State
{
$Ignition_Info::KeyState = @this;
if(@this == 3)
{
@Vehicle_Control::Speed_Up =0;
setTimer(msTcrank,800);//模拟800ms延时
}
}
//通过定时器模拟800ms后钥匙自动回到Run位置
on timer msTcrank
{
$KeyState = 2;
@sysvar::Vehicle_Key::Key_State =2;
}
//处理Driver ID改变以后,更新报文并发送
on sysvar_update Vehicle_Key::Car_Driver
{
//根据系统变量,更新报文
if(@this==1)
{
Msgdriver.byte(0) = 0;
}
else if(@this == 2)
{
Msgdriver.byte(0)=0x1;
}
output(Msgdriver);
}
//处理unlock car事件
on sysvar_update Vehicle_Key::Unlock_Car
{
if(@this==1)
{
ILControlStart();//激活CANoe IL发送报文
$LockStatus=1;
@Vehicle_Key::Car_Driver=2;//driver 2 为初始值
}
}
//处理Lock Car 事件
on sysvar_update Vehicle_Key::Lock_Car
{
if(@this==1)
{
$LockStatus=0;
setTimer(msTIL,1500);//等待1.5s,确保其他模块关闭IL
}
}
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(msTleftflash);
cancelTimer(msTrightflash);
$LightStatus=0;
@Cluster::Left_Turn_Indicator=0;
@Cluster::Right_Turn_Indicator=0;
break;
}
}
}
/*@!Encoding:936*/
includes
{
}
variables
{
msTimer msTVehSpeedDown;
msTimer msTEngSpeedDown;
Timer sTVehSpeedUp;
dword WritePage;
int busflag=0;//0 deactive;1 active
}
on preStart
{
ILControlInit();//初始化CANoeIL
ILControlStop();//禁止报文发送
writeLineEx(WritePage,1,"----- This demo demonstrated the CAN bus simulation!!---");
//write窗口输出项目仿真提示信息
writeLineEx(0,1,"Press <1> to start/stop CAN_Logging");
//write窗口输出logging提示信息
}
//控制Logging_CAN的开始与结束
on key '1'
{
int flag;
if(flag==0)
{
flag=1;
write("CAN logging starts");
startLogging("CAN_Logging",500);//pretrigger事件为500ms
}
else
{
flag =0;
write("CAN logging ends");
//停止记录设置posttrigger事件为1000ms
stopLogging("CAN_logging",1000);
}
}
//控制总线报文的开始与结束
on signal_update LockStatus
{
if(this!=busflag)
{
if(this==1)
{
ILControlStart();
}
else if(this==0)
{
ILControlStop();
}
busflag=this;
}
}
//设置档位信息
//也需要监听lock吧,如果车没有unlock,那么不能换挡
//引擎呢?发动后,才可换挡
//更详细的——也需要监听刹车信号?
//大多自动挡配置有换挡锁止功能,P 挡切换至其他挡位时需要强制踩刹车,
//切换至P档时,需要强制减速
//如果强行挂入,可能会损害变速箱。
//行驶状态:行驶过程中,行进档之间切换是不需要踩刹车的,比如D档、S档、L档之间
//
on sysvar Vehicle_Control::Gear
{
if(busflag==1 && @Vehicle_Key::Key_State==2){
$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; //有问题,直接设置成了255,后续speedup对petrolLevel的变化不起作用
//油量,油耗?看代码分不出来
}
}
//处理系统变量更新-Eng_Speed
on sysvar_update Vehicle_Control::Eng_Speed
{
//Engine speed只在Key为On时有效
if(@Vehicle_Key::Key_State==2)
{
$EngineData::EngSpeed=@this;
}
else
{
$EngineData::EngSpeed=0;
}
}
//处理系统变量更新-Veh_Speed
on sysvar_update Vehicle_Control::Veh_Speed
{
//key为on,drive档位
if((@Vehicle_Control::Gear==3)&&(@Vehicle_Key::Key_State==2))
{
$VehicleData::VehicleSpeed=@this;
}
else
{
$VehicleData::VehicleSpeed=0;
}
}
//Speed_Up在BCM.can中当钥匙状态为2crank时,初始化为0,
//此后,没有地方再控制Speed_Up的变化,因此油温,油量按原来的程序也没有变化
//根据 $VehicleSpeed=@this;推断,Speed_Up是车速控制信息
// 推断 speed_up类似踩油门动作-----简化理解为加速度
//推断1×:可以在Control面板增加了油门,绑定speed_up,其他设置与brake一致,但这个speed_up的值不能像刹车那样设置为0,1;
//推断2√:系统变量设置时,speed_up的 max=200,所以应该 设置为与车速控制类似的控件
///模拟实现车速、引擎转速、油温、油量的动态变化
on sysvar_update Vehicle_Control::Speed_Up
{
if($EngTemp<90)
{
$EngTemp=@this*1.5;//油温变化因子为1.5
}
else
{
$EngTemp=90;
}
if($PetrolLevel<255)
{
$PetrolLevel=@this*8.5;//油量变化因子
}
else
{
$PetrolLevel=255;
}
//$VehicleSpeed=@VehicleSpeed;//原始代码---不正确,应该是对应的函数
$EngSpeed=@this*40;//引擎转速变化因子
if(@this>120)
{
@this=60;
}
//新增代码,picoasis,2022.1.18,加速度控制
if (@this>0)
{
setTimer(sTVehSpeedUp,1);//按秒加速
}
//新增代码,picoasis,2022.1.18,加速度控制
if(@this==0){
cancelTimer(sTVehSpeedUp);
}
}
//新增代码,picoasis,2022.1.18,加速度控制
on timer sTVehSpeedUp
{
//Vt=Vo+a*t
//km/h =km/h +km/h2 *1s = km/h +km/h2 *(1/3600)h
//@Vehicle_Control::Veh_Speed += (1/3600)*@Vehicle_Control::Speed_Up;//--应该这样算,但是效果不明显,也可能是整型数据在除法运算时,出现了类型转换问题。。;先用下面的计算式子,看结果
@Vehicle_Control::Veh_Speed += @Vehicle_Control::Speed_Up;
// write('%f',@Vehicle_Control::Veh_Speed);
setTimer(this,1);
if(@Vehicle_Control::Veh_Speed>=300)
{
cancelTimer(msTVehSpeedDown);
@Vehicle_Control::Veh_Speed=300;
}
}
on sysvar Vehicle_Control::Brake
{
int i;
if(@this==1)
{
$Gear_Lock=0;
setTimer(msTVehSpeedDown,20);
setTimer(msTEngSpeedDown,2);
}
else
{
$Gear_Lock=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;
}
}
未完待续,跳转至--https://blog.csdn.net/lamanchas/article/details/122331103