技术博客

05/04/2016 作者 Logan Via

在配置中添加脚本和触发器

这是使用Kvaser Memorator第二代设备通过kvmlib进行配置和读取记录数据4篇系列文章的第二篇:

  1. kvmlib入门指南
  2. 在配置中添加脚本和触发器
  3. 深入了解kvmlib
  4. 使用kvmlib配置SD卡

在第一篇文章中,我们讲述了如何使用kvmlib通过可记录所有内容的简单配置对设备进行设置。现在让我们通过添加一个t程序和一些触发器来增加我们配置的复杂性。全部程序列表可在GitHub上获得。

2.1 准备t程序以添加至配置中

让我们准备t程序,为了测试目的,要生成一些CAN流量并添加到配置中。此脚本实际上是测试的一部分,该测试中我们能够对使用触发器控制记录的开始和结束进行验证。从脚本启动的0.5秒开始,脚本本身每秒发送一条CAN报文。对于每个发送的CAN报文,CAN报文标识将会增加1。在CAN总线上总共可以发送11条CAN报文。

// This script is intended to be used to check a configuration set as:
//
// [ ] Log everything
// [ ] FIFO mode
// Power settings: 5 Time to live after CAN power disconnected, in seconds
//
// CAN 1 should be connected to CAN 2
//
// Triggers:
// CAN1 Trigger1 Timer [4s] : Start logging, post-trigger=0
// CAN1 Trigger2 Timer [7s] : Stop logging, post-trigger=3000
//
// Script sends msg id:
// Id 1 at 0.5s
// Id 2 at 1.5s
// Id 3 at 2.5s
// Id 4 at 3.5s
// Id 5 at 4.5s
// ... and so on until
// Id 11 at 10.5s

variables {
  // Base channel. CAN messages will be sent on channel ch and received on
  // channel ch + 1
  const int ch = 0;

  // The singleshot timer is used to get a delay before the first CAN message
  // is sent.
  Timer singleshot;

  // The periodic timer is then used between each CAN message
  Timer periodic;

  // The message id of the sent CAN messages, will be incremented
  int msgId = 1;

  // The CAN message to be sent
  CanMessage msg;
}

on Timer singleshot {
  // Start the periodic timer to send 10 more CAN messages
  timerStart(periodic, 10);

  // After using the current CAN message id, increment before next use
  msg.id = msgId++;
  msg.flags = 0;
  msg.dlc = 8;
  msg.data = "\x12\x21\x13\x31\x22\x34\x41\x15";

  // Send CAN message
  canWrite(ch, msg);
  printf("Single shot MsgId: %d\n", msg.id);
}

on Timer periodic {
  // After using the current CAN message id, increment before next use
  msg.id = msgId++;

  // Send CAN message
  canWrite(ch, msg);
  printf("Periodic MsgId: %d\n", msg.id);
  if (!timerIsPending(periodic)) {
    printf("Timer done!");
  }
}

on start {
  printf("Starting testlogger companion script\n");

  // Setup the two CAN channels and go bus on.
  // This will override the settings in the binary configuration,
  // most notably the channels will no longer be in silent mode.
  canBusOff(ch);
  canBusOff(ch + 1);
  canSetBitrate(ch, canBITRATE_1M);
  canSetBitrate(ch + 1, canBITRATE_1M);
  canSetBusOutputControl(ch, canDRIVER_NORMAL);
  canSetBusOutputControl(ch + 1, canDRIVER_NORMAL);
  canBusOn(ch);
  canBusOn(ch + 1);

  singleshot.timeout = 500; // Wait half a second
  periodic.timeout = 1000; // One second period

  // Start the singleshot timer to send the first CAN message
  timerStart(singleshot);
  printf("Start periodic transmission\n");
}

on stop {
  printf("Stopping script\n");
  canBusOff(ch);
  canBusOff(ch + 1);
}

列表7:生成CAN报文的示例t程序

t程序需要在添加到配置之前进行编译。t编译器称为“scc.exe’”,当安装CANlib SDK时通常放在“C:\Program Files (x86)\Kvaser\Canlib\Bin\scc.exe”。如果在没有任何参数的情况下调用,将打印使用帮助。

scc.exe
No input file found.
Script compiler for Kvaser t-script.
This is version 3.3.305 built on Sun Dec 13 19:38:53 2015.
Usage:
scc [-v -verbose] [-c] [-g] [-dx] [-devlines]
[-addsrc] [-comment=XXX]
[-pkey=N] [-skey=K]
@<filename>] [-dbase=<filename>] <filename>
where
-c Compile only. No output is produced.
-dbase=XXX.dbc Use the database XXX.dbc to define CAN messages
in the script.
-devlines Supress line numbers in generated code. Generates faster and
smaller code, but line numbers cannot be reported in exceptions.
-g Generate symbol tables for debug.
-addsrc Include the source code.
-comment=XXX Include the comment XXX.
Note that spaces can be used in arguments "like this".
Encryption of script and source code:
Script and source are protected by a symmetric crypto (-skey). The
symmetric key is then protected by a public key crypto (-pkey).
-pkey=N Use Kvaser public key number N.
Default:
0 - (no encryption) if no skey is entered
2 - (1024 bit RSA) if a skey is entered
-skey=K Use the symmetric key K.
If no K is entered and a pkey is, a random key K (hex)
will be generated for you
Key K formats:
-skey=0x11223344FFACAC - Hexadecimal format.
-skey=mysecretkey - ASCII format.
Contains multiple-precision arithmetic code originally written by
David Ireland, copyright (c) 2001-8 by D.I. Management Services Pty Limited
, and is used with permission.

