理解软件自带的easy工程(二)

发布时间 2023-07-13 15:50:44作者: 玩一会

继续分析Light的代码

/*@@msg:CAN1.easy::LightState (0x321):*/
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;
    }
  }
}
/*@@end*/

这里应该是总线上有Light报文才会触发事件吧,但没看到哪里有报文变动。

 if (this.dir == TX)
  {
    gDebugCounterTX++;
    if(gDebugCounterTX == 10)
    {
      writeDbgLevel(1,"LightState TX received by node %NODE_NAME%");
      gDebugCounterTX = 0;
    }     
  }

dir是什么意思,查阅资料

 dir表示报文的传输方向,若报文的dir=TX(1),表示这个报文是Light这个ECU发送的;若是RX(0),表示这个报文是Light接收的;若是TXREQUEST,我也不知道啥意思。

gDebugCounterTX是自定义的变量,初始值为0。若报文发送,则gDebugCounterTX加1,当gDebugCounterTX=10,输出:LightState TX received by node %NODE_NAME%,这里要注意,因为writeDbgLevel的第一个参数是1,而在最开始start函数里运行了setWriteDbgLevel(0),看下图关于writeDbgLevel的介绍,能明白不按按键1(后面有代码,按了按键1,setWriteDbgLevel就会变成1)那么就不会输出。现在暂且还不明白为什么只有当gDebugCounterTX=10时才被接收。
  • writeDbgLevel

if (this.dir == RX)
  {
    gDebugCounterRX++;
    if(gDebugCounterRX == 10)
    {
      writeDbgLevel(1,"Error: LightState RX received by node %NODE_NAME%");
      gDebugCounterRX = 0;
    }
  }

 

这里是因为Light节点不应该接收到从其他地方过来的报文 ,所以是个Error.

说实话上面这段代码不是很懂,革命尚未成功,同志仍需努力呀。

  • 下面是定时事件
/*@@timer:tFlashLightFrequency:*/
on timer tFlashLightFrequency
{
  gHazardLightsStatus = (gHazardLightsStatus == 1 ? 0 : 1);
  $LightState::FlashLight = gHazardLightsStatus;
  setTimer(this, gFlashLightFrequency);
}
/*@@end*/

 

有关定时事件的相关知识点如下:

 最开始已经定义了变量:msTimer tFlashLightFrequency;

表达式1?表达式2:表达式3。

含义是:如果表达式1成立(值为真),则表达式2是整个条件表达式的值;如果表达式1不成立(值为假),则表达式3是整个条件表达式的值。

gHazardLightsStatus == 1 ? 0 : 1  就是先比较gHazardLightsStatus 是否等于1,若等于1,gHazardLightsStatus=0;若不等于1,则gHazardLightsStatus=1;这应该就是一个自动取反的作用。

$LightState::FlashLight = gHazardLightsStatus;   把gHazardLightsStatus的值赋给信号FlashLight,目前没发现信号FlashLight与什么相关联。再把定时值设为500;因为定义变量

const int gFlashLightFrequency = 500;

/*@@key:'0':*/
on key '0'
{
  setwriteDbgLevel(0);
}
/*@@end*/

/*@@key:'1':*/
on key '1'
{
  setwriteDbgLevel(1);
}
/*@@end*/

 

这段代码就是按0,则write框内不输出,按1就输出。

/*@@sysvarChange:Lights::HazardLightsSwitch:*/
on sysvar sysvar::Lights::HazardLightsSwitch
{
  if (@this)
  {
    gHazardLightsStatus = 1;
    setTimer(tFlashLightFrequency, gFlashLightFrequency);
  }
  else
  {
    cancelTimer(tFlashLightFrequency);
    gHazardLightsStatus = 0;
  }

  $LightState::FlashLight = gHazardLightsStatus;
}
/*@@end*/

 

这是变量HazardLightsSwitch变动触发的事件,Hazard与HazardLightsSwitch系统变量相关联Hazard有两种状态,初始值是0,点击一下变量值变为1;如果HazardLightsSwitc的值为1,则gHazardLightsStatus = 1,再重新设置定时器。如果HazardLightsSwitc的值为0,就是不打开,则么关闭定时器,使HazardLightsSwitc的值为0;再把gHazardLightsStatus的值赋给FlashLight信号。我现在有个疑惑 ,FlashLight信号没有跟其他东西绑定,怎么显示它的值。可能在后面吧。

下面是Display的CAPL

/*@@var:*/
variables 
{
  const long kOFF = 0;
  const long kON = 1;

  int gDebugCounter = 0;
}
/*@@end*/

