CANoe入门——10、CAPL基础(6)_CAPL常用库函数介绍

CAPL提供了非常多样的库函数供我们进行使用,其中有的函数是我们较为熟悉的,如settimer,output等,这些我们已经知道函数的用法和功能了,但是,在实际使用CANoe中,我们更多的时候关心的是总线上的数据以及这些数据的处理,所以,我们有必要知道一些其他的常用函数。
一、使用CAPL函数帮助手册

        CAPL的帮助手册中有着众多函数的用法及其示例,我们先来看下如何使用CAPL的帮助手册(函数库)

打开CAPL函数库帮助手册

在CAPL浏览器中找到Layout菜单栏,点击红框中的CAPL Function,随后CAPL浏览器的右侧就会出现CAPL函数帮助界面

点击CAPL Function切换到函数帮助手册视图,可以看到上面有几大函数的分类

任意点击一个分类展开这个分类下的函数

我们可以看到,通用分组下有着我们先前已经使用过的几个最常用的函数

canceltimer、settimer、output和write。在前文中我们已经对这几个函数进行了使用,比如

output(meaageframe);

但是我们并没有深究,并不知道这些函数到底应该怎么使用,只是我在文章中对他的使用进行了说明,现在,我们以CAPL帮助手册的视角来学习一下这个函数该怎么使用。

这里,我已settimer函数为例子,鼠标点击settimer函数,右下角就会出现类似红框的界面(CANoe版本不同,界面会稍微有一点差别,总体上是一样的),随后我们点击右边的问号图标,打开这个函数的说明。

在Function Syntax中我们可以看到这个函数具有三种重载形式(不懂重载什么意思的,可以简单的认为就是这个函数的几种不同的用法)

分别是

这个函数可以接受两个参数也可以接受三个参数

下面有CANoe官网给的简单示例,告知这个函数的简单用法。

从参数列表中,可以看到这个函数的几个参数

mstimer t:一个mstimer定时器

timer t:一个秒级别定时器

duration:定时器持续的时间,即定时器超时时间

durationsec:定时器超时时间的秒

durationnanosec:定时器超时时间的纳秒

这三种 用法我们都有涉及,接着以一小段代码进行下简单示例

variables
{
  message 0x123 testmsg;
  msTimer TaskmsTimer;//ms定时器
  
  timer TaskTimer;//s定时器
  
  timer TaskTimer2;//s定时器2
}

on key'A'
{
  setTimer(TaskmsTimer,500);//设置定时器500ms超时
}

on key'B'
{
  setTimer(TaskTimer,1);//设置定时器1S超时
}

on key'C'
{
  setTimer(TaskTimer2,1,500*1000*1000);//500纳秒*1000*1000  即500ms   1s+500ms,即1.5s执行一次   
}

on key'D'
{
  cancelTimer(TaskmsTimer);//关闭定时器
  cancelTimer(TaskTimer);
  cancelTimer(TaskTimer2);
}

on timer TaskmsTimer
{
  setTimer(TaskmsTimer,500);
  output(testmsg);
}

on timer TaskTimer
{
  setTimer(TaskTimer,1);
  output(testmsg);
}

on timer TaskTimer2
{
  setTimer(TaskTimer2,1,500*1000*1000);//500纳秒*1000*1000  即500ms   1s+500ms,即1.5s执行一次
  output(testmsg);
}

运行工程,先按下大写字母A,我们通过trace窗口看看0x123的周期

周期为500ms,符合我们在A事件中写的逻辑代码。使用D关闭定时器之后,我们再按下B看下现象

报文周期为1S,也是我们想要的效果。再次使用D关闭定时器之后,我们按下C看看

报文周期为1.5s,符合我们填写的参数。

至此,我们已经通过CAPL函数库学会了settimer函数的使用,是否也掌握了CAPL函数库的使用呢?

CAPL函数库中有着非常非常多的功能函数,这里就不再继续教大家怎么去看了,各位可以自行查阅CAPL函数帮助手册

如图,从左侧点击需要查看的大类展开,随后再次展开里面的小项即可对CAPL中的所有帮助内容进行查看了。

或者,可以在帮助手册中进行关键字的搜索。

根据关键词快速搜索到相关的函数。

二、CAN总线类函数

