CAPL基础脚本和实例
1. CAPL的编写界面
CAPL脚本是CANoe中一种类C的语言,需要与网络节点关联,也可以利用其加强测量分析功能,以及搭建高效的自动化测试模块。
2. CAPL基础
2.1 CAPL概述
CAPL的主要用途:
- 仿真节点或模块
- 仿真时间报文、周期报文或者附加条件的重复报文
- 使用PC键盘模拟操作按钮等人工操作事件
- 仿真节点的定时或网络事件
- 仿真多个时间事件,每个事件都有自己特定行为
- 仿真普通操作、诊断或生产操作
- 仿真物理参数或报文的变化
- 生成错误帧,评估模块和网络软件处理机制
- 仿真模块或网络错误来评估相关的防错机制
- 提供网络测试、诊断等功能测试库函数
CAPL语言有以下特性:
- 集成在CANoe中的开发环境,是CAN总线访问编程语言(CAN Access Programming Language);
- 类C语言,但也有一些C++特性(this指针,事件等);
- 像C++一样允许函数重载;
- CAPL提供一些自带很强大的库函数;
- 可以更方便访问dbc文件和系统变量;
- 通过事件驱动的语言;
这里先看一下CAPL语言的程序结构,主要包含了:头文件、全局变量、事件函数、自定义函数。
2.2 CAPL数据类型
2.2.1 变量的声明与定义
变量的命名的规则和C语言差不多,只不过要避开CAPL之中的关键字。
注:CAPL关键字分类(只是一部分):
- 数据类型关键字:int, byte, word, dword.
- 控制语句关键字:if, else
- 存储类型关键字:static, extern
- 其他关键字:const, message,timer
全局变量
在variables部分声明全局变量
可通过直接赋值进行初始化,如果没有初始化,编译器自动初始化为0
全局变量的作用域:整个CAPL文件以及与此文件有链接的其他CAPL文件
局部变量
局部变量被静态地创建,初始化只在程序体启动时执行,再次进入程序,局部变量被假定是上一次跳出程序时的值。
局部变量的作用域仅限于当前函数体范围内
2.2.2 简单数据类型
- 整型:byte(0-255),word, dword, gword, int, long, int64
- 字符:char, 可以和byte类型直接转换
- 浮点型
2.2.3 复合数据类型
结构体
4. 结构名在程序中必须唯一
5. 简单类型、枚举类型或者其他的结构都可以作为结构的成员
6. 结构体可以作为函数的入参,但是不能作为函数的返回值。
枚举
7. 枚举的成员名必须唯一(否则将有可能代替隐藏数据库中同名的报文和信号)
8. 如果没有在声明枚举的同时对成员进行赋值,编译器将按照成员声明的顺序对成员进行初始化(第一个为0,往后依次加1)
数组
9. CAPL直接用字符串初始化字符数组的行为
10. CAPL也支持多维数组
11. CAPL通过内建函数elCount(数组名)来获得数组成员的个数
12. CAPL中必须显式的定义数组的长度
13. 可以将数组作为函数的参数(例如: MyFunction(array[][]))
2.2.3 特殊数据类型
报文(message)
- 使用关键字message来声明一个报文变量,默认是CAN报文
- 声明报文变量,有数据库支撑时,完整的声明应包含message ID or message name(Message ID以x结尾的ID表示扩展帧)
- "*"表示这条报文在声明时还不含有CAN ID(表示一个不确定CANID的message变量)
- message可以作为函数的入参使用,具体代码如下:
/*标准帧*/
message 0x1AD msg1;//声明变量,can消息 十六进制
message 100 m2; //用消息id声明can消息 十进制
message *msg; //声明一个不确定CANID的message变量;
message EngineData m3; //用总线上加载的dbc数据库(EngineData)里消息名称声明can消息
message 0x100 msg1={DLC=8}; //定义消息数据长度
/*扩展帧*/
message 100x msg1; //消息id后面加x,表示扩展帧 十进制
message 0x123456x msg2; //消息id后面加x,表示扩展帧 十六进制
/*报文发送至总线上*/
message * msg1;
msg1.dlc = 8;
message.ID = 0x100;
output(msg1); //报文发送至总线上必须要有ID
on message 0x1AD
{
message *msg1;
msg1 = this;
}
byte CalcMessageData(message *msg) //message 作为函数的入参
{
return msg.byte(0);
}
诊断报文
- 通过诊断请求和诊断响应两个对象来实现和ECU之间的诊断服务交互
- 在声明诊断对象时进行初始化
diagRequest ServiceQualifier request;
diagResponse ServiceQualifier response;
注:1)以上语句声明了对象request 和 response,通过给出诊断服务ServiceQualifier进行初始化;2)使用*代替ServiceQualifier,可用于初始化未添加诊断描述的空对象,但是在发送之前对象的数据必