从CAPL中的从节点读取LIN帧

时间:2019-08-30 04:03:30

标签: capl canoe canalyzer

我正在尝试读取从从属LIN节点发送的linFrame,以识别特定位何时从零更改为一。

我正在将LIN消息发送到从属伺服器,以命令其从物理终点停止。

一旦它物理地到达终点,它的状态消息将设置一个从零到一的位。该位标识伺服电动机何时停止运转。我的目标是让CAPL脚本检测到电动机已停转。

我的命令消息由我的CAPL脚本使用“ output()”函数发送。我不确定哪个函数可以读取响应,但是我认为必须发送响应消息的标头,然后读取响应框架。

variables
{
 linFrame 0x03 ACT_CTRL_MT3  = {msgChannel=1}; // actuator control command
 linFrame 0x21 ACT_STA_MT3   = {msgChannel=1}; // actuator status response

  mstimer timer1;

}


on key 'c'
{


  // command large angular position from servo at node 3
  ACT_CTRL_MT3.RTR = 0;
  ACT_CTRL_MT3.byte(0)=0x12; // section 4.5.9 of manual
  ACT_CTRL_MT3.byte(1)=0xE4;
  ACT_CTRL_MT3.byte(2)=0x14;
  ACT_CTRL_MT3.byte(3)=0xFE; // max angle
  ACT_CTRL_MT3.byte(4)=0xFF; // max angle
  ACT_CTRL_MT3.byte(5)=0x00;
  ACT_CTRL_MT3.byte(6)=0x00;
  ACT_CTRL_MT3.byte(7)=0x40;
  output(ACT_CTRL_MT3); // update command payload

  // Send the frame header
  ACT_CTRL_MT3.RTR = 1;
  output(ACT_CTRL_MT3);

  settimer(timer1,5000); // wait 5 seconds for motor to move 
}


on timer timer1{

  //send header of status message
  ACT_STA_MT3.RTR = 1;
  output(ACT_STA_MT3);


  write("Reading message...");

  //output message context
  writelineex(1,1,"FrameId=%d Length=%d, 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X;", ACT_STA_MT3.ID, ACT_STA_MT3.DLC,
      ACT_STA_MT3.byte(0), ACT_STA_MT3.byte(1), ACT_STA_MT3.byte(2), ACT_STA_MT3.byte(3), ACT_STA_MT3.byte(4), ACT_STA_MT3.byte(5), ACT_STA_MT3.byte(6), ACT_STA_MT3.byte(7));

}

“ writelinee”函数写入的数据与在Canalyzer的LIN跟踪窗口中看到的值完全不同。

我感到特别奇怪的是,写出的ID字段与代码开头的变量部分中设置的ID不同。在代码中,我将该状态消息的帧ID定义为0x21,但是write命令给出了一个不同的值(我相信0x35,尽管我目前不在设置中。无法寻求帮助就无法入睡。首先!)。

我显然做错了事,对此我很陌生,因此如果有人可以帮助,那就太好了。

非常感谢, 亚当

1 个答案:

答案 0 :(得分:0)

很遗憾,我没有CANoe许可证,因此无法检查我的代码是否正常。我已经多次做过类似的思考,所以我们应该很好。

从您的描述中我注意到,您需要在此处做三件事: 1)发送带有一些数据的控制LIN框架(ID 0x03),以启动电动机。 2)发送状态LIN标头(ID 0x21)-请记住,LIN Slave无法启动LIN总线上的传输,因此您需要提供LIN标头,以便LIN Slave可以响应某些数据。 3)从LIN接头连接器获取响应数据(由LIN从站添加到LIN接头连接器0x21的数据)-通知电机堵转。

这是对您之前提供的代码的小修改。我还标记了可以用不同方式完成的某些操作(您知道CANoe具有许多功能):

variables
{
 linFrame 0x03 ACT_CTRL_MT3  = {msgChannel=1}; // actuator control command
 linFrame 0x21 ACT_STA_MT3   = {msgChannel=1}; // actuator status response

 mstimer timer1;
}


// starts the fun
on key 'c'  
{
  ACT_CTRL_MT3.RTR = 1;  // RTR=1 means that you want to send entire message (header + data)
  ACT_CTRL_MT3.byte(0)=0x12;
  ACT_CTRL_MT3.byte(1)=0xE4;
  ACT_CTRL_MT3.byte(2)=0x14;
  ACT_CTRL_MT3.byte(3)=0xFE;
  ACT_CTRL_MT3.byte(4)=0xFF;
  ACT_CTRL_MT3.byte(5)=0x00;
  ACT_CTRL_MT3.byte(6)=0x00;
  ACT_CTRL_MT3.byte(7)=0x40;
  output(ACT_CTRL_MT3);  // this sends the message to the bus

  settimer(timer1, 20); // set timer to trigger actions in 20 ms
}


// sending LIN headers (ID 0x21) cyclically
on timer timer1 
{
  // sends a single LIN header - you can also try to do it this way:
  // ACT_STA_MT3.RTR=0;
  // output(ACT_STA_MT3);
  linTransmitHeader(ACT_STA_MT3);  // or linTransmitHeader(0x21);
  //set timer again to let LIN Slave respond if stalled later on
  settimer(timer1, 20); // reset to execute every 20 ms
}

// event on receiving entire frame (header + response data) from LIN Slave
on linFrame ACT_STA_MT3
{
  // not sure where is located your bit that is informing about stalling of the motor, but in this example I assumed it is on first position of byte 0
  if (this.byte(0) & 0x01)
  {
    // you can put some other instructions here
    write("Motor has stalled!");
  }
  // you can also log entire frame (I think your code was fine so I copied it):
  writelineex(1,1,"FrameId=%d Length=%d, 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X;", this.ID, this.DLC, this.byte(0), this.byte(1), this.byte(2), this.byte(3), this.byte(4), this.byte(5), this.byte(6), this.byte(7));
}

PS。试试看,让我知道它可以像我在记事本中写的那样按预期方式编译和运行。将帮助您解决潜在的错误。