两万字的CAPL语法基础,一篇文章带你入门

这篇具有很好参考价值的文章主要介绍了两万字的CAPL语法基础,一篇文章带你入门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • 🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用

  • 🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】

  • 🍅 玩转CANoe,博客目录大全,点击跳转👉

📘前言

  • 🍅 本章内容,面向CAPL初学者,超过两万字,超全超详细。

  • 🍅 本节内容大量引用,翻译下面的Vector 官方文档:capl_programming ,资料我放在下方公众号网盘了,有需自取!


    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


📙1 CAPL 简介

  • CAPL(发音为“kapple”),是 Communication Access Programming Language 的缩写。CAPL是基于C语言开发的,专门用于CANalyzer和CANoe工具环境,但是CAPL简化了C语言,移除了复杂的指针概念,和一些不常用的关键字等,也融入了一些C++的概念,比如函数重载等。就学习难度而言 CAPL < C< C++。

  • CANalyzer或CANoe工具本身无需CAPL程序,就足以执行简单的测量和分析。采用CAPL程序,大大扩展了CAN通信的测量和分析。
    如果没有CAPL,该工具无法执行的是涉及计时的分析。CAPL可以使分析更加高效

  • CAPL 脚本是基于事件驱动的,和常规语言不同,CAPL没有 main()函数,没有程序入口,任何事件都有可能触发CAPL脚本的执行,比如,按键事件,定时器事件,执行测试等;如果没有事件发生,那么CAPL程序是“闲置的”。
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

  • 任何语言都需要编译之后才能运行,我们编写CAPL 的IDE叫做 CAPL Browser ,是CNAoe 整个开发环境的一部分组件;因为CAPL Browser的整体结构基于事件的概念,并且是专门组织的围绕不同的事件类,软件开发过程比传统的组织要简单得多C程序。关于CAPL的事件结构更详细的解读,参考后面章节博客内容。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


📙2 CAPL 语法基础

🍅2.1 CAPL和C语言的主要不同点

  • 下图可以看出,C语言支持很多概念,CAPL都舍弃掉了,或者只取其一小部分支持,让CAPL语言更加简便和易懂
  • 比如CAPL是基础事件驱动的,所以不需要main()函数入口
  • 持指针操作,宏定义,头文件都不在支持
  • 下图有点老,博主基于CANoe 11版本,枚举和结构体类型都是支持的。
  • 在c语言中,使用函数之前,必须要进行声明,而CAPL是不需要的。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


