本文是共包括4部分的技术博客的第二部分。此博客介绍通过kvmlib语言,使用第二代Kvaser Memorator数据记录仪,配置和读取已记录的数据:
技术博客
为配置添加脚本和触发点
在本博客的第一部分我们介绍了如何使用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(集成开发环境)。