CANOE入门:CAPL语言常用事件和函数

目录

查看函数文档

常用函数及示例

 发送CAN报文函数 output 

获取Signal值和MessageID

在Write窗口打印数据

获取Signal的值

修改已有信号的值并发送

信号触发事件

定时事件

完整的示例代码


查看函数文档

查看方法:在CAPL编辑界面中找到CAPL函数助手,查找到相应的函数,在函数简介的下方小窗口内的右上角点开。这里以output()函数为例,演示如何查看函数文档。

CANOE入门:CAPL语言常用事件和函数_第1张图片

 在弹出的窗口中,可以看到函数的详细介细,包括入参,出参,示例等。

CANOE入门:CAPL语言常用事件和函数_第2张图片

常用函数及示例

 发送CAN报文函数 output 

简介:output()函数用于往CAN总线上发送CAN报文,入参为message结构体,发送前需要定义所有相关的参数,比如报文ID,报文dlc,data中各个有效字节的内容等等。

//键盘事件:按下对应的键触发
on key 'a'
{
  message 0x401 msg1;  //报文id和名称
  msg1.dlc = 8; //设置有效载何长度
  msg1.byte(0) = 0x02;  //字节0的内容
  msg1.byte(1) = 0x02;  //字节1的内容
  msg1.byte(2) = 0x03;  //字节2的内容
  msg1.byte(3) = 0x04;  //字节3的内容
  msg1.byte(4) = 0x01;  //字节4的内容
  msg1.byte(5) = 0x01;  //字节5的内容
  msg1.byte(6) = 0x01;  //字节6的内容
  msg1.byte(7) = 0x01;  //字节7的内容
  output(msg1);  //发送报文到总线上
  write("键盘事件..."); //在CANoe的屏幕上打印
}

获取Signal值和MessageID

函数getSignal()和getMessageID(),可以获取获取Signal值和MessageID

includes
{
  
}

variables
{
   int signalValue; //信号值
   dword MessageID; //报文ID

}

//报文事件:收到指定报文触发
on message 0x3E9
{
  signalValue = getSignal(Key_region_Signal); //获取指定信号的值
  write("收到信号Key_region_Signal值为:%hx\n",signalValue);
  
  MessageID = getMessageID("PEPS_Region_on"); //获取指定报文的ID
  write("收到报文ID值为:%hx\n",MessageID);
}

在Write窗口打印数据

使用write()函数可以在CANoe的Write窗口中打印需要显示的数据。这个函数可以理解为C语言的print()函数,打印格式也是一样的。

获取Signal的值

通过$+信号名称即可以获取信号当前的值

//获取当前Signal的值
//通过$+信号名称即可以获取信号当前的值
on key 'b'
{
  //访法1:直接访问
  sig = $Key_region_Signal;
  write("收到信号值为:%hx\n",sig);
  
  //方法2:前面加Mesage(主要用于区别总线中同名的信号)
  sig = $PEPS_Region_on::Key_region_Signal;
  write("收到信号值为:%hx\n",sig);
}

修改已有信号的值并发送

直接在事件中定义一个报文,通过报文属性的方式修改报文中信号的值。

//修改DBC中信号的值并发送
//注:这种方法只适用于DBC文件中已定义的信号
on key 'c'{
  message BCM_Message msg_bcm;
  msg_bcm.bcm_Signal_of =11; //改对应信号的值
  output(msg_bcm);
  write("c");
}

信号触发事件

CAPL中,信号触发事件有两种触发方式,分别为on signal和on  signal_update两种触发方式。区别如下:

on signal 监测到信号变化则触发

on signal_update 监测到信号即触发

如何理解呢?举个例子,有一个信号bcm_Signal_of,当ECU启动后总线上发送次序如下的信号

bcm_Signal_of = 1

bcm_Signal_of = 0

bcm_Signal_of = 0

bcm_Signal_of = 1

bcm_Signal_of = 1

两分事件分别触发的情况如下:

on signal 触发     on signal_update触发

on signal 触发      on signal_update触发

on signal 不触发  on signal_update触发

on signal 触发      on signal_update触发

on signal 不触发  on signal_update触发

由上面可以看出,on signal事件是只要信号值发生改变时都会触发包括信号从无到有的那一次,也即只第一次发送也会触发,因为这种情况下相当天信号从0变为1。on signal_update则可以理解为,只要总线监测到有这个信号就会触发,不论这个信号的值是否改变。

定时事件