/*@@msg:CAN1.easy::EngineState (0x123):*/
on message EngineState 
{  
  // engine state received
  if (this.dir == RX)
  {
    @sysvar::Engine::EngineSpeedDspMeter = this.EngineSpeed / 1000.0;
  }
}
/*@@end*/

/*@@startStart:Start:*/
on start
{
  setwriteDbgLevel(0); // set DbgLevel = 1 to get more information in Write-Window 
  write("Press key 1 to set DbgLevel = 1 for more information in the Write-Window");
  write("Press key 0 to set DbgLevel = 0 for less information in the Write-Window");
}
/*@@end*/

/*@@msg:CAN1.easy::LightState (0x321):*/
on message LightState 
{
  gDebugCounter++;

  if (this.dir == RX)
  {
    SetLightDsp(this.HeadLight,this.FlashLight);

    if(gDebugCounter == 10)
    {
      writeDbgLevel(1,"LightState RX received by node %NODE_NAME%");
      gDebugCounter = 0;
    }    
  }
  else
  {
    if(gDebugCounter == 10)
    {
      writeDbgLevel(1,"Error: LightState TX received by node %NODE_NAME%"); 
      gDebugCounter = 0; 
    }
  }
}
/*@@end*/

/*@@caplFunc:SetLightDsp(long,long):*///function
SetLightDsp (long headLight, long hazardFlasher)
{
  if(headLight == kON) 
  {
    if(hazardFlasher == kON) 
    {
      @sysvar::Lights::LightDisplay = 7;
    } 
    else if(hazardFlasher == kOFF) 
    {
      @sysvar::Lights::LightDisplay = 4;
    }
  }
  else if(headLight == kOFF) 
  {
    if(hazardFlasher == kON)  
    {
      @sysvar::Lights::LightDisplay = 3;
    } 
    else if(hazardFlasher == kOFF) 
    {
      @sysvar::Lights::LightDisplay = 0; 
    }
  }
}
/*@@end*/

/*@@key:'0':*/
on key '0'
{
  setwriteDbgLevel(0);
}
/*@@end*/

/*@@key:'1':*/
on key '1'
{
  setwriteDbgLevel(1);
}
/*@@end*/

 

下面分段理解

/*@@startStart:Start:*/
on start
{
  setwriteDbgLevel(0); // set DbgLevel = 1 to get more information in Write-Window 
  write("Press key 1 to set DbgLevel = 1 for more information in the Write-Window");
  write("Press key 0 to set DbgLevel = 0 for less information in the Write-Window");
}
/*@@end*/

 

on start 是CAPL程序开始时执行的函数,输出两条提示,具体什么意思在(二)中解释过了。

/*@@msg:CAN1.easy::EngineState (0x123):*/
on message EngineState 
{  
  // engine state received
  if (this.dir == RX)
  {
    @sysvar::Engine::EngineSpeedDspMeter = this.EngineSpeed / 1000.0;
  }
}
/*@@end*/

 

当收到EngineState报文触发事件,当EngineState.dir=RX,那么就将速度值/1000.0的值赋予以与meter相关联的EngineSpeedDspMeter,这样Display中的指针会转动。

/*@@caplFunc:SetLightDsp(long,long):*///function
SetLightDsp (long headLight, long hazardFlasher)
{
  if(headLight == kON) 
  {
    if(hazardFlasher == kON) 
    {
      @sysvar::Lights::LightDisplay = 7;
    } 
    else if(hazardFlasher == kOFF) 
    {
      @sysvar::Lights::LightDisplay = 4;
    }
  }
  else if(headLight == kOFF) 
  {
    if(hazardFlasher == kON)  
    {
      @sysvar::Lights::LightDisplay = 3;
    } 
    else if(hazardFlasher == kOFF) 
    {
      @sysvar::Lights::LightDisplay = 0; 
    }
  }
}
/*@@end*/

 

这是自定义函数,下面是自定义函数相关知识点。这个函数的意思就是如果头灯打开,再打开双闪那么双闪就会在状态4和7反复跳转;如果头灯关闭,再打开双闪它就会在状态0和3反复跳转。为什么会反复跳转呢,因为在Light的CAPL中已经提到过了FlashLight由另一个会自动取反的值赋值。

on message LightState 
{
  gDebugCounter++;

  if (this.dir == RX)
  {
    SetLightDsp(this.HeadLight,this.FlashLight);

    if(gDebugCounter == 10)
    {
      writeDbgLevel(1,"LightState RX received by node %NODE_NAME%");
      gDebugCounter = 0;
    }    
  }
  else
  {
    if(gDebugCounter == 10)
    {
      writeDbgLevel(1,"Error: LightState TX received by node %NODE_NAME%"); 
      gDebugCounter = 0; 
    }
  }
}
/*@@end*/

 

 

 又来这个,还是不能理解为啥要等他到10。