CAPL中提供了非常多的用于CAN总线的函数

这里只对常用的几个进行介绍

canGetDataLength(返回指定CAN报文的长度)

函数原型:long canGetDataLength(message msg);

用法示例

on message *
{
  byte len;
  len = canGetDataLength(this);//this指针,指代事件本身,在这里指代这个收到的CAN报文。
  write("收到的CAN报文长度为:%d",len);
}

在这里,我使用CAN IG模块向总线上发送一条CAN报文

在CAN总线上,点击红色连接线,右键鼠标,选择新建一个CAN IG模块。

 左键双击新建的CAN IG节点,进入CAN IG界面。

在CAN IG界面右键选择添加一个CAN帧

给新建的CAN帧一个id  我这里是0x321,可以看到我的dlc为8

随后,启动工程。点击图中的红色箭头手动发送一次0x321

在write窗口可以看到,代码中打印出了总线上收到的CAN帧0x321的长度为8,正确的。

我们再次在CAN IG中修改这个dlc为5看一下

再次按下按钮手动发送一帧0x321

write中又打印了刚刚收到的CAN帧的长度为5。

以上就是这个函数的用法。

getMessageID(返回CAN报文的ID)

函数原型:

dword getMessageID(char messageName[]); // form 1

dword getMessageID(char messageName[], char dbName[]); // form 2

用法示例:

on message *
{
  word id;
  id = getMessageID("Test");
  write("收到的CAN报文id为:%d",id);
}

注意,此函数的参数的message需要在dbc中有定义。

我在dbc中定义了一个名为Test的CAN帧,ID为0x123。

随后,在CAN IG中添加这个报文并发送试一下

选择从dbc中添加报文。

添加完成后,启动工程发送试一下

解析到了报文ID、

三、LIN总线类函数

linStopScheduler  用于停止CANoe自动运行LIN的调度表,常用于需要暂停发送LIN报文的场景,比如需要停发LIN报文一段时间后测试ecu是否休眠,常用此函数。

函数原型:void linStopScheduler();

linStartScheduler 用于开始CANoe自动运行LIN的调度表

函数原型:void linStartScheduler();

linChangeSchedtable 用于切换运行的调度表

函数原型:

long linChangeSchedTable(dword tableIndex);

long linChangeSchedTable(dword tableIndex, dword slotIndex);

long linChangeSchedTable(dword tableIndex, dword slotIndex, dword onSlotIndex);

常用于在APP调度表和诊断调度表中互相切换。

linGotoSleep LIN总线休眠函数

函数原型:long linGotoSleep();

本质上调用该函数后,会由CANoe自动向总线上发送一个LIN的通用休眠帧。

linWakeup LIN总线唤醒函数,调用该函数本质上是向LIN总线上发送一个250~5000us的低电平。

long linWakeup(); // form 1

linWakeup(dword ttobrk, dword wakeupSignalCount, dword widthInMicSec); // from 2

linGetDlc  获取指定LIN帧的长度

函数原型:long linGetDlc(long frameID);

linGetChecksum 获取指定LIN帧或者错误帧的校验和

函数原型

byte linGetChecksum(linFrame linFrame); form 1

byte linGetChecksum(linCSError linCsError); // form 2

四、数学运算类函数

_max 返回数据中的最大值

函数原型:

long _max(long x, long y); // form 1

dword _max(dword x, dword y); // form 2

int64 _max(int64 x, int64 y); // form 3

qword _max(qword x, qword y); // form 4

float _max(float x, float y); // form 5

用法示例

on key' '
{
  byte max;
  
  write("max=%d",_max(36,85));
}

_min 返回数据中的最小值

函数原型:

long _min(long x, long y); // form 1

dword _min(dword x, dword y); // form 2

int64 _min(int64 x, int64 y); // form 3

qword _min(qword x, qword y); // form 4

float _min(float x, float y); // form 5

示例:

on key' '
{
  float min;
  
  write("min=%f",_min(36.6,_min(58.2,12.3)));
}

可以看到,返回了最小值为12.3

_pow 返回x的y次幂

函数原型:double _pow(double x, double y);

用法示例

on key' '
{
  float res;
  
  write("res=%f",_pow(3,4));
}

random 产生指定范围的随机数

函数原型:dword random(dword num);

