CANoe之CAPL语言设计(一)
CAPL 全称为 Communication Access Programming Language,即通信访问编程语言。 它是Vector公司专门为CANoe开发环境设计的编程语言,在语法和概念上与C语言类似。 借助CAPL,用户可以编写程序并应用到网络的各个节点上,也可以利用CAPL编程加强 测量分析功能,以及搭建高效的自动化测试模块。
1. CAPL 的特点
CAPL类似C语言,与C语言在语法和结构上有很多相同之处,但也有一些其特殊的地方(主要表现在函数声明和调用)。 (1) 未定义返回类型,默认为void类型; (2) 像C++—样允许空的参数列表; (3) 像C++—样允许函数重载; (4) 参数检测与C++中一样; (5) CAPL提供一些自带的库函数; (6) CAPL编译时不对自带的关键字和自带的函数名做区分。
全局变量与局部变量 在CAPL中,全局变量需要被声明在variables部分,同时可以使用直接赋值方法进行初始化。如果没有初始化,编译器会执行自动初始化,默认值为0。全局变量的作用域包括整个CAPL文件以及与此文件有链接的其他CAPL文件。 与C语言不同,局部变量在CAPL中总是被静态地创建。这意味着初始化只在程序体启动时执行,当再次进入程序时,局部变量被假定是上一次跳出程序时的值。局部变量的作用域,仅限于当前函数体范围内,即该函数的大括号范围内。
关于以上全局变量和局部变量的描述,在这里使用一个示例说明:
// 在全局变量variables中定义int a
variables
{
timer cycle;
int a = 0;
}
// 设置一个定时器(秒),1s循环
on timer cycle{
setTimer(cycle, 1); // 复位定时器
demo();
}
// CANoe点击start选项时执行
on start{
setTimer(cycle, 1);
}
// 自定义一个函数体,使a自增;
demo(){
a++;
write("a = %d", a);
}
执行效果:a在循环过程中能够自增1
variables
{
timer cycle;
}
on timer cycle{
setTimer(cycle, 1);
demo();
}
on start{
setTimer(cycle, 1);
}
// 在自定义demo()函数体中定义int a,并直接赋值;
demo(){
int a = 0;
a++;
write("a = %d", a);
}
执行效果:出现了奇怪的现象,如果学过C语言的应该会觉得a为局部变量,每次执行demo()函数体,a 都会被赋值0,所以选择打印的结果应该为1。 下面我们再看另一种写法:
variables
{
timer cycle;
}
on timer cycle{
setTimer(cycle, 1);
demo();
}
on start{
setTimer(cycle, 1);
}
demo(){
// 先声明int a,再下一个语句赋值
int a;
a = 0;
a++;
write("a = %d", a);
}
执行效果: 由上示例可见:CAPL语言与C语言在局部变量这里有些差异,与C语言不同,局部变量在CAPL中总是被静态地创建。这意味着初始化只在程序体启动时执行,当再次进入程序时,局部变量被假定是上一次跳出程序时的值。
2、CPAL特有的类型
关于其他基础数据类型,这里不作描述。
2.1 报文
报文(CAN/LIN messages)是车载网络最基本的构成部分,CAPL提供了各种网络相对应的报文类。这里主要介绍CAN报文和LIN报文。
使用关键字message来声明一个报文变量,当使用message声明报文变量时,默认变量为CAN报文变量。当有数据库支撑的时候,一个完整的声明应该包括message ID或者 message name。
message OxA ml; // ID OxA (hex)
message 100 m2; // ID 100 (dec)
message EngineData m3; // name EngineData
以标识符“x”结尾的ID表示这是一个扩展帧ID,例如,100x。 而 “*” 则表明这条报文在声明时还不含有CAN ID。例如:
on message CAN1.* // event机制
{
message *msg; // 使用 "*" 声明报文
if(this.dir!=rx) // 判断报文是否为RX报文
return;
msg = this; // 将RX报文报文下来
}
注意:以这种方式声明报文,后期只有指定ID后,才能将msg发出去。
2.2 选择器Selector的使用
CAPL提供了一系列的选择器供用户按自己的意图去修改CAN Message属性。
关键字 | 描述 | 数据类型 | 访问权限 |
---|
AN | CAN报文传输的逻辑通道,有效值范围:1~32 | word | | MsgChannel | CAN报文传输的逻辑通道,有效值范围:1~32 | word | | ID | CAN报文标识符 | dword | | name | 报文在dbc文件中的名称 | char[] | readonly | DIR | 报文的传输方向: tx或rx | byte | | RTR | 远程帧的标志位 | | | DLC | 报文的数据长度,有效值范围:0~15 | byte | | Byte | 数据字节位有效值范围:0~63(8~63字节适用于CAN-FD) | byte | |
如果需要在CAN1网络上发送一条指定的报文,报文名:magicMsg,报文id: 0x250, 包含8个字节0x00 01 02 03 04 05 06 07;可以定义如下:
variables
{
message *magicMsg;
}
// CANoe点击start选项时执行
on start{
magicMsg.CAN = 1;
magicMsg.id = 0x250;
magicMsg.dlc = 8;
magicMsg.byte(0) = 0x00;
magicMsg.byte(1) = 0x01;
magicMsg.byte(2) = 0x02;
magicMsg.byte(3) = 0x03;
magicMsg.byte(4) = 0x04;
magicMsg.byte(5) = 0x05;
magicMsg.byte(6) = 0x06;
magicMsg.byte(7) = 0x07;
output(magicMsg);
}
执行上述工程后,可在CANoe Trace窗口看到如下报文信息。
说明:本发布文章为个人学习CANoe的学习笔记,学习中主要借鉴《CANoe开发从入门到精通》书籍以及Vector的官网资源。
|