在某些情况下,您可能需要合并两条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 v2、Kvaser USBcan Pro 4xHS或Kvaser Hybrid Pro 2xHS等设备,以下是启动脚本的步骤:
- 打开总线监控/总线分析软件
- 配置设备并打开通道
- 启动TRX并加载项目
- 在TRX中将设备设置为“在线”状态
- 在TRX中将t脚本下载到设备上
- 在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的处理间隔逐一处理每一条报文。请在将本示例集成到您的网络时考虑到上述内容。