来源:http://www.cnblogs.com/dongdonghuihui/archive/2012/09/26/2704623.html

最好的学习方式是什么?模仿。有人会问,那不是山寨么?但是我认为,那是模仿的初级阶段,当把别人最好的设计已经融化到自己的血液里,变成自己的东西,而灵活运用的时候,才是真正高级阶段。正所谓画虎画皮难画骨。但初级阶段仍然是必须经历的过程,他会使你在达到高级阶段的过程中少走很多弯路,下面我们来迈出这一步。先研究一下别人的简单例子。

最好的例子莫过于Vector本身的Demo了,这个在安装完CANoe之后就会被自动安装。先看最简单的一个,名字叫Easy,但并不简单哦,比我们之前介绍的所有的东西都整合再一起了,很简单,但很全面。但是假如你说,这个我自己也可以完全自己写出来(并不是仅仅是看懂哦),那么我可以肯定的说,在工作中,你完全可以胜任一般的任务要求哦~,剩下的只是工作量的问题了。但我相信到现在为止,你们很多人,都无法写出这样的程序,所以我建议你们把这个程序好好的研究明白,这点很重要。废话不多说,上图,下面是打开运行后的界面。

通过面板可以控制,及显示很多动画效果,做的非常的漂亮。在其余的窗体也将主要的数据以图表等表现方式呈现出来。

我们先看一下DBC的内容吧

Signals:

EngineSpeed  车速信息

FlashLight      双跳灯

HeadLight      大灯

OnOff            引擎状态

Messages:

EngineState  引擎状态:包含的信号有OnOff,EngineSpeed

LightState    灯光状态:包含的信号有FlashLight,HeadLight

Network nodes:

Display        显示节点,接收所有消息

Engine        引擎节点,发送EngineState 消息

Light          灯光节点,发送LightState 消息

Environment variables:   环境变量,一般与界面的组件相关联,这样就实现了图形化界面的控制与显示,下面就是关联的界面组件

EnvEngineSpeedDspMeter  

EnvEngineSpeedDspText   

EnvEngineSpeedEntry       

EnvEngineStateDsp          

EnvEngineStateSwitch       

EnvHazardLightsSwitch     

EnvHeadLightSwitch         

EnvLightDsp                    

注意一下信号的信息:

Definition页面的,Init.Val的输入框使能了,之前是灰色的状态,为什么呢?点击一下蓝色的带下划线的连接,弹出窗台如下:

意思是说这个值的设置,必须要定义的属性才能有效,之前一直没有提到信号的属性,这次还是第一次遇到哦。个人理解信号属性是表明信号的特点的一系列参数,当然消息和节点也都有对应的属性。为了更加详细的了解这个属性,我们求助于帮助。

哦,明白了,原来是用来初始化数据的哦。其实在Definition表示的是物理值,都要转换成Raw值保存到GenSigStartValue属性中。在属性的创建我们之前也没有提到过,这里讲一下,请在CANdb++ Editor菜单中,View->Attribute Definitions

右键,New,填写好信息即可。属性背后跟行为是密切相关的,甚至跟底层dll,其他的一些属性请参考Help文档,当然重要的属性我们也会跟大家在后面提到。

dbc还有一些细节,就是接受的消息的定义,之间也没介绍过,例如Display节点只接收消息,那么你就应该在节点的属性上进行配置,方法是右击节点然后点Edit Node,在Mapped Rx Sig.中就可以定义接收的信号了,Add…

其实不定义接收消息也是可以的,但会在File->Consistency check 的检查中中显示出无接收节点等的报警。例如前面第一讲例子的dbc的检查如下:

再看一下CAPL程序。

engine.can 程序如下:

variables 
{
}

on envvar EnvEngineStateSwitch         //当拨动开关的时候,会更改发动机发出的信号
{
  $EngineState::OnOff = @this;           //注意信号和环境变量直接赋值时的符号,信号用$,环境变量用@
  if(@this)
    $EngineState::EngineSpeed = @EnvEngineSpeedEntry;
  else
    $EngineState::EngineSpeed = 0;
}

on envvar EnvEngineSpeedEntry         //当移动车速滑条时,会更改发动机发出的信号
{
  if(@EnvEngineStateSwitch) 
  {
    $EngineState::EngineSpeed = @this;
  }
}