Note
1,在CAPL中,默认所有的局部变量都是静态的,在C语言中,需要用关键字static 修饰的变量才是静态的。这一点新手在写脚本要特别注意 点击,了解 CAPL脚本中关于 局部变量 容易忽略的一点
2,void 在CAPL中只支持函数返回值类型,表示函数没有返回值
3,CAPL中使用了一些标准的C函数。这些函数通常是数学函数或字符串函数(例如,abs(),strncpy())已经在CAPL内部预定义了。
4,CAPL没有完整的ANSI C标准库,但它有CAPL特有的库,称为CAPL dll。dll编程需要有一定的编程经验
5,字符串数据类型在CAPL中不支持;但是,您可以使用字符数组(例如,char temp[6]= " Hello "😉。


🍅2.1 CAPL和C语言中等价的函数

  • 对于C程序员来说,了解一些等价的函数是很有帮助的。下面是一个类似的简明列表函数,但有关CAPL函数如何使用的更多详细信息,请参阅CAPL函数参考手册。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


🍅2.2 注释

  • CAPL 的注释方式和大多数语言都一样,都是通过 // 或者 /**/ 来实现的,下面四种注释方法都是合法的。
  • CAPL Brower中注释代码的默认快捷键 选中你要注释的代码,先按住组合键 Ctrl + K ,然后在按组合键Ctrl +C ; 解除注释是 先按住组合键 Ctrl + K ,然后在按组合键Ctrl +U ;
1. /* This is a comment.*/ 
2. /* This comment is spread 
 over two lines.*/

3. /* 
 You can do this, too. 
 */ 
4. // CAPL also accepts the C++ comment.

🍅2.3 变量的命名规范

  • 变量名、函数名和数组名可以由字母和数字和下划线组成,但是首字母不能是数字

  • 下面的命名都是合法的:
    sum
    number_of_units
    J5x7
    _sysflag

  • 下面的命名都是不合法的:
    int // because it is a reserved keyword
    sum$value // the $ is not a recognized character
    3Times // because a variable name cannot begin with a number
    number of units // because spaces are not allowed


🍅2.4 区分大小写

  • 在使用CAPL编写时,一定要记住,对于用户定义的变量,小写字母和大写字母是不同的变量

  • 下面三个变量是三个不同的变量
    input_1
    Input_1
    INPUT_1

  • 但是CAPL支持的关键字是不区分大小写的,比如 INT a; 和int a;是一样的。


🍅2.5 CAPL 关键字

  • 关键字不能用来命名变量或函数。CAPL使用C编程中保留的关键字语言。但是,CAPL不支持一些常见的C关键字。
    下面是保留关键字的列表,包括CAPL支持的和不支持的关键字
  • 本图较老,emum和struct现在是支持的。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


🍅2.6 CAPL 支持的数据类型

  • 下表列出了支持的部分数据类型,不全,不过足以介绍CAPL支持的基本数据类型,以及所占的字节数,还有是是有符号数等等。message 和timer等是CAPL独有的数据类型,这里不描述

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


🍅2.7 变量声明

  • CAPL 变量有局部变量和全局变量,在CAPL 中Variables中定义的是全局变量
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL
  • 数据类型float和double都是占8个字节,它们指定符合IEEE的64位浮点数标准,它们彼此兼容。
  • 变量的初始化在声明期间是可选的,定义的时候如果没有初始化,
    整形数据则默认是0;
    char 型默认是null ;
    message 类型默认的数据段是0;
    定时器timer ,不需要初始化
  • 下面的变量声明是合法的
char letter_a = “a”; 
int number_days_in_year = 365; 
message wake-up xxx; // 后面再说
timer one_second; // 定时器必须全局变量 后面再说
int j, k = 2; // 如果变量不初始化,默认j = 0 
double x = 33.7; 
char p;

🍅2.8 数据类型转换

  • CAPL支持类型转换,隐形和显性都可以
    -下面 第一个赋值语句使用隐形转换,即将1.6和1.7添加到结果3.3,但是sum是整形,所以自动截断,结果就是3
    -下面 第二个赋值语句使用显性转换,即1+1 =2 ,最后结果就是2
int sum; 
sum = 1.6 + 1.7; 
sum = (int) 1.6 + (int) 1.7;

🍅2.9 常量

  • 初始化一个变量意味着给它赋一个初始值或开始值。在CAPL中,这可以在同一行中完成变量声明。当值在声明期间赋值时,它们被视为常量

整形

  • 整形可以是十进制和十六进制
int value = 20; 
int value2 = 0x14; 



浮点数

  • 浮点数可以是十进制数,或者科学计数法,以下都是合法的
float value = 0.23; 
float value2 = 23E-2;
2.1 
2.1e0 
3.1415 
0.00034 
22e+3 
1E-6

字符

  • 字符常量 是用单引号,括起来的一个字符
char value = ‘B’; 
char value2 =8; 
char value3 =?;

  • CAPL支持使用ASCII字符集。上面的三个字符赋值可以用十六进制分别
char value = 0x42; 
char value2 = 0x38; 
char value3 = 0x3F;

字符串

  • 字符串常量由一系列由双引号括起来的一个或多个连续字符组成。
  • 字符串存储在char类型的数据元素数组中。最后一个元素包含空字符\0,即用于指示字符串的结束。
  • 要确保字符串数组定义时的大小总是字符串长度 + 1,因为结束符\0也占用一个字符
char value[30] = “Here’s a string in C and CAPL”; 
char value2[19] = “spaces are allowed”; 
char value3[31] = “with a tab escape sequence \t”;
  • 如果已经定义过了一个字符串数组,不可以直接给它赋值的,下面代码时不允许的
char value3[31] ;
value3 = “with a tab escape sequence ”;
  • 可行的一种方法,是通过CAPL自带的字符串操作函数实现
char value3[31]strncpy(value3,  “with a tab escape sequence ”, elcount(value3)); 

宏定义

  • 在C语言中,下面代码是合法的,但是在CAPL中是不可以的。
#define TRUE 1 
#define FALSE 0

🍅 2.10 数组

  • 数组时同一种数据类型的集合,元素必须小于等于指定的大小

  • 下面时26个字母,但是我们必须定义27个大小,因为数据类型时char , 结束符\0要占一个字节
    char alphabet[27] = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;
    我们通过下表索引可以获取数组中的数值,比如 alphabet[0] 就是 ‘A’

  • 整形或者浮点型数组,大小可以和声明的元素数量一致,比如
    int sample_data[4] = { 100, 300, 500, 600 };

  • 如果,定义时,数组没有完全舒适化,其余的用默认值0填充
    int sample_data[10] = { 100, 300, 500, 600 };

  • 也可以定义二维数组
    int M[4][5] = {
    { 10, 5, -3, 17, 82 },
    { 9, 0, 0, 8, -7 },
    { 32, 20, 1, 0, 14 },
    { 0, 0, 8, 7, 6 }
    };

  • 要确定数组中元素的数量,可以使用elCount()函数,如下面的例子所示:
    nt i, j;
    for ( j = 0; j < elCount(array); j++ )
    for ( i = 0; i <= elCount(array[j]); i++ )
    . . .


🍅 2.11 枚举类型

  • 枚举类型在CAPL中定义的方式与在C中完全相同
enum Colors { Red, Green, Blue }; // 默认 从 0开始,每个元素+1
enum State { State_Off = -1, State_On = 1 }; //可以指定值
  • 定义完成后,可以直接使用enum的成员变量
on key 'c'
{
  enum Colors { Red, Green, Blue }; // 默认 从 0开始,每个元素+1
  write("Colors red : %d",Red);
  write("Colors Green : %d",Green);
}
//输出结果
Program / Model	Colors red : 0
Program / Model	Colors Green : 1
  • 当对枚举类型初始化变量后,有两种方法给枚举变量赋值,如下脚本
  • 可以通过 enum.Name() 可以获取变量当前值对应的元素名字
on key 'c'
{
  enum Colors { Red, Green, Blue }; // 默认 从 0开始,每个元素+1
  enum Colors color; //定义枚举变量
  color = Green;
 # color = (enum Colors)1;//也可以通过 强制类型转换,将整形数据转为枚举类型赋值
  write("colors is %s and value is : %d",color.Name(),color);
  //输出结果
  Program / Model	colors is Green and value is : 1
}

🍅 2.12 结构体数据类型

  • 结构体在CAPL中定义的方式与在C中完全相同
  • -定义结构体变量时,完成初始化
on key 'c'
{  
  struct Data 
  {
      int age;
      long hight;
      char name[50];
  };  
  struct Data   data = {12,150,"张三"}; //结构体定义时,初始化
  
  write("姓名:%s ; 年龄:%d ; 身高:%d",data.name,data.age,data.hight);
  //输出结果
 姓名:张三 ; 年龄:12 ; 身高:150
}
  • 定义结构体变量时,没有初始化,后面再赋值
on key 'c'
{  
  struct Data 
  {
      int age;
      long hight;
      char name[50];
  };
  
  struct Data data;
  
  data.age = 15;
  data.hight = 150;
  strncpy(data.name,"张三",elcount(data.name));
 
  write("姓名:%s ; 年龄:%d ; 身高:%d",data.name,data.age,data.hight);
    //输出结果
  姓名:张三 ; 年龄:15 ; 身高:150
}

🍅 2.13 message

  • message 是CAPL独有的数据类型,可以用来仿真,改写,创建报文等,是CANoe 仿真测试的比较核心内容
  • message ,有丰富的属性和相关方法,详情需要参考help文档了,不做深入探讨
  • 一下代码将向总线上发送一帧ID = 100 的报文
on key 'c'
{
  message 100 msg;
  msg.DLC = 1;
  msg.BYTE(0) = 0xff;
  output(msg);
}

🍅 2.14 定时器

  • 由于CAPL被设计为提供事件驱动的环境,计时器提供了一种简单的触发周期性的方法事件。CAPL允许设置无限多个用户定义的计时器。
  • CAPL 提供两种定时器: 毫秒计时器(msTimer) 和 秒计时器(timer),必须再全局变量中定义定时器
msTimer tenth_second_clock; 
Timer one_minute_clock;
  • 使用一个定时器分一下三个步骤:

    1. 声明一个计时器变量
    2. 在事件过程(preStart 除外)或用户定义的函数中预先设置计时器
    3. 为该计时器定义一个on timer 事件
  • 下面代码,是一个简单但是完整的毫秒定时器的使用方法,目的是案件‘a’触发后,开启定时器,20ms后发送 ID =100的报文

variables 
{ 
 msTimer myTimer; // creates a millisecond timer 
message 100 msg; // creates message 100 
} 
on key ‘a’ // when the ‘a’ key is pressed 
{ 
 setTimer(myTimer,20); // set myTimer to 20 ms 
} 
on timer myTimer // when myTimer expires (after 20 ms) 
{
output(msg); // output the message 
}

  • 周期定时器:下面代码周期为100ms的发送ID=0x555的报文
variables 
{ 
 message 0x555 msg1 = {dlc = 1}; 
 mstimer timer1; // define timer1 
} 
on start 
{ 
 setTimer(timer1, 100); // initialize timer to run for 100 msec 
} 
on timer timer1 
{ 
 msg1.byte(0) = msg1.byte(0) + 1; // increment the data
 output(msg1); // output message
 setTimer(timer1, 100); // reset the timer
}
  • 如果定时器还没被触发,你可以通过setTimer() 函数,重置该定时器
  • 如果定时器还没被触发,你也可以通过cancelTimer() 函数来取消该定时器

🍅 2.15 运算符

  • CAPL的运算符大多数和C都一样,也进行了一些删减
  • CAPL的运算符包括下面几大类
    算数运算
    赋值运算
    关系运算
    布尔运算
    位运算
    混合运算

2.15.1 算数运算

  • 下图是CAPL支持的算数运算符,包括加减乘除,取模等,完全和C语言一样
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

  • 下面一些算数运算符的使用

int x,y,z; 
y = 8; 
z = 4; 
x = y + z; // Addition. Result = 12 
x = y - z; // Subtraction. Result = 4 
x = y * z; // Multiplication. Result = 32 
x = y / z; // Division. Result = 2 
x = z % y; // Modulo. Result = 4 
x = y++; // Increment. Result = 9 
x = z--; // Decrement. Result = 3 

2.15.2 赋值运算符

  • 下图是CAPL支持的赋值运算符,完全和C语言一样。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

  • 下面一些赋值运算符的简单使用
int y, z; 
y = 8; 
z = 4; 
 // each statement below is independent from the others 
y += z; // Addition. Result: y = 12 
y -= z; // Subtraction. Result: y = 4 
y *= z; // Multiplication. Result: y = 32 
y /= z; // Division. Result: y = 2 
y %= z; // Modulo. Result: y = 0 
y <<= 1; // Left-shift. Result: y = 16 
y &= z; // AND. Result: y = 0 (binary arithmetic) 
y |= z; // OR. Result: y = 12 (binary arithmetic) 
y ^= z; // XOR. Result: y = 12 (binary arithmetic) 

2.15.3 布尔运算符

  • 下图是CAPL支持的布尔运算符,完全和C语言一样。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

  • 下面一些布尔运算符的简单使用
byte y, z; 
y = 0x00; 
z = 0x01; 
if (!y) // test result is TRUE 
if (!z) // test result is FALSE 
if (y == 0 && z == 1) // test result is TRUE 
if (y == 1 || z == 1) // test result is TRUE

2.15.4 比较运算符

  • 下图是CAPL支持的比较运算符,完全和C语言一样。
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

  • 下面一些比较运算符的简单使用

int y,z; 
y = 8; 
z = 4;
if (y == z) // test result is FALSE 
if (y != z) // test result is TRUE 
if (y <= z) // test result is FALSE 
if (y >= z) // test result is TRUE 

2.15.5 位运算符

  • 下图是CAPL支持的位运算符,完全和C语言一样。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

  • 下面一些位运算符的简单使用
byte x, y, z; 
y = 0x0AA; // y = 1010 1010 
z = 0x05A; // z = 0101 1010 
x = y & z; // AND result = 0000 1010 
x = y | z; // OR result = 1111 1010 
x = y ^ z; // XOR result = 1111 0000 
x = y << 1; // shift left result = 0101 0100 
x = y >> 1; // shift right result = 0101 0101 
x = ~y; // 1’s complement result = 0101 0101 

2.15.6 三目运算符

  • 下图是CAPL支持的三目运算符,完全和C语言一样。
  • 返回值:先求表达式 1 的值,如果为真,则执行表达式 2,并返回表达式 2 的结果;如果表达式 1 的值为假,则执行表达式 3,并返回表达式 3 的结果
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL
byte x, y, z; 
z = 3; 
y = 5; 
x = (y < z) ? z : y; // conditional result x = 5

2.15.7 其它运算符

  • 下图是CAPL支持的运算符,[]可以用来数组索引取值, 点 表示结构体的成员,这在CAPL语言中很常见,不止用于结构体的成员变量,很多Object都有成员
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL
  • 比如message数据类型
  message 100 msg;
  msg.DLC = 1;
  msg.BYTE(0) = 0xff;
  output(msg);

2.15.8 不支持运算符

  • 下图是CAPL支持的运算符,& 在CAPL中局部支持,可以用来地址传参,比如 void function(int & dl),可以在函数内部改变传入的变量

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

2.15.9 运算符优先级

  • 下图是我在网上找的C语言的运算符优先级,因为CAPL语言基于C,大部分都适用。
  • 没有必要去记哈,贴出来给个参考。如果代码需要复合运算的时候,都加上括号,既方便阅读代码,也不用担心优先级的问题。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


🍅 2.16 控制语句

  • CAPL支持的控制语句和C语言中一样,包括 if else ,do ,while ,for 等

2.16.1 if 语句

if (expression) statement;

  • if 括号内的表达式为真,或者非0,则执行if 下面的语句
  • 如果没有花括号,则只执行if下面的第一行语句
  int speed ;
  speed  = 80if (speed > 60)
    write("line 1");//这一行语句受if语句控制
    write("line 2");//这一行语句不受if语句控制
  • 如果有花括号,执行if下面花括号的所有语句
  int speed ;
  speed  = 80if (speed > 60) 
  {
  //花括号内的语句都会执行
    write("line 1");
    write("line 2");
   }

2.16.2 if else 语句

  • 如果下面表达式为真或者非0,则执行语句块1,否则执行语句块2
    if (expression) statement_1
    else statement_2

  • if else 的典型用法

  int speed ;
  speed = 40;
  if (speed > 60)
  {
    write("line 1");
  }
  else if(speed > 80)
  {
    write("line 2");
  }
  else
  {
    write("line 3");
  }

2.16.3 Switch 语句

  • 下面是switch 语句的伪代码表示:
switch (expression) 
{ 
 case value1: statement1; statement2;break; 
 case value2: statement1; statement2;break; 
 . . . 
 default: statement1; statement2;break; 
}
  • switch (expression) 中的 expression应该是个 整形变量或者字符变量或者枚举类型变量
  • case value1: 每个case分支中的value应该是个 整形或者字符常量,注意case value后面有个冒号
  • default ,当所有分支都不能匹配的时候,会执行default内的代码
  • 当遇到 break 语句时,switch 终止,控制流将跳转到 switch 语句后的下一行。
  • 不是每一个 case 都需要包含 break。如果 case 语句不包含 break,控制流将会 继续 后续的 case,直到遇到 break 为止。
float value1, value2, result; 
char operator; 
... 
switch ( operator ) 
{ 
 case+: result = value1 + value2; 
 break; 
 case-: result = value1 – value2; 
 break;
 case*: result = value1 * value2; 
 break; 
 case/: if ( value2 == 0) write (“Division by zero!); 
 else result = value1 / value2; 
 break; 
 default: write (“Unknown operator.); 
 break; 
} 

2.16.4 While 循环语句

  • Capl 语言中 while 循环的语法:
while(condition)
{
   statement(s);
}
  • 在这里,statement(s) 可以是一个单独的语句,也可以是几个语句组成的代码块。
  • condition 可以是任意的表达式,当为任意非零值时都为 true。当条件为 true 时执行循环。 当条件为 false 时,退出循环.

   int a = 10;

   /* while 循环执行 */
   while( a < 20 )
   {
      write("a 的值: %d\n", a);
      a++;
   }
 

2.16.5 do…while 循环语句

  • Capl 语言中 do…while 循环的语法:
do
{
   statement(s);

}while( condition );
  • 在这里,statement(s) 可以是一个单独的语句,也可以是几个语句组成的代码块。
  • condition 可以是任意的表达式,当为任意非零值时都为 true。当条件为 true 时执行循环。 当条件为 false 时,退出循环.
  • 不像 for 和 while 循环,它们是在循环头部测试循环条件。在 C 语言中,do…while 循环是在循环的尾部检查它的条件。
  • do…while 循环与 while 循环类似,但是 do…while 循环会确保至少执行一次循环
  • 还要注意while 表达式最后是分号结尾的

   int a = 10;

   /* do 循环执行,在条件被测试之前至少执行一次 */
   do
   {
       write("a 的值: %d\n", a);
       a = a + 1;
   }while( a < 20 );
 

2.16.6 for 循环语句

  • Capl 语言中 for 循环的语法:
for ( init; condition; increment )
{
   statement(s);
}
  • 下面是 for 循环的控制流:
    1,init 会首先被执行,且只会执行一次。您也可以不在这里写任何语句,只要有一个分号出现即可。CAPL语句不允许在这个位置定义新的变量,而C语言是可以的
    2,接下来,会判断 condition。如果为真,则执行循环主体。如果为假,则不执行循环主体,且控制流会跳转到紧接着 for 循环的下一条语句。切记不要让condition永远为真,否则会是个死循环
    3,在执行完 for 循环主体后,控制流会跳回上面的 increment 语句。该语句允许您更新循环控制变量。该语句可以留空,只要在条件后有一个分号出现即可。
    4,条件再次被判断。如果为真,则执行循环,这个过程会不断重复(循环主体,然后增加步值,再然后重新判断条件)。在条件变为假时,for 循环终止。

  • 下面三个代码都是可以的

   int a ;
   /* for 循环执行 */
   for(  a = 10; a < 20; a = a + 1 )
   {
      write("a 的值: %d\n", a);
   }
   int a ;
	a =10;
   /* for 循环执行 */
   for(  ; a < 20; a = a + 1 ) //第一个表达式为空
   {
      write("a 的值: %d\n", a);
   } 
   int a ;
	a =10;
   /* for 循环执行 */
   for(  ; a < 20;  )//第1,3个表达式为空
   {
      write("a 的值: %d\n", a);
      a = a + 1;     
   } 

2.16.7 break 语句

  • Capl 语言中 break 语句有以下两种用法:
    当 break 语句出现在一个循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句。
    它可用于终止 switch 语句中的一个 case。

  • 如果您使用的是嵌套循环(即一个循环内嵌套另一个循环),break 语句会停止执行最内层的循环,然后开始执行该块之后的下一行代码。

  • 下图是break语句在循环语句中的使用,和退出循环的过程
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

   int a = 10;

   /* while 循环执行 */
   while( a < 20 )
   {
      write("a 的值: %d\n", a);
      a++;
      if( a > 15)
      {
         /* 使用 break 语句终止循环 */
          break;
      }
   }

2.16.8 continue 语句

  • continue 语句有点像 break 语句。但它不是强制终止,continue 会跳过当前循环中的代码,强迫开始下一次循环。

  • 对于 for 循环,continue 语句执行后自增语句仍然会执行。对于 while 和 do…while 循环,continue 语句重新执行条件判断语句

  • -下图是continue 语句在循环语句中的使用
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

   int a = 10;
   /* do 循环执行 */
   do
   {
      if( a == 15)
      {
         /* 跳过迭代 */
         a = a + 1;
         continue;
      }
      write("a 的值: %d\n", a);
      a++;
     
   }while( a < 20 );
   //输出结果:
a 的值: 10
a 的值: 11
a 的值: 12
a 的值: 13
a 的值: 14
a 的值: 16
a 的值: 17
a 的值: 18
a 的值: 19

2.16.9 return 语句

  • CAPL脚本中,不带参数的return也可以退出循环语句
on key 'c'
{
   int a = 10;
   /* while 循环执行 */
   while( a < 20 )
   {
      write("a 的值: %d\n", a);
      a++;
      if( a > 15)
      {
         /* 使用 break 语句终止循环 */
          return;
      }
   }
}
  • 但是更多的使用return,是用来在函数中,返回一个值或者值的表达式
  • 注意:CAPL中所有的事件处理都不返回
long Power(int x, int y) 
{ 
 int i; 
 long result; 
 result = 1; 
 for (i = 1; i <= y; i++) 
 	result *= x; 
 return result; 
} 

🍅 2.17 函数

1, CAPL语言,选用了C语言库的少部分函数,但是CANoe有它自己的大量的函数库,这些函数都是专用于CANalyzer或CANoe编程环境中有用的各种专用操作。
2,CAPL的函数大致分为3类:

  • 自定义的函数;不用任何声明,在CAPL文件任意位置都可以
  • CAPL内置的函数;不用像C语言那样的要引用 #include <stdio.h>等等各种库,已经被内置在CAPL中,随用随调
  • DLL: 考虑到CAPL内置库不够用,CAPL对动态库有很好的支持

3 ,CAPL为其内置函数使用一致且易于阅读的命名约定:

  • 所有标准C函数都是小写的(例如,sin(), cos(), strlen(), strncat())
  • 非标准C函数,且只有1个单词的函数都是用小写(例如,trigger(), outport(), inport())
  • 非标准C函数,但是超过1个单词的,除第一个单词,其余的首字母都大写(例如,swapInt(), timeDiff(), putValueToControl())

4, 虽然函数名是不区分大小的,但是为了保持CAPL统一的编码规则和可读性,建议你依据上面的规则

2.17.1 函数重载

  • 这里CAPL引入了C++的函数重载的思想,只要保证参数不同,我们可以定义相同的函数名
on key 'c'
{
  printme(5.7);
  printme(3, "Feet"); 
}

void printme (double num) 
{ 
 write("Floating point %f", num); 
} 
void printme (int num, char units[]) 
{ 
 write("%d %s", num, units); 
}

2.17.2 函数传参

  • 因为没有C语言指针的概念,相对C语言函数传参就相对简单很对,以数值类型传参为例
  • 传值:将函数外的参数再内存中拷贝一份,再函数内的更改,不会对函数外的参数有影响。
on key 'a'
{
  int a = 10 ,b =20 ;
  write("a=%d ; b=%d",a,b);
  swip_1(a,b);
  write("a=%d ; b=%d",a,b);
}

void swip_1(int a, int b)
{
	int temp;
  temp = a;
	a = b;
	b = temp;
  write("inter>>>>a=%d ; b=%d",a,b);
}

输出结果:
a=10 ; b=20
inter>>>>a=20 ; b=10
a=10 ; b=20


  • 引用传参:将变量的引用传入函数,效果和指针相同,在函数内更改,也会对函数外的参数进行更改
on key 'b'
{
  int a = 10 ,b =20 ;
   write("a=%d ; b=%d",a,b);
  swip_2(a,b);
   write("a=%d ; b=%d",a,b);
}

void swip_2(int& a, int& b)
{
	int temp;
  temp = a;
	a = b;
	b = temp;
   write("inter>>>>a=%d ; b=%d",a,b);
}

输出结果:
a=10 ; b=20
inter>>>>a=20 ; b=10
a=20 ; b=10


  • 数组/结构体传参 : 数组/结构体等连续内存的变量传参都是 地址传参,函数内部的操作都会对函数外产生影响。
void  test_2(char para2[])
{
   snprintf(para2,elCount(para2),"hello Vector!");
}

On key 'c' 
{  
  char input[100] = "hello world!";
  write("***********%s",input); 
  test_2(input);    
  write("***********%s",input); 
}

输出结果:
***********hello world!
***********hello Vector!


2.17.3 函数返回值

原则上来说,CAPL 的函数只支持 数值类型 的返回值
有同学问,数组和结构体类型可以作为返回值吗?答案是不可以的,如果你想把函数中的数组传出去,请给它传参传入一个数组,上面也说了函数内对数组的更改是会影响要函数外的,这样就把函数 “return” 出去了

long  test_1(long para1,long para2)
{  
  return para1 + para2 ;
}

On key 'a' 
{
  write("***********%d",test_1(3,5)); 
}

🍅 2.18 test case

testcase NewTestCase()
{
 // 测试方法的代码块
}

testcase 是CAPL语法独有的一种语法模块,有点像函数,可以传递各种参数,也是需要有程序调用它才会执行

常见的调用testcase 的方法有两种 ,一种是XML TestModule ,另一种是CAPL TestModule
从零开始学习CANoe(七)—— XML 测试节点
从零开始学习CANoe(六)—— CAPL 测试节点

  • 下面是XML TestModule 方式,由xml文件调用testcase ,xml编程进一步的学习可以参考:Capl编程xml标签语法

test.xml 部分代码,测试启动时,会依次调用CAPL中的 testcase

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<testmodule title="CANoe" version="1.12">
		<capltestcase name="test_1" />
		<capltestcase name="test_1" >
			<caplparam type="string" name="case_id">TC_10449595</caplparam>
			<caplparam type="int"    name="case_id">0x245</caplparam>
		</capltestcase>	
</testmodule>

test.can 中的 testcase,负责测试方法的具体实现。

testcase test_1()
{
  write("test_1 running");
}

testcase test_2(char case_id[],int message_id)
{
  write("test_2 running ,case_id : %s",case_id);
}
  • CAPL TestModule 类型中的 testcase 是通过 MainTest 来调用的。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


🍅 2.19 CAPL 文件类型

2.19.1 根据文件后缀分为.can 和 .cin

类似于C语言的.c和.h文件 ,一般情况我们在.can文件写 test case,在 .cin 文件写函数和定义变量,然后在.can的includes 模块中把.cin文件引用进来。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL
特别说明:
其实 .can 和.cin文件 的内部结构基本一致,都可以定义变量,事件,函数等,功能基本一样
和C语言不同的是 在.can和.cin文件中,使用函数,不需要提前声明,任何地方都可以定义,任何地方都可以使用,注意我说的任何
比如:在.cin 文件中定义的函数和变量,在.can文件中可以直接使用,这好理解,因为是.can文件 include了 .cin文件 ;但是 在.can 文件中定义的函数和变量,在cin文件中也是可以直接使用的。

2.19.2 创建不同的节点类型,就会有不同类型的.can/.cin文件

  • 如下图,虽然都是.can文件,但是 一个节点类型是 Test node ,一个节点类型是Simulation node,节点类型不同

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

文件的类型不同,在创建节点类型的时候就决定了,虽然都是.can文件 ,但是支持的CAPL语法也会有所差别。

Test node:侧重于测试测量,CAPL内置了很多的测试函数,可以在Test node类型的.can文件中使用,但是不可以在simulation node 类型的can文件中使用,函数中包含testxxxx的都是如此 ,比如常见的testwaitfortimeout()是最常见的延时等待函数,但是它不能在 simulation node 类型的can文件中使用。
两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


🍅 2.20 CAPL 文件的编码方式

.can/cin文件的编码方式,这在很多编程语言中都有,在CAPL中开头部分定义

/@!Encoding:936/ : 支持中文字符串,比如write(“调用顺序 —— 1”)

/*@!Encoding:ASCII/ :不支持中文,老外写代码用的都是这个

其它的暂时没用到,就不说了,有兴趣自己gg吧

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


🍅 2.21 CAPL 的事件结构

这里再次强调下,CAPL脚本是基于事件驱动的,也就是说CAPL脚本中每一行代码都是某个对应的事件发生了才去执行的。

  • testcase,是由其它功能模块调用而执行的,如上边所说xml test module
  • Functions :函数也肯定是被调用才被执行的
  • Test Function ,这个本文我没说,也是被xml/.net 文件调用而执行的,和testcse同一类的
  • includes : 非事件,引用.cin和dll文件的功能块
  • Variables: 非事件,定义全局变量,注意是相对本文件的全局变量,非CANoe环境的全局变量,在CANoe中使用全局变量有系统变量和环境变量

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

2.21.1 sytem ,系统事件

on timer 和 on key 就不再赘述了,前面也已经写过了,圈起来的是几个测量事件,启动和停止CANoe 软件的时候会分别调用
CAPL 脚本中 定时器 ,按键触发事件的使用

在这里插入代码片

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

  • 执行顺序如下:
  • on preStart过程仅用于初始化变量、在Write Window中显示消息以及从文件中读取数据
  • on preStop函数可用于执行一些在测量停止实际生效之前必须执行的最终操作。
on preStart
{
  write("调用顺序 —— 1");
}

on Start
{
  write("调用顺序 —— 2");
}
on preStop
{
   write("调用顺序 —— 3");
}

on stopMeasurement
{
  write("调用顺序 —— 4");
}

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

注意

  • on start 和 on stopMeasurement 事件不能在 test node 类型的.can文件中使用
  • 可以使用 on preStart ,但是不能用来对变量赋值等操作
  • 如果测量测试已经完成,那么 on preStop 中的代码也不会被执行。
  • 所以 系统的测数量事件相关代码最好集中在simulated node .can文件中完成
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

2.21.2 值(信号/变量)变化事件

比如信号值,系统变量,环境变量 ,这些元素值发生变化,会触发这些事件
CAPL 脚本中对信号,系统变量,环境变量的 事件响应
两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

2.21.3 报文接收事件

总线上收到指定的报文后,会触发 on message 事件,同时message 是一个object 对象,它由很多属性,可以通过 this .xxx获取和设置

CAPL脚本 对CAN 报文的事件响应

On message CAN1.0x4c
{
  write("***0x%x",this.id);
}

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL


2.21.4 事件中的this 关键字

1)在接收CAN对象或环境变量的事件过程中,对象的数据结构由关键字this指定。例如,您可以通过以下方式访问刚刚接收到的消息100的第一个数据字节

on message 100 {
byte byte_0;
byte_0 = this.byte(0);
...
}

2):类似地,您可以通过以下方法读取刚刚更改过的整数环境变量Switch的新值

on envVar Switch {
int val;
val = getvalue(this);
...
}

3):类似地,键盘按键事件

On key 'a'

{
  write("pressed %c",this);
}



🍅 2.22 CAPL Browser 的设置

2.22.1 配色方案:

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL
两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

2.22.2 必须的工具栏:

在使用CAPL 写脚本时,我认为这三个工具栏应该要打开的,可以便捷你的开发速度

  • Output :开发的时候,编译可以实时发现脚本的错误信息
  • Symbols: 在CANoe中加载的DBC,CDD文件的元素,定义的系统变量等都可以直接这里找的到,随用随查看
  • CALP Functions: C语言在使用库函数时,需要在文件开头include相应的库文件,但是CAPL不需要那么麻烦,它内置了很多自己专用的函数,也吸收了一些C/C++的函数,但是不需要include任何文件,可以在CAPL中直接使用。有时候记不全函数的名称,可以直接搜索查看。

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

🌎总结

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL文章来源地址https://www.toymoban.com/news/detail-788900.html

  • 🚩要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!

  • 🚩如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
    两万字的capl语法基础,一篇文章带你入门,CANoe和CAPL,开发语言,CANoe,CAPL

到了这里,关于两万字的CAPL语法基础,一篇文章带你入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一篇文章,带你彻底掌握接口测试!

    一、什么是接口测试? 所谓接口,是指同一个系统中模块与模块间的数据传递接口、前后端交互、跨系统跨平台跨数据库的对接。而接口测试,则是通过接口的不同情况下的输入,去对比输出,看看是否满足接口规范所规定的功能、安全以及性能方面的要求。 二、为什么要

    2024年02月10日
    浏览(53)
  • 一篇文章带你快速认识区块链(必看)

           区块链技术,这一划时代的分布式账本技术,正在全球范围内掀起一场深度的信任与协作模式变革。区块链如同一部由多方共同维护的公开而又安全的大账本,每一笔交易都被打包成一个区块,通过高级密码学手段确保传输和访问安全,并按照时间顺序串联起来,形

    2024年04月25日
    浏览(61)
  • 一篇文章带你了解什么是JDK

    JDK(Java Development Kit)是Java开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源。下面是JDK的一些重点介绍: Java编译器(javac):JDK包含了Java编译器,可以将Java源代码编译为Java字节码。通过编译器,开发人员可以将Java源代码转换为可在JVM上运行的字节码文

    2024年03月19日
    浏览(98)
  • 一篇文章带你了解什么是图灵完备

    图灵完备(Turing-complete)是一个计算机科学中的概念,它指的是一种计算模型能够模拟任何其他计算模型的能力。这意味着,只要一种计算模型是图灵完备的,那么它就能够完成任何可计算的任务。 图灵完备是指一种计算机语言或计算模型具有足够的能力来模拟图灵机的所有

    2024年02月15日
    浏览(48)
  • 一篇文章带你了解SpringBoot目录结构

    前言 SpringBoot是整合Spring技术栈的一站式框架,是简化Spring技术栈的快速开发脚手架,是一个能够快速构建生产级别的Spring应用的工具。SpringBoot是目前流行的微服务框架,倡导“约定优于配置”,简化Spring项目搭建及开发过程。springboot提供了很多核心的功能,比如自动化配置

    2024年03月25日
    浏览(71)
  • 一篇文章带你搞懂前端Cookie

    浏览器Cookie相信各位点进这篇文章的小伙伴应该不陌生了,它是前端领域中一个非常重要的内容,当然也是面试的一个考点,不知道各位小伙伴是否真正掌握了Cookie呢?当然没有掌握也是没有关系的,可以跟着小编的脚步一起来学习一下前端Cookie,没有熟练掌握的小伙伴看完这

    2024年02月04日
    浏览(46)
  • 一篇文章带你实现栈的接口

    栈(Stacks)是限定在一端插入和删除的线性表。允许插入和删除的一端称为栈顶(Top),另一端称为栈底(Bottom)。栈中的数据元素遵守后进先出(Last In First Out)的原则。因此,栈又称为后进先出(先进后出)线性表。 压栈:栈的插入操作叫做进栈、压栈、入栈,入数据在

    2024年02月13日
    浏览(51)
  • 一篇文章带你走进Java(保姆级)

    手打不易,希望对各位还在徘徊学什么语言的有帮助!!java不会让你失望!! Java是一种优秀的程序设计语言,它具有令人赏心悦目的语法和易于理解的语义。 Java还是有一系列计算机软件和规范形成的技术体系,这个技术体系提供了完整的用于软件开发和跨平台部署的支持

    2024年02月15日
    浏览(54)
  • 【C++】一篇文章带你深入了解list

    list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。 list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。 list与forward_list非常相似:最主要的不同在

    2024年04月23日
    浏览(56)
  • 一篇文章带你了解-selenium工作原理详解

    前言 Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。 主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得

    2024年02月10日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包