技术博客

21/05/2024 作者 Adam Raymer

只需一个简单脚本,具备编程功能的Kvaser设备秒变高效网关

在某些情况下,您可能需要合并两条CAN总线,或者在使用不同比特率和/或协议的两条总线之间进行数据传输。您可以选择购买网关来完成这项任务。或者,您也可以使用自己的多通道Kvaser设备和t脚本来创建自己的网关。在本文中,我们将简要介绍t脚本,以及如何通过编写少量代码来建立自己的网关。

什么是t脚本?
我们的t脚本语言与C语言类似,它允许用户使用“hooks”对总线上的某些事件做出编程反应和响应。t脚本在Kvaser设备上进行本地运行。一旦加载并启动t脚本,就无需再与PC通信。*

如何设置网关?
首先,您需要一台可以使用t脚本的多通道设备,例如USBcan Pro(2xHS或4xHS)或Kvaser Memorator Pro(2xHS v2或5xHS)。然后将通道1和2分别连接到两条CAN总线上。如果设备有两条以上的通道,那么您也可以接入不同的通道。在示例中,我们将使用通道1和通道2。如果在独立模式下使用Memorator Pro,则需要为通道1供电。

通过Kvaser用于创建、编译和运行t脚本的集成开发环境TRX,您可以使用以下t脚本,并将其下载到通道1上的设备中:

variables { 

  const int ch1 = 0; 

  const int ch2 = 1; 

} 

 

on start { 

  canSetBitrate(ch1, canBITRATE_250K); 

  canSetBitrate(ch2, canBITRATE_250K); 

  canSetBusOutputControl(ch1, canDRIVER_NORMAL); 

  canSetBusOutputControl(ch2, canDRIVER_NORMAL); 

  canBusOn(ch1); 

  canBusOn(ch2); 

} 

 

on stop { 

  canBusOff(ch1); 

  canBusOff(ch2); 

} 

 

on CanMessage <ch1> * { 

  canWrite(ch2, this); 

} 

 

on CanMessage <ch2> * { 

  canWrite(ch1, this); 

} 

在TRX中运行此脚本时,通道1和通道2都将以250 kb/s的比特率接入总线。之后,第一条CAN总线上的流量将传输至第二条CAN总线,反之亦然。

正在发生什么?
该脚本共有四个“hooks”,分别为:on start、on stop、on CANMessage <ch 1>和 on CANMessage <ch 2>。当加载脚本并由TRX通知开始时,“on start”将被触发。在这段代码中,通道将被置于总线上。当通知TRX停止脚本时,“on stop”被触发,通道将被置于总线关闭状态。如果CAN通道1读取报文,则会触发on CANMessage <ch 1>,并运行代码将报文复制到CAN通道2。而如果CAN通道2读取报文,则运行on CANMessage <ch 2>中的代码。

通过这些基本步骤,您就可以拥有一个连接两条CAN总线的功能网关。但是,如果您还想做得更多,该怎么办呢?

如果设备已经在总线上,需进行哪些操作?
如果设备已经在总线上,则无需on start和on stop hooks。为了便于读取,可以删除这些hooks:

variables { 

  const int ch1 = 0; 

  const int ch2 = 1; 

} 

 

on CanMessage <ch1> * { 

  canWrite(ch2, this); 

} 

 

on CanMessage <ch2> * { 

  canWrite(ch1, this); 

} 

如果您使用的是Kvaser USBcan Pro 2xHS v2Kvaser USBcan Pro 4xHS或Kvaser Hybrid Pro 2xHS等设备,以下是启动脚本的步骤:

  1. 打开总线监控/总线分析软件
  2. 配置设备并打开通道
  3. 启动TRX并加载项目
  4. TRX中将设备设置为在线状态
  5. TRX中将t脚本下载到设备上
  6. TRX中启动t脚本

现在,设备已作为网关运行,您仍可使用总线分析/总线监控软件。以上就是关于设置基本网关的全部内容。但如果要连接两条不同比特率的总线,该怎么办呢?您可以为CAN通道设置所需的比特率:

