CANoe入门——5、CAPL基础(1)_CAPL介绍
静听夜半雨 2024-08-29 13:35:01 阅读 93
CAPL(Communication Access Programming Language)是一种专门用于CAN(Controller Area Network,控制器局域网络)通信和诊断的脚本语言,要想熟练地使用Vector系列的软件,离不开CAPL的帮助。
目录
一、CAPL语言的特点
二、CAPL的编辑环境和CAPL浏览器
三、CAPL中支持的数据类型
四、CAPL中的关键字(保留字)
五、CAPL中变量的声明
六、CAPL程序代码是如何执行的?
七、CAPL常见事件的使用和触发
一、CAPL语言的特点
基于C语言:CAPL的语法基于C语言,但包含了一些特定的功能和语法结构,用于处理CAN通信。对于熟悉C语言的开发人员来说,学习和使用CAPL相对较为简单。事件驱动:CAPL是一种过程性的事件驱动语言,其执行由事件触发,如定时器事件、消息事件、系统变量事件等。丰富的函数库:CAPL提供了丰富的库函数和API,用于操作CAN消息、节点配置、信号解析和其他与CAN相关的操作。实时性:CAPL支持实时执行,可以在通信网络中模拟实时事件和响应,以验证ECU(Electronic Control Unit,电子控制单元)的实时性能。可扩展性:CAPL支持自定义函数和变量,开发人员可以根据特定需求扩展CAPL的功能。
二、CAPL的编辑环境和CAPL浏览器
在CANoe的Simulation Steup界面,选中一个节点,随后点击节点左下角的铅笔图标,即可打开CAPL编辑器
随后在打开的界面中,选择一个路径用于保存这个CAPL代码文件,并为这个.can文件取一个名字即可
打开后弹出CAPL浏览器,如图所示。
三、CAPL中支持的数据类型
CAPL是一种类C/C++语言,继承了C/C++中大部分的语法,也定义了一些CAPL独有的数据类型。
数据类型主要分为以下几种:
数值类型:
byte(字节类型,长度8bit,无符号)
word(字类型,长度16bit,无符号)
dword(双字类型,长度32bit,无符号)
qword(整形,长度64bit,无符号)
int(短整型,长度16bit,有符号)
long(长整型,长度32bit,有符号)
int64(整形,长度64bit,有符号)
字符类型:
char(字符类型,长度8bit,可以表示字符,可以和byte类型直接互相转换)
浮点数(小数类型):
float(单精度浮点数,长度64bit,有符号)
double(双精度浮点数,长度64bit,有符号)
CAPL定义的特殊数据类型,以下只列出常见的几种
message :用于定义CAN报文
linframe:用于定义LIN报文
timer/mstimer:用于定义一个秒级别定时器和毫秒级别定时器
ethernetPacket:用于定义一个以太网报文包
pdu:用于定义一个pdu
diagrequest:定义诊断请求
diagresponse:定义诊断响应
复合类型:
结构体类型,声明方法与C/C++基本相同,可以表示一个包含了不同数据类型的对象。
枚举类型,声明方法也与C/C++相同,常用于表示某个变量的几种取值结果
数组:
CAPL支持定义除了复合类型以外的其他所有类型的数组,需要注意的是,CAPL在声明数组时必须指定数组的长度。
四、CAPL中的关键字(保留字)
关键字(keyword)是CAPL中预定义的一些单词或者字符,这些关键字被编程语言本身预定义并赋予特殊含义的单词或标识符。这些关键字在编程语言中有特定的用途,不能用作变量名、函数名或其他标识符的名称。不同的编程语言有不同的关键字集合,但通常都包括用于控制程序流程(如循环、条件判断)、声明数据类型、定义函数或类等的关键字。
常见的关键字如下
五、CAPL中变量的声明
CAPL中的变量分为全局变量与局部变量
全局变量在整个.can文件内,所有的地方都可以使用,只能在全局变量定义区定义
局部变量可以在任一事件、函数内定义,同时,局部变量的作用域只在当前事件或函数内有效,且局部变量的定义,必须在事件或函数的最上方,后续会给出说明。
基础数据类型变量定义的语法:
变量类型+空格+变量名;或者 变量类型+空格+变量名+等于号+一个值。
<code>int Intnumber;//定义短整型变量number,由于定义时没有给number指定值,默认是0
//定义时进行赋值
byte Bytenumber = 0;//定义字节型变量number,并为他显示赋值为0
char CharC= 'C';//定义字符变量CharC,并为他赋值为大写字符C
CAPL定义的特殊数据类型的变量声明语法:
/*CAN报文变量声明
message + 空格 + 报文ID(16进制或者十进制都可) +空格+变量名。
message + 空格 + DBC中的报文名字 + 空格 + 变量名
第一种声明方式,不管是否有DBC都可以进行声明
第二种声明方式,需要DBC中有名称为DoorStsFrame 的CAN报文才可以使用这种方式进行声明
*/
message 0x300 Can_0x300Msg;//第一种定义方式,使用ID号进行声明,声明一个ID为0x300,变量名为Can_0x300Msg的CAN帧。
message DoorStsFrame DoorStsMsg;//第二种定义方式,使用DBC中CAN报文的名称进行定义
/*
LIN报文变量声明,方法与CAN报文变量声明几乎一致,区别仅在于声明所使用的关键字不同
linframe +空格 + 报文ID + 空格 + 变量名
Linframe +空格 + LDF中的LIN报文名称 + 空格 + 变量名
*/
linframe 0x20 Lin_0x20Frame;//第一种声明方式
linframe DoorLinStsFrame DoorLinStsMsg;//第二种声明方式,此方式也需要LDF中有名称为DoorLinStsFrame 的LIN报文。
/*
定时器变量声明
声明方式为
timer + 空格 + 变量名
mstimer + 空格 + 变量名
*/
timer Timer1;//声明一个秒级别定时器timer1
mstimer Timer2;//声明一个毫秒级别定时器timer2
/*
其他自定义类型的声明后面再叙述,前文还未铺垫至此
*/
复合类型变量的声明方法:
/*
数组声明方法
数组类型 + 空格 + 变量名+[数组元素个数];
*/
int intArray[2];//声明一个具有两个短整型元素的短整型数组
byte byteArray[5];//声明一个具有5个字节型元素的字节型数组
double doubArray[4]//声明一个具有4个双精度浮点数元素的双精度型数组
/*
结构体声明方法
struct + 空格 +结构体名称{
里面如同普通类型一样定义即可,需注意的是,里面每个元素定义时也需有分号结尾
}
*/
struct myStruct{
int a;
byte b;
float c;
message 0x80 Can_0x80Msg;
};
/*
枚举定义
enum + 空格 + 枚举体名称+{}
枚举在定义时,可以给里面各个元素赋值,也可以不进行赋值。
如果不进行赋值,默认枚举的第一个元素为0,后面的其他元素挨个值加一,第二个元素为1,第三个元素为2...
也可以根据自己的需要进行赋值,被赋值的枚举元素的值为赋予的值,其后面的元素为这个值加一
*/
enum Color{
red,green,blue
};//这个枚举中,red的值为0,green为1,blue为2
enum Day{
Mon=1,Tues=2,Wed,Thur,Fri,Satu,Sun
};//这个枚举中,Mon为1,Tues为2,其他后面的依次为34567
enum myEnum{
num1,num2=5,num3,num4=9
};//这个枚举中,num1为0,num2为5,num3为6,num4为9
六、CAPL程序代码是如何执行的?
CAPL是一个基于事件驱动的编程语言,所有的代码都需要在相应的事件被触发时才能执行。
CAPL中常用的事件主要有以下几个
CANoe预启动事件:preStart事件
CANoe启动事件:Start
CANoe测量停止事件:preStop
总线上收到CAN报文事件:message
定时器超时事件:timer
总线上收到LIN报文事件:linframe
键盘事件:key
我们的CAPL代码想要执行,必须在一个事件以内,并且写在事件区外的代码是非法的。
可以看到,在事件内的代码 int a;编译是没有错的。
而在事件之外定义的 int b;被系统提示有语法错误。
这进一步说明了CAPL的代码只能在事件内执行。
七、CAPL常见事件的使用和触发
CAPL事件的语法为
on +空格+事件类型(有的事件还需要加上具体事件的名称)
接下来通过在CANoe的Write窗口打印一句话来说明各个事件如何触发
例如
on start 表示程序启动时执行
<code>on start
{
write("启动事件被触发了");//write()的功能是向CANoe的write窗口输出信息
}
随后点击编译图标,编译代码
左侧的按钮编译当前的can文件,右侧按钮编译CAPL浏览器打开的所有can文件,我们使用左侧得到编译当前文件
编译完成后启动CANoe工程,随后打开CANoe的write窗口查看
单击home栏目下的write按钮,即可打开write窗口。
可以看到,write窗口下打印了我们刚刚写的话,说明CANoe启动之后,刚刚编写的代码被执行了。
on preStop 表示在CANoe工程测量结束时执行的事件
我们还是使用向write窗口打印一句话来看看这个事件的执行
<code>on preStop
{
write("CANoe停止事件被触发了");
}
随后编译代码,启动CANoe工程。
我们发现,CANoe启动的时候,write窗口没有任何信息。
当我们暂停CANoe工程后,write窗口打印了刚刚写的话
on key 键盘按键事件 在键盘上对应的按键被按下时触发
<code>on key'A'
{
write("键盘上的大写字母A被按下了");
}
编译后启动工程
随后我们按下大写字母A,可以看到,on key'A'中的代码被执行了。
上一篇: C++第四十一弹---C++11新特性深度解析:让你的代码更现代、更高效(上)
下一篇: 【problem】解决“Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token”错误
本文标签
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。