1、CAPL概述
提到CAPL,相信各位一定不陌生,它是由Vector公司开发的类似于C语言的面向过程编程语言,是CANoe和CANalyzer中可用的编程语言。CAPL中程序块的执行由事件控制,在专用的编译器中开发和编译,这样可以访问数据库中的所有对象以及系统变量,作为汽车电子工程师,在工作中会经常用到。
(1)主要用途:
2、CAPL开发环境
2.1、CAPL浏览器简介
以CANoe自带了一个CAPL程序的开发环境CAPL Browser(CAPL浏 览器)为例:
CAPL浏览器界面由功能区、程序框架浏览树、输出窗口、编辑区、访问区五部分组成。
2.2、功能区介绍
Home功能区:提供了CAPL编译常用功能,包括代码编译、查找、替换、屏蔽、取消屏蔽等功能。
Filter功能区:作用是管理CAPL的函数库,可以在函数访问区中屏蔽掉不需要的函数
Debug功能区:调试的区域,提供了一些基本的调试操作,一般情况下不通过debug模式来调试脚本。基本上编译一次,存在错误可以通过Output输出窗口获得错误类型并进行更改。如果脚本编译成功之后,仍然不能满足测试步骤的输出,一般会使用Write窗口进行调试。
3、数据类型
3.1、变量的声明和定义
(1)变量名
命名规则与C语言类似,必须注意遵循合法性、有效性 和易读性的原则。合法性主要体现在以下几条。
(2)关键字
关键字是计算机语言中的词汇,都是CAPL专用的, 不能用作他用。
注意: 编译器不区分CAPL自带的关键字和函数名的大小写
(3)全局变量与局部变量
全局变量
局部变量
3.2、简单变量
(1)整型
整数就是没有小数部分的数字,如3、201、-3412和0。根据数值 的大小不同,CAPL提供了以下几种整型,
(2)字符
区别于C语言,CAPL未将char类型(长度1B)归类至整型中,这是因为在CANoe中提供了byte类型。如果数据是具体数值则应使用 byte,而对于字符,则应用char(字符串使用char数组)。char类型 和byte类型之间可以直接转换,例如:
CAPL中Char用于表示ASCALL码字符,如S19文件名 char s19FileName[200];
Byte是CAPL中的一个特殊的类型,用于表示字节数据比如存放4个字节的安全校验种子,byte seedFlash[4]
(3)浮点型
CAPL提供两种浮点型变量:float和double,
3.3、符合变量
(1)结构
CAPL中可以简单地按照C语言的方法来声明结构( ),但结构名在程序中必须是唯一的。简单类型、枚举类型或者其他的结构都可以作为结构的成员。
(2)数组
数组(Array)作为一种基本的数据结构,也同样被CAPL支持, 就像在C语言中一样。但为了方便使用,CAPL支持直接用字符串初始化字符数组的行为。例如:
(3)枚举
枚举的成员名必须唯一,否则将有可能代替隐藏数据库中同名的报文和信号。如果没有在声明枚举的同时对成员进行赋值,编译器将按照成员声明的顺序对成员进行初始化。即第一个成员被初始化为0,往后依次加1。
3.4、特殊类型
(1)报文
使用关键字message来声明一个报文变量,当使用message声明报文变量时,默认变量为CAN报文变量。当有数据库支撑的时候,一 个 完 整 的 声 明 应 该 包 括 message ID 或 者 message name 。结 合 database的例子,使用ID 0xA或者报文名来声明一条数据库中的 EngineData报文。例如:
CAN报文属性及相关信息
如果需要在CAN1网络上发送一条指定的报文,报文名:magicMessage;报文ID:0x252;包含8个字节0x03 3B 40 00 00 00 00 00;可以定义如下。
(1)系统变量
系统变量是一种特殊的变量,用来描述某种特殊状态(例如某种 事件触发)或者记录测量数据。一般有系统定义和用户自定义两种, 它们的作用域都是在各自的命令空间内。
系统变量的类型
(1)定时器
CAPL 提 供 了 两 种 定 时 器 变 量 : timer 基 于 秒 的 时 间 单 位 ; msTimer基于毫秒的时间单位,例如:
作用:定时器在CAPL中的作用是提供一种灵活的机制,用于执行周期性任务、延迟执行任务以及处理定时事件,帮助实现复杂的控制逻辑和任务调度。
功能举例:实现特定报文在总线上的周期发送。
4、CAPL常见运算
与C语言一样,CAPL也提供了算术、逻辑和位运算的运算符,其用法也与C语言保持一致。
5、流程控制
有C语言基础对C语言中的流程控制不陌生,流程控制 分为顺序结构、选择结构和循环结构。CAPL是基于事件的编程,顺序 结构只在某个事件中有效,而选择和循环结构则在CAPL中起着更加重 要的作用。
(1)选择程序结构设计
if语句:根据给定条件的真假来决定是否执行特定的代码块。
switch语句:根据不同条件执行不同代码块的控制结构。
(2)循环结构程序设计
while语句:用于重复执行一段代码,只要给定的条件为真(非零)。
condition是一个表达式,它决定了是否继续执行循环体语句。如果condition为真,则执行循环体语句,然后再次判断condition的值。如果condition为假(即为0),则跳出循环,继续执行后面的代码。
for语句:用于循环执行特定代码块的迭代控制语句。
初始表达式:在循环开始前执行的一次性代码。通常用于初始化循环计数器或设置其他必要的变量。
循环条件:每次循环开始前被检查的条件表达式。如果条件为真(非零),则执行循环体;如果条件为假(零),则跳出循环。
更新表达式:在每次循环结束后执行的表达式。通常用于递增循环计数器或改变其他必要的变量。
6、CAPL程序结构
6.1、事件处理
CAPL采用了面向事件的机制,通俗来说就是,在什么条件下,在什么时间节点,发生了什么样的报文传递,得到了什么样的报文反馈。而这种面向事件的机制是通过event handler来实现的。
事件起始关键字on *
on后面加某种条件,一旦条件满足则执行下面函数体内的语句。 函数体内的语句是实现接下来需要完成的操作。
关键字this
在CAN报文事件中或变量事件中,可以使用关键字this访问数据内容
这里的this即为message 100(ID为100的报文变量)
主要事件类型
6.2、常用事件
(1)CAN报文事件
指在CAN总线上有指定的或任意报文出现时被调用。 关键字为:on message xxx。
(2)定时器事件
在测量的过程中,通常需要由用户来触发某些事件来模拟实际测试环境的人工操作,例如,开始记录log、改变信号或变量的值、停止测量等。利用CAPL提供的键盘事件可以方便地完成这些操作。键盘事件的关键字为 :on key xxx。
7、常用函数库
CAPL提供了一个强大的函数库,针对一些不常用的函数,需要使用的时候可使用F1查阅帮助文档。
8、CAN变量和信号的访问
(1)信号的访问
signal在CAPL中代表的是总线信号交互层的表示,它不同于message。message是CAPL的数据类型,而signal不是。因此,不能在CAPL中定义一个类型为signal的变量。当用户需要访问信号缓冲区并期望读到最后接收到的信号值时,可以使用$符号,例如:
(2)系统变量的访问
格式:@变量空间名字::变量名
(3)环境变量的访问
格式:@变量名
也可以用getValue()和putValue()访问变量的值,比如:
9、CAPL程序调试
(1)CAPL程序的Debug功能调试
注意:Debug Mode只适用于Simulated Bus模式, 否则在Debugger窗口中无法开启Debug Mode。
Variables窗口区,查看断点代码中各种变量(系统变量、环境变量、当前节点 程序中的局部或全局变量、报文的相关参数等)的状态,也可以将想要观测的变量添加到Watch窗口区查看。
Debug Mode只适用于Simulated Bus模式,否则在 Debugger窗口无法开启Debug Mode,所以CANoe仿真工程开发过程中就面临一个问题:无法在真实网络相联的时候使用Debug Mode。 对于这种情况可以使用write相关输出函数,在特定位置输出变量值或字符串提示信息输出到Write窗口,来帮助自己调试CAPL程序。
write函数输出格式定义
write函数是基于C语言函数中的printf,其输出格式也很相似
例子:
10、CAPL编程实例
实例一:实现周期发送报文
需求:实现报文在总线上的周期发送;帧ID:0X7E2,长度:8字节,发送周期:100ms
代码实现:
}
variables
{
message 0x7E2 Diag_Req_VCU;//定义要发送的报文
msTimer Tx_timer;//定义一个毫秒定时器
}
on start //系统事件start,程序执行时触发
{
setTimer(Tx_timer,100);//运行canoe程序,设置定时器时间间隔,
// 定义时间为100ms,定时器开始记时启动
}
on timer Tx_timer//定时器事件,当定时器运行到达设定的时间间隔时,
//将触发该事件,这时on timer函数中的程序块将被执行。
{
Diag_Req_VCU.dlc = 8;//定义该报文长度
Diag_Req_VCU.byte(0)=0x03;//定义报文数据
Diag_Req_VCU.byte(1)=0x19;
Diag_Req_VCU.byte(2)=0x02;
Diag_Req_VCU.byte(3)=0xFF;
Diag_Req_VCU.byte(4)=0x00;
Diag_Req_VCU.byte(5)=0x00;
Diag_Req_VCU.byte(6)=0x00;
Diag_Req_VCU.byte(7)=0x00;
output(Diag_Req_VCU); //输出该报文到CAN总线
write("data:%x",Diag_Req_VCU.byte(0));//输出Diag_Req_VCU首字节16进制数据
setTimer(Tx_timer,100); //重置定时器,周期性触发需要在每次触发结束后使用SetTimer复位.
}
Trace窗口:
实例二:实现自定义报文发送
项目开发流程:
项目需求:
代码框架:
测试panl Trace界面:
项目源码资源及搭建过程:CAPL编程教学实战-(实现列表报文选择发送和自定义报文发送)-CSDN博客
(3)实例三:基于UDS_DID读取
项目需求:
功能实现:
程序框架:
测试界面:
项目源码资源及搭建过程更新中,尽情期待!!!!!