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


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

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

    tmpD0

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

    我们先看一下DBC的内容吧

    Signals:

    EngineSpeed  车速信息

    FlashLight      双跳灯

    HeadLight      大灯

    OnOff            引擎状态

    Messages:

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

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

    Network nodes:

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

    Engine        引擎节点,发送EngineState 消息

    Light          灯光节点,发送LightState 消息

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

    EnvEngineSpeedDspMeter  tmp60

    EnvEngineSpeedDspText   tmp61

    EnvEngineSpeedEntry       tmp5D

    EnvEngineStateDsp          tmp5E

    EnvEngineStateSwitch       tmp56

    EnvHazardLightsSwitch     tmp57

    EnvHeadLightSwitch         tmp58

    EnvLightDsp                    tmp62

    注意一下信号的信息:

    tmp156tmp157

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

    tmp158

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

    tmp15E

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

    tmp163

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

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

    tmp16C

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

    tmp16E

    再看一下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消息的函数(只是更改其中的信号),但报文却真的发出去了,这是为什么呢?

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

    tmp29

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

    下面说一下界面。

    tmp4B

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

    tmp4D

    这个组件类型为:Switch/Indicator

    属性栏中:

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

    tmp4F

    State Count 表示状态的个数

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

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

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

  • 相关阅读:
    演示-JQuery属性选择器
    演示--Jquery核心选择器
    JQuery选择器
    SoapUI 接口测试之post提交本地数据文件
    Python使用MySQLConnector/Python操作MySQL、MariaDB数据库
    测试思想-测试设计 测试用例设计需要注意的几个点
    Jenkins 为Jenkins添加Windows Slave远程执行python项目脚本
    测试思想-测试设计 接口测试用例设计实践总结
    测试思想-测试设计 测试用例设计最新实践总结-来自不断的追求
    Python 基于Python实现邮件发送
  • 原文地址:https://www.cnblogs.com/CCJVL/p/3432726.html
Copyright © 2020-2023  润新知