在使用CAPL时,有时候需要执行一些定时任务,比如其个报文20秒后执行,或者在CAPL启动1小时后自动退出程序等。这个时候就需要用到定时事件。

定时事件需要使用on timer事件,同时需要配置定时器msTimer,这个定时器单位为ms。还需要配合触发定时器的事件,on key和on start事件。

/*@!Encoding:936*/
includes
{
  
}
variables
{
   msTimer Timer1; //定时器
   
}
//定时事件:需要配合setTimer()函数使用。
on key 's'{
  //设置定时器时间,单位为毫秒
  setTimer(Timer1,1000); 
}

on timer Timer1
{
  write("定时事件");
  setTimer(Timer1,1000); //再次设置,可以实现循环
}

需要注意的是 setTimer()函数设置成功后,on timer只会执行一次,执行完成后即会失效。如果需要周期性的执行同一个事件,则需要在执行完业务代码后再调用setTimer()一次,让程序进入下一个执行周期。上面的示例通过按键s事件触发,如果不想要这种方式,可以通过on start事件触发,可以实现程序启动即触发定时器。

另外,如果需要实现周期性执行,还可以通过setTimerCyclic()函数进行设置。函数的和参如下

void setTimerCyclic(msTimer t, long firstDuration, long period); 

传入一个msTimer,从firstDuration开始每隔period时间间隔后执行。

/*@!Encoding:936*/
includes
{
  
}

variables
{
   msTimer Timer1; //定时器
   
}
//定时事件:配合setTimerCyclic()函数使用。
on key 's'{
  //设置定时器时间,单位为毫秒
  //第一次在1000ms后执行,后面每次间隔2000ms执行
  setTimerCyclic(Timer1,1000,2000); 
}

on timer Timer1
{
  write("定时事件");
}


上面的示例则可以更简洁的完成一些周期性的操作。建议一次性执行的任务选择setTimer()函数,周期性执行的任务选择setTimerCyclic()。

完整的示例代码

/*@!Encoding:936*/
includes
{
  
}

variables
{
   int signalValue; //信号值
   dword MessageID; //报文ID
   dword msgName ;
   int sig;
   int i;  
   msTimer Timer1; //定时器
   
}

//键盘事件:按下对应的键触发
on key 'a'
{
  message 0x401 msg1;  //报文id和名称
  msg1.dlc = 8; //设置有效载何长度
  msg1.byte(0) = 0x02;  //字节0的内容
  msg1.byte(1) = 0x02;  //字节1的内容
  msg1.byte(2) = 0x03;  //字节2的内容
  msg1.byte(3) = 0x04;  //字节3的内容
  msg1.byte(4) = 0x01;  //字节4的内容
  msg1.byte(5) = 0x01;  //字节5的内容
  msg1.byte(6) = 0x01;  //字节6的内容
  msg1.byte(7) = 0x01;  //字节7的内容
  output(msg1);  //发送报文到总线上
  write("键盘事件..."); //在CANoe的屏幕上打印
}

//报文事件:收到指定报文触发
on message 0x3E1
{
  signalValue = getSignal(Key_region_Signal); //获取指定信号的值
  write("收到信号Key_region_Signal值为:%hx\n",signalValue);
  
  MessageID = getMessageID("PEPS_Region_on"); //获取指定报文的ID
  write("收到报文ID值为:%hx\n",MessageID);
  
  
}

//获取当前Signal的值
//通过$+信号名称即可以获取信号当前的值
on key 'b'
{
  //访法1:直接访问
  sig = $Key_region_Signal;
  write("收到信号值为:%hx\n",sig);
  
  //方法2:前面加Mesage(主要用于区别总线中同名的信号)
  sig = $PEPS_Region_on::Key_region_Signal;
  write("收到信号值为:%hx\n",sig);
   
}

//修改DBC中信号的值并发送
//注:这种方法只适用于DBC文件中已定义的信号
on key 'c'{
  message BCM_Message msg_bcm;
  msg_bcm.bcm_Signal_of =11; //改对应信号的值
  output(msg_bcm);
  write("c");
}


//信号值发生改时触发
on signal bcm_Signal_of
{
  write("信号值发生改变");
}

on  signal_update bcm_Signal_of{
  write("信号值发送时触发");
}


//定时事件:需要配合setTimer()函数使用。
on key 's'{
  //设置定时器时间,单位为毫秒
  //第一次在1000ms后执行,后面每次间隔2000ms执行
  setTimerCyclic(Timer1,1000,2000); 
}

on timer Timer1
{
  write("定时事件");
}

你可能感兴趣的:(汽车)