on start                                         //程序开始运行的时候,将调用所有的环境变量的事件
{
  CallAllOnEnvVar();    // call all envvar procedures of this model and
                        // thus consider the START VALUES of all environment
                        // variables for:  
                        //  - initialization of all message variables
                        //  - starting of any timers
                        //  - sending messages (output) with start values
}

light.can 的程序如下:

variables 
{
  msTimer tFlashLightFrequency;                 //定义闪灯定时器
  const int gFlashLightFrequency = 500;      //定义闪灯频率,初始化为500ms
  int gHazardLightsStatus = 0;                   //定义危险灯信号

int gDebugCounterTX = 0;                      //用于调试,记录TX报文个数
  int gDebugCounterTXRQ = 0;                  //用于调试,记录TXRQ报文个数
  int gDebugCounterRX = 0;                      //用于调试,记录RX报文个数
}

on envvar EnvHeadLightSwitch                   //大灯开关状态更改时,更新灯光消息的信号
{
  // assign EV value to the message signal
  $LightState::HeadLight = @this;
}

on start
{
  CallAllOnEnvVar();    // call all envvar procedures of this model and
                        // thus consider the START VALUES of all environment
                        // variables for:  
                        //  - initialization of all message variables
                        //  - starting of any timers
                        //  - sending messages (output) with start values

setWriteDbgLevel(0); // set DbgLevel = 1 to get more information in Write-Window
}