用法示例

on key' '
{
  dword num;
  
  num = random(100);//产生0到100之间的额随机数
  
  write("本次产生的随机数为%d",num);
}

其他的数学运算函数,大家就自己去使用吧

五、字符串处理类函数

strlen 返回字符串的真实长度

函数原型 long strlen(char s[]);

on key' '
{
  char str[16] = "你好世界";
  
  
  write("字符串str的长度为%d",strlen(str));
}

我的CAPL中编码方式为utf8,而在utf8编码中,一个中文占3个字节,这里总共四个中文字符,所以总长占12字节,返回值正确。

strnact 字符串黏贴函数,用于将一个字符串粘贴至另一个字符串的末尾。

函数原型:void strncat(char dest[], char src[], long len);

on key' '
{
  char str[16] = "你好世界";
  char isp[32] = "hello word";
  
  strncat(isp,str,elcount(isp));
  
  
  write("字符串isp的内容为%s",isp);
}

可以看到,isp已经变成了hello word你好世界,str被黏贴到了isp后面。

strncpy 字符串拷贝函数,用于把一个字符串复制到另一个字符串中。

函数原型:void strncpy(char dest[], char src[], long max);

on key' '
{
  char str[16] = "你好世界";
  char isp[32] = "hello word";
  
  strncpy(isp,str,elcount(isp));
  
  
  write("字符串isp的内容为%s",isp);
}

可以看到,经过strncpy操作后,isp的内容由"hello word"变为了"你好世界",str的数据被拷贝到了isp中。

strncmp 判断字符串是否相等

函数原型:

long strncmp(char s1[], char s2[], long len); // form 1

long strncmp(char s1[], char s2[], long s2offset, long len); // form 2

on key' '
{
  char str[16] = "你好世界";
  char isp[32] = "你好世界";
  
  byte result;
  
  result = strncmp(isp,str,elcount(isp));
  
  if(result == 0)
    
  
  
  write("字符串str与isp相等");
}

这里定的了str和isp,数据是一样的,仅长度不同,在数据上他们是相等的,所以返回了0,即这两个字符串相等。

ltoa 将数字以字符串形式显示,即将数字转换为字符串。

函数原型:

void ltoa(long val, char s[], long base);

on key' '
{
  word num = 365;
  char str[4];
  
  ltoa(num,str,10);
  write("str=%s",str);
}

可以看到,我已经把num转换成了字符串,使用的%s输出。

atol 将字符串转换为数字,与ltoa相反。

函数原型:long atol(char s[]);

on key' '
{
  char str[5] = "4567";
  word num;
  num = atol(str);
  
  write("num=%d",num);
}

可以看到,调用这个函数我们把字符串“4567”转换成了数字4567

_atoi64 将字符数组转换为64位整数

函数原型:int64 _atoi64(char s[]);

on key' '
{
  char numstr[10] = "123456789";
  
  int64 num;
  
  num = _atoi64(numstr);
  
  write("num = %ld",num);
}

可以看到,这里把字符数组(字符串“123456789”)转换成了一个64位整数。

六、其他常用函数

stop 结束正在运行的CANoe工程。

函数原型:void stop();

getSignal 获取指定的信号的物理值。

函数原型:float getSignal(Signal aSignal); // form 1

此函数调用的结果等同于直接使用$来取信号。

setSignal 设置指定的信号的物理值

函数原型:void setSignal(Signal aSignal, double aValue); // form 1

此函数调用的结果等同于直接使用$取信号给信号赋值。

putvalue 给环境变量赋值(高版本中已经废弃环境变量,此函数也随之被废弃)

用法为:putvalue(EnvVar,Num);其中envvar是环境变量的变量名,num是要赋予的值。

getvalue 获取环境变量的值(高版本中已经废弃)

函数原型:float getvalue(Envvar);

系统变量赋值函数

使用对应的函数可以为对应的类型的系统变量进行赋值。

比如,为一个double类型的系统变量赋值

使用 sysSetVariableFloat

函数原型:

long sysSetVariableFloat(char namespace[], char variable[], float value); // form 1

long sysSetVariableFloat(SysVarName, float value); // form 2

注意:使用此类函数,在使用系统变量作为参数时,需要先指定命名空间,否则代码会报错。

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值