on start { 

  canSetBitrate(ch1, canBITRATE_250K); 

  canSetBitrate(ch2, canBITRATE_500K); 

  canSetBusOutputControl(ch1, canDRIVER_NORMAL); 

  canSetBusOutputControl(ch2, canDRIVER_NORMAL); 

  canBusOn(ch1); 

  canBusOn(ch2); 

} 

如果您使用软件监控总线,则在软件中进行配置。如果需要两个以上的通道,可以为这些通道添加更多的“CanMessage”hooks。

将某些报文ID转移到另一个通道:
我们可以使用以下hooks轻松地根据ID进行过滤。该hooks事件将只发送一个11位ID 1019(十进制)的报文到CAN通道2。

on CanMessage <ch1> 1019 { 

  canWrite(ch2, this); 

} 

从CAN转到CAN FD:
从CAN转到CAN FD(反之亦然)更加复杂。您无法直接复制报文,而是需要重新将报文格式化为CAN FD格式。

在本例中,我们将CAN 通道2设置为CAN FD,标称比特率为1 mb/s,数据段比特率为2 mb/s。CAN通道1接收的任何报文都将被传输为CAN通道2的CAN FD格式,而CAN通道2的任何CAN FD报文都将被重新格式化为CAN 格式,以便在通道1上发送。本例中CAN和CAN FD的DLC均为8。在更高级的示例中,在传输报文时还需要考虑CAN和CAN FD之间的其他差异,如CAN FD帧大于8个数据字节。

variables{
  const int ch1 = 0;
  const int ch2 = 1;
  CanMessageFd msgFD;
  CanMessage msg;
}
 
on start { 
  canSetBitrate(ch1, canBITRATE_250K); 
 
  canSetBitrateFd(ch2, canFD_BITRATE_2M_80P);
  canSetCommunicationMode(ch2, canMODE_CAN_FD);
 
  canBusOn(ch1); 
  canBusOn(ch2); 
} 
 
on CanMessage <ch1> *{
  if ((this.flags & (canMSG_RTR | canMSG_ERROR_FRAME)) == 0) { 
     msgFD.id = this.id;
     if ((this.flags & canMSG_EXT) != 0) { 
       msgFD.flags = canMSG_EXT; 
     } 
     
     msgFD.flags = 0;
     msgFD.dlc   = 8; 
     msgFD.data  = this.data;   
     
     canWrite(ch2, msgFD); 
   } 
 
} 
 
on CanMessageFd <ch2> *{  
  if ((this.id & canMSG_ERROR_FRAME) == 0) {  
     msg.id = this.id; 
     msg.flags = 0; 
     if ((this.id & canMSG_EXT) != 0) { 
        msg.flags = canMSG_EXT; 
     } 
     
     msg.dlc   = 8; 
     msg.data  = this.data; 
 
     canWrite(ch1, msg); 
   } 
 } 

on stop{
  canBusOff(ch1);
  canBusOff(ch2);
}

以上所有这些有什么用途?
您无需购买全新设备作为网关,并且可以使用现有的、具有兼容性的Kvaser设备作为网关。Kvaser的t脚本语言允许使用现有硬件灵活地解决常见问题,以便节省您的时间和资源。

这只是使用支持t脚本的设备和几行代码就能解决问题的一个示例。如需了解更多示例,请参阅我们的其他DevBlogs

*也就是说,如果您的设备被用作USB通讯仪,在程序运行时从电脑上拔下设备会导致t脚本停止运行。

此外,由于t脚本调度程序每次只能处理一个非定时hooks事件,因此在处理报文时会有1 ms的延迟。在某些情况下,如果同时发送多条报文,可能会推迟执行,因为调度程序会报文以1 ms的处理间隔逐一处理每一条报文。请在将本示例集成到您的网络时考虑到上述内容。

Author Image

Adam Raymer

Adam Raymer是Kvaser公司的一名现场应用工程师,公司总部位于美国底特律附近。Adam定期会见客户,是我们全球支持团队中的一个活跃成员。