前言
- CAN 报文层交互层的内容呢全网的资源基本上都是对Help文档的直译,对于没接触过的同学理解起来可能比较吃力,这一节我就结合脚本一步一步的阐述下交互层
文章目录
- 前言
- 概念理解
-
- 信号发送的基本类型
-
- 1,周期发送(cycle)
- 2,信号值有变化了才发送(OnChange)
- 3,只要设置了信号值就发送(OnWrite)
- 4,设置了信号值且不等于默认值(IfActive)
- 5,只要设置了信号值就发送n次(OnWriteWithRepetions)
- 6,不指定发送方式,(NoSigSendType)
- message发送的属性
-
- 1,是否支持交互层,(GenMsgILSupport)
- 2,message发送类型,(GenMsgSendType)
- 3,message快速发送周期,(GenMsgCycleTimeFast)
- 4,message连续发送N帧当条件触发的时候,(GenMsgNrOfRepetition)
- 5,message延迟多久再发,(GenMsgStartDelayTime)
- IL CAPL Functions
- 计算 Counter 和CheckSun
- 总结
概念理解
1,下面的图是Help文档的首页。这张图我们能得到哪些信息呢?
- IL层在message发送到总线上之前,默认情况下,IL层的参数是在DBC文件中定义的。
- IL层定义message 和signal的行为方式,比如什么时候发,发送周期是多少。
信号发送的基本类型
1,下图定义了 信号的行为,是周期的发送还是信号又变化的时候发送,又或者只要对信号设置了,不管值又改变否都要发送,下面结合实例一个一个看下
2,这里博主用的是官方的一个工程C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 11.0.81\CAN\Easy
,如下图,博主这样排列了四个子面板,待会用得到。
3,这里一定要明白DBC文件中定义了message和signals, 在DBC文件中通过属性定义了他们的发送行为(怎么定义,这里就不展开讲述DBC Editor的编辑操作了),下图我们观察下,节点的属性只有两个,用于说明支持IL层,并且给出引用的Dll.
4,下面是Light node下的 LightState (message)和FlashLight (signal)的发送属性,这些属性都是什么意思,在下面内容会展开讲
5,如下图。我们打开 IL Configration 面板 ,找到 LightState (message)和FlashLight (signal)的发送属性,看的到是和上面DBC文件中定义的相吻合的。
1,周期发送(cycle)
- Cyclic - The message is sent at a fixed cycle time independent of signal values.
1,请看上面的那张图,LightState 报文的发送方式没定义(not_used),但是LightState 信号的发送方式是cycle,所以这整个信号的发送行为就是周期发送
结论:某个message下只要有一个信号的发送方式是cycle,则这个message的发送方式就是cycle
2,信号值有变化了才发送(OnChange)
- OnChange-The message is sent when a changed signal value is written
to the message.
2,根据下图的步骤改变信号的值,发现只有值每次改变才会发送一帧
3,只要设置了信号值就发送(OnWrite)
- OnWrite - The message is sent when the value of a signal is rewritten to the message.
3,根据下图,我连续三次设置了FlashLight==1 ,所以Trace上打印了三帧报文
4,设置了信号值且不等于默认值(IfActive)
- IfActive: The message is sent at a fast cycle time if a signal of the message is set to an active value. As soon as all values are inactive, the message is no longer sent.
这段话可以理解为信号值有变化,而且值不等于默认值,才视为有效值
4,看下FlashLight的默认值是0,设置成IFActive之后,开始Trace中是没报文的,当我将值设置为1之后,立马100ms的周期发送报文,当再设置为0之后,报文立马停发。
5,只要设置了信号值就发送n次(OnWriteWithRepetions)
这个Help中没说,根据理解就是 在OnWrite的基础上,连续以fast cycle time发送 n 次,n的数值由Repetitionsc参数请确定
6,不指定发送方式,(NoSigSendType)
如果signal的发送方式 是不指定发送方式,那么这个信号的发送方式取决于message的发送方式
- 如果message 的发送方式 not_used ,则报文不发送
- 如果message 的发送方式 cycle,则报文发送
message发送的属性
1,下图呢,help中说明了一些message 的常用属性,那么接下来我们就借助IL Configration 说明下这些属性
1,是否支持交互层,(GenMsgILSupport)
这个必须打勾的,不打勾,下面定义的属性全都没用的
2,message发送类型,(GenMsgSendType)
支持以下四种类型
- Cyclic
- NotUsed
- IfActive
- NoMsgSendType
如果message设置为cycle,即使signal 设置为 NoSigSendType ,则报文还是会以cycle发送的
如果message设置为NoMsgSendType 或者NotUsed ,但是signal 设置为 Cyclic ,则报文还是会以cycle发送的
总而言之,message 和signal的发送方式有点取或 的意思,signal发送类型在mesage的属性上进一步定义了报文的发送方式,再比如
如果message设置为cycle,signal 设置为 OnWriteWithRepetions,则报文不仅以cycle发送,还能响应 OnWriteWithRepetions的发送方式。
3,message快速发送周期,(GenMsgCycleTimeFast)
这个参数,在signal 的发送方式者只为 ifactive的时候 有用 ,
4,message连续发送N帧当条件触发的时候,(GenMsgNrOfRepetition)
这个参数,在signal 的发送方式者只为xxxxwithRepetition的时候 有用 ,就是以fast cycle time 连续发送 n帧报文,n就是这个参数定义的内容
5,message延迟多久再发,(GenMsgStartDelayTime)
这个参数,比如这只为10s,则当start Run之后,Trace中10s后你才能看到这个第一帧报文。
IL CAPL Functions
IL CAPL Functions 给了很多的API函数可以用的,下面我就选取一些比较实用的函数讲解下。
1,下图 IL 启动和停止的一个状态机和函数
2,`long ILControlInit () :初始化 IL
这个函数只能在 on preStart中使用 ,目的是阻止 IL自动启动( IL 是默认生效的)
我们在light.can里面添加如下代码
On preStart
{
long ret;ret = ILControlInit ();write("****ILControlInit trolinit:%d",ret);
}
测试结果来看,Trace没输出,说明禁止IL成功了。
3,`long ILControlStart() 和 ILControlStop () :开始和停止
我们在light.can里面添加如下代码:
//On preStart
//{
// long ret;
// ret = ILControlInit ();
// write("****ILControlInit trolinit:%d",ret);
//}
on key 'a'
{
long ret;ret = ILControlStop ();write("****ILControlStop :%d",ret);
}on key 'b'
{
long ret;ret = ILControlStart ();write("****ILControlStart :%d",ret);
}
测试结果:在4s的时候按下’a‘,Trace中停发了, 然后又按下’b‘ 报文又继续发送
4,`long ILSetMsgEvent (dbMessage msg) :直接向总线上发送一帧报文
我们在light.can里面添加如下代码:
on key 'c'
{
long ret;ret = ILSetMsgEvent (LightState);write("****ILSetMsgEvent :%d",ret);
}
测试结果:
5,故障注入
我们在light.can里面添加如下代码:
on key 'd'
{
long ret;ret = ILFaultInjectionDisableMsg(LightState);write("****ILFaultInjectionDisableMsg:%d",ret); }on key 'e'
{
long ret;ret = ILFaultInjectionEnableMsg(LightState);write("****ILFaultInjectionEnableMsg:%d",ret);
}on key 'f'
{
long ret;ret = ILFaultInjectionSetMsgCycleTime (LightState,200);write("****ILFaultInjectionSetMsgCycleTime :%d",ret);
}on key 'g'
{
long ret;ret = ILFaultInjectionResetMsgCycleTime (LightState);write("****ILFaultInjectionResetMsgCycleTime :%d",ret);
}
分别以此按下键盘的,d,e,f,g 测试结果如下:
5,节点的函数我们选择节点开始和停发
因为我们的工程Light 节点只有一个 message ,不能很好的体现对节点的操作,所以我们按照下图添加一个message,
我们在light.can里面添加如下代码:
on key 'h'
{
long ret;ret = ILNodeControlStop ("Light");write("****ILNodeControlStop :%d",ret);
}on key 'i'
{
long ret;ret = ILNodeControlStart ("Light");write("****ILNodeControlStart :%d",ret);
}
分别以此按下键盘的,h,i 测试结果如下:
计算 Counter 和CheckSun
IL 层最常用的应该就是计算Counter和 CheckSum了,上面新建的message中包含了counter和checkSum信号的目的就在这一步。
dword applILTxPending(long aId, dword aDlc, byte data[]);这个函数是个回调函数,当前节点又message发出,就会调用这个函数
我们在light.can里面添加如下代码:
dword applILTxPending (long aId, dword aDlc, byte data[])
{
dword i;byte xor;if(aId == 0x322){
// calculate counteri = data[1] & 0x0F;i++;i = i % 16;data[1] = i & 0x0F;// calculate checksumxor = 0xff;for(i = 1; i < aDlc; ++i) {
xor = xor ^ data[i];}data[0] = xor;}return 1; // don't prevent sending of the message
}
从测试结果来看,我们成功的计算了counter 和 check sum
总结
-
回顾下本章节讲述了的知识点,主要还是要对DBC文件对node,message,signal定义的属性要了解,其次IL层的函数用很多,我们选择了一些长得漂亮的函数测试;最重要的是我们可以在IL层就完成对message 的counter和checksum的计算。
-
本博客谢绝转载
-
有需要本博客演示所用Demo工程,可以去下方交流群网盘地址下载
- ?要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!
- ? 有手机的小伙伴可以加下交流群,在车载诊断领域的一个小小圈子,群里有
网盘资料
,源码
,可能有你需要的呢,平时可以交流技术,聊聊工作机会啥的。
- ?如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。