我建议你总是使用-comment参数(在描述文本旁保存程序版本号)进行编译,还可以选择 -addsrc,它可将sourcet程序附加到生成的.txe文件。.txe文件可以使用Kvaser TRX打开,它是用于为Kvaser设备开发t程序的轻量级集成开发环境,如果使用-addsrc参数进行编译,源代码将显示在Kvaser TRX内置的.txe检查器的Source选项卡中。如果要隐藏脚本,可以使用加密。

scc.exe myCanGenerator.t -addsrc -comment="My CAN generator program v1.0"

列表8:在添加注释和源代码的同时编译t程序

scc.exe myCanGenerator.t -addsrc -comment="My CAN generator program v1.0"
Source size: 2516 bytes
Compilation succeeded

2.2 创建配置

现在我们已经编译了t程序“myCanGenerator.txe”,让我们创建一个包含编译的t程序的配置,并设置两个触发器。配置是以XML格式编写的,具体见文档Kvaser Memorator设备配置XML格式规范。我们创建配置,在通道0和1上将波特率设置为1Mbps,在CAN通道0或1上添加CAN报文标识3的触发语句,并在CAN通道1上为CAN报文标识6添加第二个触发语句。我们指定第一个语句应直接开始记录,第二个语句应在延迟2.5秒后停止记录(通过使用posttrigger)。

使用此设置,将CAN 1连接到CAN 2,并要考虑到我们的脚本每秒发送一个CAN报文,预期的结果是捕获CAN报文3到8。日志记录从CAN报文标识3开始,并在CAN报文标识6停止,但是由于我们有一个2.5秒的posttrigger,CAN报文标识7和8也预期在日志文件中结束。

XML配置中特别注意的一个标记是标记BINARY_VERSION,它在创建用于下载到设备的二进制配置时由转换库使用。我们的设备(运行固件版本3.0)应使用二进制配置格式v6.0。

有关XML格式的详细信息,请参阅Kvaser Memorator设备配置XML格式的规范

<?xml version="1.0" ?>
<!DOCTYPE KVASER>
<KVASER>
  <VERSION>2.0</VERSION>
  <BINARY_VERSION>6.0</BINARY_VERSION>
  <SETTINGS>
    <MODE fifo_mode="NO" log_all="NO"/>
    <CANPOWER timeout="5000"/>
  </SETTINGS>
  <CAN_BUS>
    <PARAMETERS bitrate="1000000" channel="0" silent="YES" sjw="1" tseg1="5" tseg2="2"/>
    <PARAMETERS bitrate="1000000" channel="1" silent="YES" sjw="1" tseg1="5" tseg2="2"/>
  </CAN_BUS>
  <TRIGGERBLOCK>
    <TRIGGERS>
      <TRIGGER_MSG_ID can_ext="NO" can_fd="NO" channel="0" msgid="3" msgid_min="3"
       name="trigger_0" protocol="NONE" timeout="0"/>
      <TRIGGER_MSG_ID can_ext="NO" can_fd="NO" channel="1" msgid="6" msgid_min="6"
       name="trigger_1" protocol="NONE" timeout="0"/>
      <TRIGGER_MSG_ID can_ext="NO" can_fd="NO" channel="1" msgid="3" msgid_min="3"
       name="trigger_2" protocol="NONE" timeout="0"/>
    </TRIGGERS>
    <STATEMENTS>
      <STATEMENT posttrigger="0" pretrigger="0">
        <EXPRESSION>trigger_0 OR trigger_2</EXPRESSION>
        <ACTIONS>
          <ACTION_START_LOG/>
        </ACTIONS>
      </STATEMENT>
      <STATEMENT posttrigger="2500" pretrigger="0">
        <EXPRESSION>trigger_1</EXPRESSION>
        <ACTIONS>
          <ACTION_STOP_LOG/>
        </ACTIONS>
      </STATEMENT>
    </STATEMENTS>
  </TRIGGERBLOCK>
  <SCRIPTS>
    <SCRIPT default_channel="0" primary="YES">
      <FILENAME>myCanGenerator.txe</FILENAME>
      <PATH></PATH>
    </SCRIPT>
  </SCRIPTS>
</KVASER>

列表9:XML配置示例

2.3 验证配置

如果发现任何错误,即使从XML配置到二进制配置的转换会失败,我仍然建议使用kvaMemoLibXml显式验证XML配置。当你创建未包含任何表达式以启动日志记录的配置时,此验证会给你警告。调用验证后,我们可以读出检测到的错误和警告的数量,以及每个的代码和文本摘要。

xl = kvaMemoLibXml.kvaMemoLibXml()
print "kvaMemoLibXml version: v" + xl.getVersion()

# Read in the XML configuration file
with open("config.xml", 'r') as myfile:
    config_xml = myfile.read()

# Validate the XML configuration
xl.kvaXmlValidate(config_xml)

# Get number of validation messages
(countErr, countWarn) = xl.xmlGetValidationStatusCount()
print "Errors: %d, Warnings: %d" % (countErr, countWarn)

# If we have any validation errors, print those
if countErr != 0:
    code = -1
    while code != 0:
        (code, text) = xl.xmlGetValidationError()
        print "%d: %s" % (code, text)

# If we have any validation warnings, print those
if countWarn != 0:
    code = -1
    while code != 0:
        (code, text) = xl.xmlGetValidationWarning()
        print "%d: %s" % (code, text)

# Exit if we had any validation errors or warnings
if countErr != 0 or countWarn != 0:
    raise Exception('Please fix validation Errors/Warnings.')

列表10:验证XML配置

这篇文章对配置增加了的一些复杂性,在下一篇文章,我们将回到kvmlib,看看如何调用kvmlib在C语言API级别运行。

Author Image

Logan Via