CAPL编程实现诊断刷写,车联⽹FOTA流程⾃动化测试(代
码篇)
  原创内容,转载请注明出处
  接上篇,本⽂主要讲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;  //监控唤醒状态
14const 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;
41if(varPowerMode==2)
42  {
43    BCM_ATWS = 2;  //车⾝安全锁报警状态变量,略过定义处
44  }
45if(varPowerMode == 3)//休眠
46  {
47    InactiveGW();
48  }
49else
50  {
51    ActiveGW();
52  }
53 }
54
55//模拟按键按下,物理寻址
56void diagPhysRespMessage()
57 {
58if(IsResponse){
59  @sysvar::GW::Conn1::sysSendData = 1;
60  setTimer(PhysRespTimer, N_As);
61  }
62 }
63
64//模拟按键按下,功能寻址
65void diagFuncRespMessage()
66 {
67if(IsResponse){
68  @sysvar::GW::Conn2::sysSendData = 1;
69  setTimer(FuncRespTimer, N_As);
70  }
71 }
72
73 on message NWM_message
74 {
75if(IsBUSActive == 0)
76  {
77    GW_message.PEPS_PowerMode = 0;
78    ActiveGW();  //设备被唤醒,升级定时器触发后激活信号
79  }
80 }
81
82//处理来⾃诊断仪的物理寻址访问GW请求
83 on message 0x701//此处是捏造的物理寻址诊断ID,根据产品实际的来变更
84 {
85  diagReqMsg=this;
86  writeDbgLevel(level_1, "---physical diagnostic request, id = 0x%x", diagReqMsg.id);
87  SetValue(); //获取当前应回复值
88  diagParseReqMessage();      //解析请求内容
89  diagPhysRespMessage();    //应答请求
90
91 }
92
93//处理来⾃诊断仪的功能寻址访问GW请求
94 on message 0x7EE//此处是捏造的功能寻址诊断ID,根据产品实际的来变更
95 {
96  diagReqMsg=this;
97  writeDbgLevel(level_1, "---functional diagnostic request, id = 0x%x", diagReqMsg.id);
98  diagParseReqMessage();
99  diagFuncRespMessage();
100 }
101怎样写代码 自己做编程
102//初始化仿真的通信信号值
103void InitGWValue()
104 {
105  putValue(PEPS_PwrMode, 0);
106  GW_message.PEPS_PowerModeValidity = 2;
107  GW_message.PEPS_RemoteControlState = 0;
108 }
109//初始化数据
110void InitValue()
111 {
112//以下是从配置⽂件读取 GW接到诊断请求时的应答的数据
113  getProfileString("GW", gEntry_1, gDefautStr, cOEMInfo, gLenEntry_1, gFileName); 114  putValue(GWOEMNumber, cOEMInfo); //EPS OEM  NO.
115 }
116
117//获取ECU的回复参数
118void SetValue()
119 {
120  getValue(GWOEMNumber, cOEMInfo);
121 }
122
123 on start
124 {
125  InitGWValue();
126  ActiveGW();

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。