事件程序
capl是一种程序语言,其中程序块的执行由事件控制,这些程序块称为事件程序,每个事件程序对应一个事件,事件发生就会执行对应的事件程序
on *
收到任何消息,都能触发此事件程序
on envVar
环境变量改变,触发此事件程序(仅CANoe)
on sysVar/on sysVar_change
系统变量改变,触发此事件程序
on sysVar_update
系统变量值只要更新,即使不改变,也触发此事件程序
on sysVar/on sysVar_change和on sysVar_update的区别是什么
通过change和update这两个单词也能猜出来,一个是改变,一个是刷新,on sysVar/on sysVar_change是只有系统变量的值发生改变时触发,on sysVar_update是系统变量的值刷新时触发
什么意思
如果系统变量vSpeed值为3,我现在vSpeed = 4,那么它的值发生了改变,肯定会触发事件程序on sysVar/on sysVar_change的执行
那么on sysVar_update执不执行呢,也是执行的,因为vSpeed的值不只是改变了,也更新了,对吧
如果我现在vSpeed = 3,又会怎样呢
值没发生改变,还是3,那么on sysVar/on sysVar_change肯定不会触发执行
虽然值没改变,但是有没有更新,有的吧,我又赋值了一个新的3给它,所以会触发on sysVar_update的事件程序
on key
按一个键,触发此事件程序
按的是电脑的鼠标按键,记住,分大小写的
on * 对所有的按键有效,如果你想把多个键盘输入的处理合并到一个事件过程中,你可以用on * 和this关键字实现,代码如下
on key *
{
switch(this)
{
case 'a' : ... break;
case F10: ... break;
...
}
}
this在这里表示按键事件
这里提出一个疑问,如果on key 'a’和on key *同时存在,那么当使用键’a’时,会调用哪一个
调用on key 'a’的事件过程
一些特殊的按键对应的key code为:
ESC、F7、F8和F9在key事件程序中是不支持的
对于字符键,可以用单引号把字符括起来,或者是输入对应的key code键码值
对于功能键,可以使用符合标识符来表示它
on timer
运行定时器,触发此事件程序
可以在capl中定义时间事件,当时间事情触发时,将调用on timer程序
所以如果想调用on timer程序,必须先定义时间事件,然后触发它
capl中有两个计时器变量类型
- timer:以秒为单位
- msTimer:以毫秒为单位
定义完时间事件,如何触发呢,capl也提供了两种函数:
- setTimer:设置定时器执行时间,只执行一次
- setTimerCyclic:设置定时器循环执行时间
既然能设置定时器按规定的时间执行,也就可以取消定时器执行,可以通过调用函数cancelTimer
helper文档中提供了一个示例,在按下’a’键20毫秒后在总线上传输消息100
msTimer myTimer;
message 100 msg;
...
on key 'a' {
setTimer(myTimer,20);
}
...
on timer myTimer {
output(msg);
}
on signal
信号改变,触发此事件程序
on signal_update
接收到信号,触发此事件程序
on preStart
测量开始前,触发此事件程序
on start
程序启动时,触发此事件程序
on preStop
测量停止前,触发此事件程序
on stopMeasurement
测量停止时,触发此事件程序
on PDU
当接收到一个PDU时,触发此事件程序
在CANoe 10.0 SP4以上版本,支持
- can AUTOSAR PDUs
- Ethernet AUTOSAR PDUs
- SOME/IP PDU只能用于on PDU *
对于preStop处理,event处理和time处理来说,如果测试停止,也就是test module处于非活动状态的话,这些处理程序将不会在测试节点内执行
转义字符
当你想用char数组存储字符串时,需要在末尾保留一个char作为终止符(/0),所以char数组要比纯字符串长度要大一个元素长度
其他转义字符
关于回车与换行,有个有趣的知识点
在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。这就是“换行”和“回车”的来历
后来这两个概念又被搬到了计算机上,由于存储器太贵,科学家认为在每行末尾加两个两个字符太浪费了,加一个就行,于是,在不同的操作系统中出现了分歧:
- Unix:每行结尾只有“换行”,即“\n”
- Windows:每行结尾是“回车+换行”,即“\r\n”
- Mac:每行结尾是“回车”,即“\r”
在Windows系统中,回车键被当作“\r\n”来处理
“\r\n”其实也很好理解,当一行结束,先把光标移到行首,然后再移到下一行,就能保证光标位于下一行的最左侧,当然其他操作系统用一个字符来表示这两个意思
无条件事件程序
我们知道当接收到一条CAN消息时,能触发执行on message事件程序
那么当on message *和on message ID同时存在时,情况会如何,是两个程序都执行,还是只能执行一个,执行的是哪一个呢
通常,只有在程序中没有针对接收到的消息的特定事件程序时(on message),才会调用通用事件程序(on *)
什么意思
比如说,总线上接收到message 100,只有程序中没有on message 100这个事件程序,才会执行on message *的程序,如果有,on message *就不会执行
这就是为什么
on message 100
{
write("specific");
}
on message *
{
write("generic");
}
打印的结果只有“specific”
如果你想实现事件程序可以被调用,而不用管其他事件程序的影响,可以用[]实现“装箱”
比如说这样
on message 100
{
write("specific");
}
on message [*]
{
write("generic");
}
打印的结果为“generic”“specific”,可以看出先执行的是on message [*]
这里还要注意,对于事件程序而言,它们是没有先后顺序的
具有以下消息类型的事件程序都可以用“装箱”:
- message
- pg
- linFrame
- frSlot