原创内容,转载请注明出处
接上篇,本文主要讲CAPL编程详细实现,软件环境CANoe 11.0
一、Simulation Setup
1、建模之前,首先创建一个.DBC文件。如果不会,可以用一个已有的DBC文件修改。新建待仿真的空节点,如下图,只有节点名称无任何信号。然后加载到Setup
2、新插入节点,选择Insert Network Node, 然后右击新建的节点配置该节点属性。
选择DBC中创建的节点名,此处很有用
设置节点属性为OSEK_TP节点(添加osek_tp.dll即可,在canoe安装目录下查找,我的是 "C:\Program Files\Vector CANoe 11.0\Exec32")
我的整个模型建完如下图(ECU太多,未截图完整):
可能大家会有疑问,关于这个网络模型的合理性。
疑问1. 如此多的节点,运行负载如何,会不会不足以支撑,变得不够实时性?
答:我的硬件是CANoe89系列,是最强悍的一款。完全可以支撑这么多节点。 而且按CANoe官方介绍的说法,理论上这种模型可支持无限多个节点,只是会降低速率。当然canoe对PC的运存要求比较高,需一台强悍的电脑承载。
ISO11898标准规定标准的1M/s CAN网络的最大总线长度40m, 最多允许存在30个节点,各节点支路最长为0.3m,如果网络以较低的速度运行则可支持更多的节点,总线长度也可增加。
高速总线的标准最大速率500k/s, 而支持超过30个节点的低速总线的速率为125k/s或更低, 低速CAN网络普遍能支持50个或更多的节点。
疑问2.目前才20几个ECU,复杂度不算太高,当ECU数量更多时,是否会造成编码量过大,可维护性变得极差?
答:上一篇的介绍过系统框架和通信模型,此模型非常简便的支持节点热增减,各ECU之间的耦合度降到最低,互不牵连。设计时抽取了通用接口,即使是二次开发也是非常简单的。
二、代码实现
此处选择GW节点作为样例讲解。其中涉及的环境变量和系统变量在代码中出现时再做说明
1、ECU应用层行为仿真
1 /*@!Encoding:936*/ 2 includes 3 { 4 #include "GenericNode.cin" //此处是一个造好的轮子,可见canoe提供的\OSEK_TP_MultiChannel Demo 5 } 6 7 variables 8 { 9 msTimer PhysRespTimer; //物理寻址应答定时器 10 msTimer FuncRespTimer; //功能寻址应答定时器 11 msTimer GWMessageTimer; //ECU外发消息定时器,周期性的往总线发报文 12 message 0x111 GW_message; //此处是随便举例的报文,假设GW的tx报文就是id=0x111 13 message 0x222 NWM_message; //监控唤醒状态 14 const int cycPepsTime = 100; //100ms周期 15 } 16 17 //每100ms发送一帧gw报文到总线,ecu信号仿真 18 on timer GWMessageTimer 19 { 20 output(GW_message); 21 setTimer(GWMessageTimer, cycPepsTime); 22 } 23 24 //模拟按键弹起,物理寻址 25 on timer PhysRespTimer 26 { 27 //注意此处的系统变量格式, ECUName::链路名::变量名, 本篇章节一介绍的在setup处建立节点时,要求配置选择数据库的节点名将在此处生效 28 @sysvar::GW::Conn1::sysSendData = 0; 29 } 30 31 //模拟按键弹起,功能寻址 32 on timer FuncRespTimer 33 { 34 @sysvar::GW::Conn2::sysSendData = 0; //注意此处链路名与上一函数不一样,区分物理寻址和功能寻址主要体现在这里 35 } 36 //监控一个环境变量,整车电源模式。 备注:环境变量可在DBC中创建 37 on envVar PEPS_PwrMode 38 { 39 varPowerMode = getValue(PEPS_PwrMode); //先略过此变量的定义位置,全局变量记录电源状态 40 GW_message.PEPS_PowerMode = varPowerMode; 41 if(varPowerMode==2) 42 { 43 BCM_ATWS = 2; //车身安全锁报警状态变量,略过定义处 44 } 45 if(varPowerMode == 3)//休眠 46 { 47 InactiveGW(); 48 } 49 else 50 { 51 ActiveGW(); 52 } 53 } 54 55 //模拟按键按下