on message LightState    //调试用,打印相关信息
{
  if (this.dir == TX)
  {
    gDebugCounterTX++;
    if(gDebugCounterTX == 10)
    {
      writeDbgLevel(1,"LightState TX received by node %NODE_NAME%");
      gDebugCounterTX = 0;
    }     
  }
  if(this.dir == TXREQUEST)
  {
    gDebugCounterTXRQ++;
    if(gDebugCounterTXRQ == 10)
    {
      writeDbgLevel(1,"LightState TXREQUEST received 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 envVar EnvHazardLightsSwitch      //危险警示灯开关变化时,更新灯光消息的闪灯信号
{
  if (@this)
  {
    gHazardLightsStatus = 1;
    setTimer(tFlashLightFrequency, gFlashLightFrequency);
  }
  else
  {
    cancelTimer(tFlashLightFrequency);
    gHazardLightsStatus = 0;
  }

$LightState::FlashLight = gHazardLightsStatus;
}

on timer tFlashLightFrequency             //危险报警灯间隔闪烁的控制
{
  gHazardLightsStatus = (gHazardLightsStatus == 1 ? 0 : 1);
  $LightState::FlashLight = gHazardLightsStatus;
  setTimer(this, gFlashLightFrequency);
}

on key '0'                                      //按键事件,定义打印调试信息的等级
{
  setwriteDbgLevel(0);
}

on key '1'                                      //按键事件,定义打印调试信息的等级
{
  setwriteDbgLevel(1);                    
}

以上程序,有C语言基础的同学应该都可以看得懂,这里不用详细介绍了。

看完程序大家可能有个疑问,没有调用任何发送CAN消息的函数(只是更改其中的信号),但报文却真的发出去了,这是为什么呢?

这是因为周期发送消息的工作,已经在消息的属性中定义了,这样消息会自动周期的发送。如下:

这个在消息的属性查看中的界面,当然也可以在上面我们介绍的View->Attribute Definitions,进行修改和查看,但区别是,这个只是针对个别消息的,View->Attribute Definitions,是针对所有的情况。还有消息属性中,对此进行归类,以上归类到Interaction Layer这个是CAN通讯的交互层。上面的各个属性的具体含义,请参考帮助文档,都有详细的说明。

下面说一下界面。

选中一个界面组件,在状态栏中可显示他的类型,关联的对象等信息。右边为属性窗口,定义选中组件的属性

这个组件类型为:Switch/Indicator

属性栏中:

Image 表示该组件使用的图片,因为要表示几种状态,所以做成这样,尺寸105x34 pix

State Count 表示状态的个数

其他的属性不一一介绍了,自己试一下基本可以知道,实在不行求助帮助文档,这里不一 一介绍了。

到现在整个工程的剖析基本上结束了,但说过的这些不足以覆盖所有的细节,但基本脉络已经很清晰了,剩下的可以自己研究,都不难理解。个人建议,在实际工作中创建自己的工程,当遇到问题是,参考例子中的实现方式,这样更加帮助理解。进步也最快。

【转载】CANoe 入门 Step by step系列(三)简单例子的剖析的更多相关文章

  1. CANoe 入门 Step by step系列(三)简单例子的剖析【转】

    最好的学习方式是什么?模仿.有人会问,那不是山寨么?但是我认为,那是模仿的初级阶段,当把别人最好的设计已经融化到自己的血液里,变成自己的东西,而灵活运用的时候,才是真正高级阶段.正所谓画虎画皮难画骨. ...

  2. ASP.Net Core 2.2 MVC入门到基本使用系列 (三)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  3. ASP.Net Core 2.2 MVC入门到基本使用系列 (三)(转)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  4. 【转载】网站配置Https证书系列(三):IIS网站设置Http链接直接跳转Https安全连接

    Http链接请求是以明文的方式传输,在传输的过程中很容易被篡改数据,一个典型的例子就是运营商的网络劫持注入广告信息等,而Https请求则是安全加密的请求,报文数据以密文的形式进行传输.当IIS网站配置 ...

  5. sql server 备份与恢复系列三 简单恢复模式下的备份与还原

    一.概述 前面讲了备份的一些理论知识,这篇开始讲在简单恢复模式下的备份与还原.在简单模式下是不能做日志备份的,发生灾难后,数据库最后一次备份之后做的数据修改将是全部丢失的,所以在生产环境下,数据又很重 ...

  6. ASP.Net Core 2.2 MVC入门到基本使用系列 (二)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  7. ASP.Net Core 2.2 MVC入门到基本使用系列 (四)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  8. Linux Kernel系列三:Kernel编译和链接中的linker script语法详解

    先要讲讲这个问题是怎么来的.(咱们在分析一个技术的时候,先要考虑它是想解决什么问题,或者学习新知识的时候,要清楚这个知识的目的是什么). 我在编译内核的时候,发现arch/arm/kernel目录下有 ...

  9. 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

    Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)   介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...

随机推荐

  1. go服务端----使用dotweb框架搭建简易服务

    使用dotweb框架搭建简易服务 go语言web框架挺多的,所谓琳琅满目,里面也有很多优秀的,比如echo.beego等,但体验下来,总是觉得哪里有点小疙瘩,后来才明白过来,echo太简单,很多日常使 ...

  2. js中替换字符串(replace方法最简单的应用)

    replace方法的语法是:stringObj.replace(rgExp, replaceText) 其中stringObj是字符串(string),reExp可以是正则表达式对象(RegExp)也 ...

  3. 对jsp的初步了解及规范问题(二)

    前言 今天的例子是用jsp制作简单的“艾宾浩斯记忆曲线的学习计划表”. 重点不是算法,重点是学习jsp中的一个重要的思想,作为展现层,jsp中不应该出现业务逻辑代码. 当中<%%>代码也会 ...

  4. Bash中的数学计算

    一.整数计算 1.整数 $delare -i num$num=5+5$echo $num10 $num="5 + 8"$echo $num13注意:算式中如果有空格,需要用引号引起 ...

  5. python 标准库 -- logging

    线程安全的日志记录模块. 一. 使用示例 import logging logging.basicConfig(filename="app.log", format="% ...

  6. 【2017-06-27】Js中获取地址栏参数、Js中字符串截取

    一.Js中获取地址栏参数 //从地址栏获取想要的参数 function GetQueryString(name) { var reg = new RegExp("(^|&)" ...

  7. maven打包 tomcat运行pom配置 或 打成jar包

    maven打包 tomcat运行pom配置,同时还需要配置org.apache.tomcat.maven插件,这里省略. <groupId>com.company</groupId& ...

  8. js调试模式控制台输出信息

    js调试模式控制台输出信息.console.log

  9. sql嵌套批量更新

    嵌套批量更新 UPDATE CheLiang SET lineName = t.linename FROM TeamJiHua t ,CheLiang tc WHERE t.id = tc.teami ...

  10. 手机cpu结构,arm

    问题描述 今天测试人员测试集成版本时除了一个bug:关于华为 Mate 8手机Android 6.0系统运行刚刚提测的版本时,出现闪退的bug,而小米 4 手机Android 6.0系统却没有出现任何 ...