CANoe自带的CAPL Browser是CAPL程序的开发环境。学习CAPL基本语法之前,先来认识下CANoe是如何创建CAPL程序。
3.1 创建CAPL程序文件
1)进入CAPL浏览器:CANoe主界面Tools → CAPL Browser
CAPL程序的文件后缀为.can
3.2 浏览器功能区
1)Home功能区:提供CAPL编译常用功能,包括代码编译以及编译等操作
2)Filter功能区:管理CAPL函数库,可在函数浏览器中屏蔽掉不需要的函数库
3)Debug功能区:提供CAPL编程常用功能,包括代码编译以及变异操作等
注:断点组件智能在debug模式开启的情况下进行操作
4)Layout功能区:设置各子窗口的显示模式
基本上学习所有的语法思路都是差不多的,首先是变量与全局变量、数据类型、支持的运算符、流程控制语句以及函数等。
4.1变量的声明与定义
注:CAPL关键字分类
4.2 全局变量与局部变量
全局变量
局部变量
4.3简单变量
4.4 复合类型
结构 struct
枚举 enum
数组 Array
4.4 特殊类型
报文
诊断报文
diagRequest ServiceQualifier request;
diagResponse ServiceQualifier response;
注:1)以上语句声明了队形request 和 response,通过给出诊断服务ServiceQualifier进行初始化;2)使用*代替ServiceQualifier,可用于初始化未添加诊断描述的空对象,但是在发送之前对象的数据必须完成具体设置
系统变量
定时器
6.1 if语句
If (表达式) 语句;
If (表达式) 语句1; else 语句2
6.2 switch语句
Switch (表达式):
{
Case 常量表达式1: 语句1;
Case 常量表达式2: 语句2;
……
Case 常量表达式n: 语句n;
Default: 语句n+1;
}
6.3 while语句
Do
循环语句;
While(表达式)
6.4 for语句
For (<初始化>; <条件表达式>; <增量>) 语句;
6.5 break语句
6.6 returen语句
7.1头文件
Includes
{
}
includes
{
#include "CommonFunction.cin"
#include "BaseServices.cin"
}
7.2 全局变量的声明
Variables
{
}
variables
{
int i =0;
message 100 msg;
msTimer myTimer;
byte ECU_Serical_Number[3]= {0x31, 0x32, 0x33};
}
7.3 事件处理 event handler
CAPL采用面向事件的机制满足CANoe对于CAN通信网络建模、仿真、测试和开发。
事件起始关键字on *
On * /On 后加条件语句,比如message XXX或者是Timer XXX等
{
语句; /实现接下来要含完成的操作
}
关键字this
在CAN报文事件或者变量事件中,用this访问数据内容,
on message 100
{
byte byte_0;
byte_0 = this.byte(0);
}
这里的this指代的是前面说的报文100,总之this指代的就是前面提到的事件或者数据。
系统事件
CAN控制器事件
CAN报文事件
CAN信号事件
或者 on signal_update xxx(每次接收到指定信号时均被调用)
定时事件
variables
{
message 0x555 msgl; //将报文0x555起名为msgl
msTimer myTimer; //声明一个毫秒计时器
}
on start
{
setTimer(myTimer,100); //将定时值设置为100ms并启动
}
//定时器超时,触发以下事件
on timer myTimer
{
serTimer(myTimer, 100); //复位定时器
msgl.byte(0) = msgl.byte(0) +1; //报文0x555的第一位上数据增加1
output(msgl); //发送报文0x555
}
键盘事件
这个事件是用来定义一些在键盘上输入某些字母或者数字,来实现快捷操作的目的。
格式为:On key xxx
//以下事件定义了在键盘上敲击S,write窗口会打印语句“Logging Starts"
on key 's'
{
write("Logging Starts");
}
错误帧事件
//以下语句定义了系统变量DI_O改变时,触发以下事件
on sysVar IO::DI_O
{
$Gateway::IOValue1 = @this;
}
//以下语句定义了系统变量DI_O更新时,触发以下事件
on sysvar_update IO::DI_O
{
$Gateway::IOValue2 = @this;
}
CAPL其实自身有一个很强大的函数库,几乎可以满足用户绝大部分的需求,包括一些:
同时,用户可可以根据自己的需求,自定义一些满足自己独特需要的函数
CAPL因为支持总线数据库,所以可以直接访问数据库已定义的报文(message)名称、类型和标识符等属性。访问语法如下:
on message 数据库中报文的名字
{
此处写要执行的动作;
}
刚开始看CAPL代码对于一些XXX::XXX以及@XXX以及$XXX的表述感觉很奇怪,看不进去。后面才搞清楚了这是CAPL访问数据的特殊表达方式,今天就在这里好好总结一下:
信号、系统变量和环境变量都可以被直接访问和赋值,只是方式稍微有些不同
访问信号
虽然不能通过CAPL定义一个信号,但是却可以通过CAPL访问信号的值,只是我们访问信号的值一般在信号名字前面加上$符号,比如:
a = $EngineSpeed; //将信号EngineSpeed的值赋给变量a
b = $EngineSpeed.raw; //将信号EngineSpeed的物理值赋给变量b
$VehicleSpeed = 80; //将信号VehicleSpeed的值设置为80
有时候也见过这种表达:
$Gateway::VehicleData::VehicleSpeed
这也是信号的一种表达方式,即 节点::报文::信号,这是为了避免重名的信号出现,在前面加上节点、报文也是为了更精确的引用。比如一个学校有好几个叫小明的,你指定是六年级::一班::第三排::王小明,一般就不会找错了。
完成的引用格式是:
channel::Node::Message::Signal
顺便介绍以下这种格式输入的好用的方法:
在要输入信号的CAPL程序位置,点击右键,如下操作,会跳转至数据库文件,找到自己要引用的信号,这样就不用手输入了。变量也是同理。
还有一种常用的又不会出错的引用信号的方式是:
VehicleData.VehicleSpeed = @this; //VehicleData报文底下的信号VehiclSpeed
访问变量
格式:@变量空间名字::变量名
if((@Engine::Gear ==2)&&(@Power::KeyState==2))
a = @EngineSate; //直接访问
环境变量也是如此,不过我们也可以用getValue()和putValue()访问变量的值,比如:
a = getvalue(EngineSpeed); //读取变量EngineSpeed的值并将其赋值给变量a
b = putvalue(EngineSpeed); //输出变量EngineSpeed的值并将其赋值给变量b