最近在学习CANoe,记录下学习路程,方便后续查看。参考《CANoe开发从入门到精通》和CANoe软件内附带的Easy例程,一步步去实现这个例程,稍加优化。
一、创建仿真工程
打开CANoe 16 SP4进入主界面,单击File→New可以看到CANoe提供的工程模板,如下图所示:
双击选择模板CAN 500kBaud 1ch,将生成一个空白的支持单通道的CAN总线仿真工程。将该工程命名为Demo.cfg,并将其保存在文件夹Demo下。Demo下面分别创建文件夹CANdb、Panels和Nodes。
二、总线数据库设计
1、在CANoe主界面,单击Tools,选择CANdb++ Editor,单击进入Vector CANdb++ Editor界面
2、选择File→Create Database命令新建数据库文件,此时可以查
看到软件自带的数据库模板,如下图所示:
选择Vector_IL_Basic Template.dbc作为模板,创建一个文件名为Demo.dbc的数据库,并将其保存到上面已创建的仿真项目Demo的文件夹CANdb中,如下图所示:
3、右击Networks下的Demo,选择Edit Network进入总线属性编辑,如下图所示:
处将Definition中的Protocol属性改为CAN总线。确定后退出。
4、右击Network Nodes,在快捷菜单中选择New,新建一个Name为Engine的网络节点,Address设为0x1,如下图所示。
同样的方法,再创建一个名称为Light的节点和一个名称为Display的节点,并保存。如下图所示:
可以看到当定义了一个网络节点后,CANdb++会自动添加一个相同名字的ECU,并且二者之间是相互关联的。(在CAN数据库中并不能直接创建ECU, CANdb++会在创建网络节点的同时,创建一个名称相同的ECU)
5、右击Message选择New,创建一个名为EngineState的报文,选择标准CAN(CAN Standard)报文,标识符为(ID)0x123,数据长度(DLC)为2,如下图所示:
在Transmitters选项卡下单击Add按钮,将Engine添加到发送节点。在
Transmitters设定界面中指定了该报文由节点Engine发送,如下图所示:
用同样的方法,创建名为LightState的报文,选择标准CAN(CAN Standard)报文,标识符(ID)为0x321,数据长度(DLC)为1,发送节点为Light。
创建完成后,在左边导航区中,EngineState与LightState报文已经被添加到节点Engine和Light下,在右边栏中显示了这两个报文的属性,如下图所示:
6、右击Signal选择New,创建信号EngineSpeed,在Defintion选项卡下设置Length为15b,Byte Order为Intel,Unit为r.p.m.,Value Type为Signed, Maximum为5000,其他设置可以使用默认值,如下图所示:
在Messages选项卡,点击Add,将该信号关联到报文EngineState中,如下图所示:
用相同方法,按下表属性,添加信号OnOff、FlashLight和HeadLight。
7、单击左侧栏中的Network Nodes,右击Display,选择Edit Node,在弹出的对话框中,选择Mapped Rx Sig.选项卡,单击Add按钮,将信号EngineSpeed添加到其中,如下图所示:
同样的方法,设置节点Engine和Light的各个信号,下图为设置完毕后的效果图:
同时注意下,上图右边各信号的Startbit值,因为EngineSpeed和OnOff是组合一起两个字节,FlashLight和HeadLight在一个字节里的不同位。如果因为加入先后顺序导致值与上图不一致的,可直接单击Startbit值修改。
8、在左侧Messages下双击之前创建的EngineState报文并切换到Attributes选项卡,将GenMsgCycleTime 改为100 , 此报文的周期就被改为100 ms, 同时需要将此报文的GenMsgSendType(报文发送类型)相应地改为Cyclic(周期性的),修改完毕如下图所示:
同样地,需要将LightState报文也改为周期性报文,周期为100ms。
9、在CANdb++工具栏上,单击Value Tables图标
进入Value Tables界面,在空白处右击,选择New,创建一个名为VtSig_OnOff的Value Table,在Value Descriptions选项卡中,单击Add按钮,新增两个值,如下图所示:
10、Value Table创建完毕后,可以将对应的信号或环境变量关联到数值表。在左侧Signals双击信号 OnOff ,在 Definition 选 项 卡 中 将 Value Table 选 择 为 上 面 创 建 的VtSig_OnOff,如下图所示:
到此,总线数据库设计完成。
11、返回CANoe主界面,在Simulation Setup的系统视图中,右击Database选择Import Wizard命令,在弹出的对话框中选择Demo数据库,并将节点Display、Light和Engine添加到Assigned nodes中,如下图所示:
单击下一步按钮直到出现完成按钮,即可完成Demo数据库的导入,最终Simulation
Setup窗口中可以看到数据库中创建的Display、Light和Engine三个仿真节点,如下图所示:
至此,数据库已经被成功创建和导入。
三、设置系统变量
1、在CANoe主界面中选择Environment→System Variables,如下图所示:
2、在左上侧空白窗口中单击鼠标右键选择New ,新建一个Name为EngineStateSwitch的系统变量,Namespace为Engine,设置初始值、最大最小值,如下图:
3、使用同样的方法创建其他两个系统变量:EngineSpeedDspMeter和EngineSpeedEntry,创建完毕后如下图所示:
4、使用同样的方法创建Namespace为Lights的两个系统变量HazardLightsSwitch和LightDisplay,创建完毕后如下图所示:
至此,系统变量设置完成。
四、创建仿真Panel
1、在CANoe主菜单上选择Tools→Panel Designer进入面板设计界面。
2、设计控制界面
2.1、在Panel Designer界面上选择File→New→Panel打开一个新的面板,默认名为Panel1,如下图所示:
2.2、右侧找到Toolbox选项卡打开,里面有所有的控件。如下图所示:
2.3、添加2个Group Box到左侧Panel内,调整好大小,并通过右侧Toolbox旁的Properties选项卡设置Text为Engine和Light。面板的布局效果如下图所示:
2.4、添加一个Switch/Indicator控件到Engine组合框内,调整好大小。并在右侧Properties选项卡设置控件参数如下:
Image File选择的是一个两种状态的按钮图片,这些图片素材在CANoe提供的Sample Configurations 16.4.4文件夹下搜索*.bmp找到。
Symbol Filter那里有两个可选项,Signal和Variable。选择Signal时,Symbol可选项为总线数据库设计时信号。选择Variable时,Symbol可选项为设置的系统变量。
此处Symbol为EngineStateSwitch,需要先设置Symbol Filter为Variable。
2.5、添加一个Track Bar控件到Engine组合框内,调整好大小。并在右侧Properties选项卡设置控件参数如下:
2.6、在Switch/Indicator和Track Bar控件上方分别添加Static Text,修改Text为Igniti、Speed。
2.7、用同样的方法,在Light组合框内,添加两个Switch/Indicator和两个Static Text,分别命名为Head和Hazard。两个Switch/Indicator参数设置如下:
完成后的效果图如下:
至此,控制面板设计完成,点击保存,将Panel1重命名为Control并保存到仿真项目Demo的文件夹Panels中。
2.8、点击上方的Check按钮,查看Panel设计是否有误,如果有错误或者警告会在Output窗口中输出。
3、设计显示界面
3.1、在Panel Designer界面上选择File→New→Panel打开一个新的面板,默认名为Panel2.
3.2、添加2个Group Box到左侧Panel内,调整好大小,并通过右侧Toolbox旁的Properties选项卡设置Text为Engine和Light。面板的布局效果如下图所示:
3.3、在Engine组合框中,添加Switch/Indicator,设置参数如下:
3.4、在Engine组合框中,添加Analog Gauge,并设置参数如下:
3.5、在Engine组合框中,添加Input/Output Box,设置参数如下:
Input/Output Box后,在添加一个Static Text,Test设置为r.p.m。设置好后,Engine内效果如下:
3.6、在Light组合框内添加Picture Box控件,调整好大小,然后设置参数如下:
3.7、在车辆图片左、右灯位置,各添加一个Switch/Indicator,参数设置如下:
注意左右灯的位置,调整好大小。完成后,Light组合框内效果如下图:
3.8、调整好两个组合框大小及位置,显示的背景色也要设置下,不然仿真运行时效果不好,设置背景色如下:
然后将Panel2重命名为Display并保存到仿真项目Demo的文件夹Panels中。效果如下:
3.9、点击上方的Check按钮,查看Panel设计是否有误,如果有错误或者警告会在Output窗口中输出。
至此,所以Panel设计完成。
五、添加CAPL程序
1、回到CANoe主界面,在Simulation Setup窗口的网络视图中,鼠标双击需要添加CAPL程序的节点Engine,会创建一个新的CAPL程序。在弹出窗口中选择要保存的路径(Demo/Nodes)并命名文件名称为Engine.can。代码如下:
/*@!Encoding:936*/
//处理系统变量EngineStateSwitch变化事件
on sysvar sysvar::Engine::EngineStateSwitch
{
$EngineState::OnOff = @this;
write("OnOff %d", $EngineState::OnOff);
if(@this) //Control界面中的Igniti开关是否打开
$EngineState::EngineSpeed = @sysvar::Engine::EngineSpeedEntry;
else
$EngineState::EngineSpeed = 0;
}
//处理系统变量EngineSpeedEntry变化事件
on sysvar sysvar::Engine::EngineSpeedEntry
{
if(@sysvar::Engine::EngineStateSwitch)
{
$EngineState::EngineSpeed = @this;
}
}
2、CAPL程序编写完成后,点击上方的Compile进行编译,编译完成后,下方Output输出编译信息,如果有错误,按照提示修改程序后再编译,直到没有错误和警告。如下图所示:
3、使用上面的方法,实现Display.can和Light.can,并编译。
Display.can如下:
/*@!Encoding:936*/
variables
{
const long kOFF = 0;
const long kON = 1;
int gDebugCounter = 0;
int geDebugCounter = 0;
}
//处理接收到报文EngineState事件
on message EngineState
{
//如果为接收
if (this.dir == RX)
{
@sysvar::Engine::EngineSpeedDspMeter = this.EngineSpeed; //将转速赋值给变量EngineSpeedDspMeter
geDebugCounter++;
if(geDebugCounter == 10)
{
writeDbgLevel(1,"EngineState RX received by node %NODE_NAME%");
geDebugCounter = 0;
}
}
}
on start
{
write("This is CANoe Demo!");
}
//处理接收到报文LightState事件
on message LightState
{
gDebugCounter++;
//如果为接收
if (this.dir == RX)
{
SetLightDsp(this.HeadLight,this.FlashLight); //通过Control界面下的Head和Hazard按钮,控制车灯状态
if(gDebugCounter == 10)
{
writeDbgLevel(1,"LightState RX received by node %NODE_NAME%");
gDebugCounter = 0;
}
}
else //如果为发送
{
if(gDebugCounter == 10)
{
writeDbgLevel(1,"Error: LightState TX send to node %NODE_NAME%");
gDebugCounter = 0;
}
}
}
SetLightDsp (long headLight, long hazardFlasher)
{
write("headLight = %d",headLight);
write("hazardFlasher = %d",hazardFlasher);
if(headLight == kON)
{
if(hazardFlasher == kON)
{
@sysvar::Lights::LightDisplay = 7;
}
else if(hazardFlasher == kOFF)
{
@sysvar::Lights::LightDisplay = 4;
}
}
else if(headLight == kOFF)
{
if(hazardFlasher == kON)
{
@sysvar::Lights::LightDisplay = 3;
}
else if(hazardFlasher == kOFF)
{
@sysvar::Lights::LightDisplay = 0;
}
}
}
Light.can如下:
/*@!Encoding:936*/
variables
{
msTimer tFlashLightFrequency;
const int gFlashLightFrequency = 500;
int gHazardLightsStatus = 0;
int gDebugCounterTX = 0;
int gDebugCounterTXRQ = 0;
int gDebugCounterRX = 0;
}
//处理发送报文LightState事件
on message LightState
{
if (this.dir == TX)
{
gDebugCounterTX++;
if(gDebugCounterTX == 10)
{
writeDbgLevel(1,"LightState TX send by node %NODE_NAME%");
gDebugCounterTX = 0;
}
}
if(this.dir == TXREQUEST)
{
gDebugCounterTXRQ++;
if(gDebugCounterTXRQ == 10)
{
writeDbgLevel(1,"LightState TXREQUEST send by node %NODE_NAME%");
gDebugCounterTXRQ = 0;
}
}
if (this.dir == RX)
{
gDebugCounterRX++;
if(gDebugCounterRX == 10)
{
writeDbgLevel(1,"Error: LightState RX received by node %NODE_NAME%");
gDebugCounterRX = 0;
}
}
}
//双闪灯闪烁频率
on timer tFlashLightFrequency
{
gHazardLightsStatus = (gHazardLightsStatus == 1 ? 0 : 1);
$LightState::FlashLight = gHazardLightsStatus;
setTimer(this, gFlashLightFrequency);
}
//处理系统变量HazardLightsSwitch变化事件
on sysvar sysvar::Lights::HazardLightsSwitch
{
if (@this)
{
gHazardLightsStatus = 1;
setTimer(tFlashLightFrequency, gFlashLightFrequency);
}
else
{
cancelTimer(tFlashLightFrequency);
gHazardLightsStatus = 0;
}
$LightState::FlashLight = gHazardLightsStatus;
}
至此,CAPL编程完成。
六、仿真测试
1、回到CANoe的Home界面,设置为仿真环境,
2、点击Panel→View下的All,在跳出的Windows下,选中Select all,如下图:
出现仿真面板Control和Display:
鼠标放在面板上,右键,设置为MDI Windows模式,并调整好位置。
3、点击上方Write,添加Write窗口,右键设置为MDI Windows模式。
4、由Home选项卡切换到Analysis选项卡,点击上方Trace,添加Trace窗口,右键设置为MDI Windows模式。调整好各界面布局如下图:
5、点击Home界面下的Start,开始仿真通过Control内的控件控制Display中的控件显示,仿真结果如下视频所示:
20230213_104650