技术博客

17/09/2018 作者 Magnus Carlsson

为配置添加脚本和触发点

本文是共包括4部分的技术博客的第二部分。此博客介绍通过kvmlib语言,使用第二代Kvaser Memorator数据记录仪,配置和读取已记录的数据:

1 开始使用kvmlib

2为配置添加脚本和触发点

3 进一步了解kvmlib

4 用kvmlib配置SD卡

在本博客的第一部分我们介绍了如何使用kvmlib简单地配置一个设备,以记录所有数据。现在我们通过添加一个 t 程序和一些触发点,来增加这个配置的复杂程度。所有程序列表都可在GitHub上看到。

2.1 为现有配置准备一个 t 程序

让我们用一个t 程序生成一些CAN通讯,并把它加到现有配置上做测试。这个脚本实际上是一个测试的一部分,在这个测试中,我们证明数据记录的开始和结束可以通过触发点来实现。此脚本自身每秒钟发送一个CAN报文,在此脚本开始后0.5秒时开始此操作。这一CAN报文的id号是依次序列递增,每发送一个CAN报文添加1。总计有11个CAN报文被发送到CAN总线上。

// 这个脚本是用来检测一套如下配置:
//
// [ ] 记录所有事件
// [ ] FIFO 模式
// 电源设置:在 CAN 电源断开后延续5次, 以秒计
//
// CAN 1 应被连接到 CAN 2
//
// 触发点:
// CAN1 触发点1 定时 [4s] : 开始记录, 后触发=0
// CAN1 触发点2 定时 [7s] : 停止记录, 后触发=3000
//
// 脚本发送报文id:
// Id 1 在 0.5s
// Id 2在1.5s
// Id 3在2.5s
// Id 4在3.5s
// Id 5在4.5s
// ... 如此类推,直到 
// Id 11 在 10.5s

variables {
  // 基本通道。 CAN 报文将被发送到通道channel ch 上和在下面通道上接收
  // channel ch + 1
  const int ch = 0;

  // 这个一次单击定时器是用来在第一个CAN报文发送前有一个延迟。 
  Timer singleshot;

  // 这个周期定时器用来在CAN 报文之间定时
  Timer periodic;

  // 这个已发送CAN报文的 id, 将被依次递增
  int msgId = 1;

  // 将被发送的CAN 报文
  CanMessage msg;
}

on Timer singleshot {
  // 开始周期定时器,发送 10 个或更多 CAN 报文
  timerStart(periodic, 10);

  // 在使用当前 CAN 报文 id后, 在下一次使用前依次递增
  msg.id = msgId++;
  msg.flags = 0;
  msg.dlc = 8;
  msg.data = "\x12\x21\x13\x31\x22\x34\x41\x15";

  // 发送 CAN 报文
  canWrite(ch, msg);
  printf("Single shot MsgId: %d\n", msg.id);
}

on Timer periodic {
  //在使用当前 CAN 报文 id后, 在下一次使用前依次递增
  msg.id = msgId++;

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

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

  // 建立两个 CAN 通道并启动总线。
  // 这将覆盖二进制的设置,
  // 最主要的是通道将不再是安静模式。
  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; // 等待半秒钟
  periodic.timeout = 1000; // 一秒时间间隔

  // 启动单击计时器以发送第一个CAN 报文
  timerStart(singleshot);
  printf("Start periodic transmission\n");
}

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

列表 5: 一个简单的t 程序用以生成CAN 报文。

此 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 argument-注译函数(按住位于描述文字旁边,你的程序版本号码)来编译,而选择性地用 addsrc – 把 t 程序源代码添加到编译的 .txe 文件。一个 .txe 文件可以用Kvaser TRX1 打开 – 我们为Kvaser设备开发 t 程序的轻量级IDE(集成开发环境),而且如果由addsrc 变量编写,源代码将显示在Kvaser TRX 内置 .txe Inspector(检查器)的Source键下面。

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

2.2 生成配置

现在我们编译了 t 程序, `myCanGenerator.txe’,让我们生成一个包括这个t 程序的配置并建立两个触发点。此配置是以XML 格式书写的,如Specification of Kvaser Memorator Device configuration XML format– Kvaser Memorator设备配置XML格式说明 所示。 我们生成了一个配置,设置通道0和1的比特率为1 Mbit/s, 为CAN总线通道0和1的上的CAN 报文 id 3添加一个触发说明, 和为通道1的CAN 报文id 6添加一个触发说明。我们规定第一个说明应直接开始记录, 第二个说明在2.5秒的延迟后应停止记录 (通过使用后触发)。

通过这个设置, 连接 CAN 1 到 CAN 2 ,同时注意我们的脚本每秒发送一个CAN报文, 预计的结果是捕捉CAN报文3到8。数据记录从CAN报文id 3开始, 在CAN 报文id 6结束, 但是因为我们有一个2.5 秒的后触发, CAN报文id 7和8也预期被存储到记录文件中。

在这个 XML 配置中的特别注释标签之一是 BINARY_VERSION, 当生成这个二进制配置来下载到设备上,是通过转换功能实现的。我们的设备 (运行固件版本 3.0) 应使用二进制配置格式v6.0。

有关XML格式的更多信息, 请参阅 Specification of Kvaser Memorator Device configuration XML format 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>

列表 6: 范例XML配置。

2.3 验证配置

即使从XML配置到二进制配置的转换在发生任何错误时都会失败,仍然建议使用kvaMemoLibXml对XML配置进行显式验证。比如当你创建的配置没有包括任何要开始数据记录的说明时,此验证将向你发出警告。在调用验证之后,我们可以读取检测到的错误和警告的数量,以及每个错误或警告的代码和简述。

import canlib.kvaMemoLibXml as kvaMemoLibXml

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

# 读取 XML 配置文件
with open("config.xml", 'r') as myfile:
    config_xml = myfile.read()

# 验证 XML 配置
xl.kvaXmlValidate(config_xml)

# 获取验证报文
(countErr, countWarn) = xl.xmlGetValidationStatusCount()
print("Errors: %d, Warnings: %d" % (countErr, countWarn))

# 如果我们有任何验证错误, 打印它们
if countErr != 0:
    code = -1
    while code != 0:
        (code, text) = xl.xmlGetValidationError()
        print("%d: %s" % (code, text))

# 如果我们有任何验证警告, 打印它们
if countWarn != 0:
    code = -1
    while code != 0:
        (code, text) = xl.xmlGetValidationWarning()
        print("%d: %s" % (code, text))

# 如果没有任何验证错误或警告,那么退出
if countErr != 0 or countWarn != 0:
    raise Exception('Please fix validation Errors/Warnings.')

列表 7: 验证 XML 配置。

本文为配置添加了一定复杂性, 在下一部分我们将回到kvmlib,来看怎样进一步运用kvmlib。

注释

1Kvaser TRX工具是一个为Kvaser设备开发 t 程序的轻量级IDE(集成开发环境)。



本文已更新。 要查看原件,请单击下面的框。

Author Image

Magnus Carlsson

Margus Carlsson是Kvaser AB公司的软件开发人员,从2007年以来深度参与了Kvaser固件和软件的开发。他还为Kvaser的技术博客撰写了许多用流行的Python语言编写应用程序的文章。