CAPL编程系列_02
1_CAPL 中的运算符
在CAPL(CANoe/CANalyzer Programming Language)中,运算符用于执行各种运算操作,类似于其他编程语言。CAPL中的运算符可以分为以下几类:
1. 算术运算符
算术运算符 | |
+ | 加法运算符 |
- | 减法运算符 |
* | 乘法运算符 |
/ | 除法运算符 |
% | 求余运算符 |
int a = 10, b = 5;
int sum = a + b; // sum = 15
int diff = a - b; // diff = 5
int prod = a * b; // prod = 50
int quotient = a / b; // quotient = 2
int remainder = a % b; // remainder = 0
2. 赋值运算符
赋值运算符 | |
= | 赋值 |
+= | 加法赋值 |
-= | 减法赋值 |
*= | 乘法赋值 |
/= | 除法赋值 |
%= | 取余赋值 |
int a = 5;
a += 10; // a = a + 10 => a = 15
a -= 3; // a = a - 3 => a = 12
a *= 2; // a = a * 2 => a = 24
a /= 4; // a = a / 4 => a = 6
a %= 4; // a = a % 4 => a = 2
3. 自增和自减运算符
自增和自减运算符 | |
++ | 自增(前置或后置) |
-- | 自减(前置或后置) |
int a = 5;
a++; // a = 6 (后置自增)
++a; // a = 7 (前置自增)int b = 10;
b--; // b = 9 (后置自减)
--b; // b = 8 (前置自减)
4. 类型转换运算符
(type)
:类型转换
double a = 5.7;
int b = (int)a; // b = 5
5. 关系运算符
== | 等于 |
!= | 不等于 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
6.逻辑运算符
! | 逻辑非 |
&& | 逻辑与 |
|| | 逻辑或 |
7.位运算符
& | 按位与 | 两个操作数对应位都为1时,结果位才为1,否则为0 |
| | 按位或 | 两个操作数对应位有一个是1,结果位就为1,否则为0 |
^ | 按位异或 | 相同位的两个操作数不同,结果为1,相同则为0 |
~ | 按位取反 | 对操作数的每一个位取反,即将0变为1,将1变为0 |
<< | 左移 | 将操作数的二进制位向左移动指定的位数,右侧空出的位用0填充 |
>> | 右移 | 将操作数的二进制位向右移动指定的位数,左侧空出的位由符号位填充 |
2_CAPL 中的分支结构
1.if
三种 i f 分支语句
简单 if 语句(单分支) if-else 语句(双分支) if-else if 语句(多分支)
//简单 if 语句(单分支)if(条件)
{条件成立执行的语句
}// 任意一个表达式都可以做“条件”
// 判定规则:非 0 即 “真”
// 0, 0.0,‘\0' 都表示“假”//示例//单分支
on key "a"
{int score = 92;if (score >= 90)
{
write (“奖励1000元”);
}write(“程序结束了~~~”)}
if-else 语句 (双分支)if(条件)
{条件成立执行的语句
}
else
{条件不成立执行的语句
}
if-else if 语句 (多分支)if(条件1)
{条件1成立执行的语句
}
else if (条件2)
{前面条件不成立,但条件2成立执行的语句
}
else if (条件N)
{前面条件不成立,但条件N成立执行的语句
}
else
{所有条件都不成立时执行的语句
}
条件判断的三元运算符
条件 ? 表达式一 : 表达式二 on key "e" {int score = 52;char result;//三元运算表达式result = score >= 60 ? 'Y' : 'N';write ("result 为 %c", result); }//输出:result 为 N
2.switch
switch(表达式) {case 值1:语句;break;case 值2:语句;break;case 值N:语句;break;default:语句; }
注意点:
> case 后的值必须是整型的常量或常量表达式
> 分支中的break可以缺省,如果缺省,该分支语句执行后会贯穿到下一个分支
3.while 和 do-while 语句
while//while 语句while (条件表达式) {循环主体语句1;循环主体语句2;循环主体语句N; }
注意点:
>条件表达式可以是一个任意的表达式
>注意正确设计循环的执行流程,防止出现死循环
do-while
//do-while 语句do {循环主体语句1;循环主体语句2;循环主体语句N; } while (条件表达式) ;
注意点:
>先执行,后判断
>至少执行一次循环主体
on key 'd' {//输出1到100之间所有能被 7 整除或以 7 结尾的数字int i = 1;while (i <= 100){if (i % 7 == 0 || i % 10 == 7){ write("i: % d",i);}i++;}}
循环过程中的流程控制关键字:
>break : 跳出整个循环
on key 'f' {//判断一个数字是否是质数int n = 13;int i = 2;while ( i < n ){if (n % i == 0){write ("%d不是质数,它能为%d整除",n,i);break;}i++;}if (i == n){write("%d是质数",n);}}
>continue :继续下一次循环
4.for 语句
on key 'b' {//判断一个数字是否是质数(素数)int num = 13;int i;for(i = 2; i < num; i++){if(num % i == 0){ write("%d 不是质数,能被 %d 整除",num,i);break;}}if(i == num){write("%d是质数",num);} }
注意点:
>初始化,条件,更新三个部分均可省略,但如果省略了条件,则默认为“真”
>与C语言的for不同,不支持逗号运算符
3_CAPL 中的函数定义
返回值类型 函数名(形参列表)
{
函数主体语句return 返回值;
}
注意点:
> 函数如果没有返回值,返回值的占位符为 void,且void可以省略.
> 函数可以重载(函数名相同、返回值相同,但形参不同).
on key 'a'
{float r;r = power (2.5,3); //调用函数write("2.5的3次方为: %.4f " ,r ) ;write("4的4次方为:%d",(int)power(4,4)); //调用函数
}// 定义求a的b次方的函数
float power(float a,int b)
{float p;int i;p = 1; //乘积for(i = 0; i < b; i++){p = p * a; //将当前乘积 p 跟 a 相乘的结果,再赋值给乘积 p}return p;
}
4_CAPL 中的定时器
variables {timer tmr1; //声明一个定时器变量 }//当定时器被触发时需要执行的代码 on timer tmr1 {write("发送报文等等工作......."); }on key 'a' {//设置定时器在多少秒后执行setTimer(tmr1,2); }
注意点:
> 有“秒定时器”和“毫米定时器”两种 timer、 msTimer> 定时器变量只能声明在 variables 作用域
> 必须为定时器变量定义对应的“处理代码块” 【 on timer 定时器变量 】
> 启动定时器的函数 -- setTimer
> 结束定时器的函数 -- cancelTimer
>msTimer 有一个直接用于周期性使用的函数:setTimerCyclic(变量名,毫秒数);
5_CAPL 中的报文发送
> 声明 message 类型的“报文”变量
message 0x1A5 msg1;
message EngineState msg2;
> 给报文变量赋值
声明报文变量的同时,赋初值
声明变量后,再进行赋值
> 调用内置函数output,发送报文
》注意:
write是往canoe工具上的输出面板,输出一些文字信息
output是内置函数,是往总线上输出报文
on key 'a ' {//多种声明变量的方法//1.声明了一个ID为0x1A5的报文变量message 0x1A5 msg1;//2.声明了一个ID为0x2B6的报文变量,并且赋予初始值message 0x2B6 msg2 = { dlc=4, byte(0) = 0x2D,byte(1)=0x3F };//3.声明了一个ID为0x3c7的报文变量(和 msg1 对比)message 0x2B6 msg2 = { dlc=4, byte(0) = 0x2D,byte(1)=0x3F };//msg1的变量赋值msg1.dlc = 8; //给报文变量的dlc赋值msg1.byte(0) = 0xC7; //给报文数据域中的Byte0的这个字节赋值msgl.byte(1) = 0x95; //给报文数据域中的Byte1的这个字节赋值msgl.byte(2) = 0x3F; //给报文数据域中的Byte2的这个字节赋值msgl.byte(3) = 0x6B; //给报文数据域中的Byte3的这个字节赋值//msg3的变量赋值msg3.dlc = 8;msg3.word(0) = ox95C7; //给报文数据域中的Byte0和Byte1的这个字节赋值(两个字节倒序)msg3.word(2) = ox6B3F; //word占两个字节,所以要跳两个output(msg1); //发送报文msg1output(msg2); //发送报文msg2output(msg3); //发送报文msg3 }
//只需填写转速,后台会自动生成DATA的值
on key 'a'
{//创建一个指定报文名的报文变量//如果这个报文在 dbc 中存在,不用指定dlcmessage EngineState msg1;//给该报文的 EngineSpeed 和 OnOff 这两个信号赋值//语法:【报文变量.信号名】msg1.EngineSpeed = 3000; //赋值为 3000 rpmmsg1.OnOff = 1; //赋值引擎开关状态为On ( 值为 1 )//发送报文msg1output(msg1);
}
定时器周期性发送
//定义一个定时器事件,当触发定时器,就给msg2.EngineSpeed(引擎转速)进行赋值 variables //全局变量里去定义一个毫秒定时器 {int currEngspd = 0 ; // 当前的引擎转速值message EngineState msg2 ; // 创建报文msTimer tmrSendMsg2; // 定义一个毫秒定时器用于发送报文 }on timer tmrSendMsg2 //定义一个Msg2定时事件 {// 将当前转速值赋值给报文msg2的引擎转速信号EngineSpeed msg2.EngineSpeed = currEngspd; currEngspd += 10; // 每次增长10rmpoutput(msg2); }on key 'b' {setTimerCyclic(tmrSendMsg2,100) }
6_CAPL 中的事件
时间驱动的概念 | |||
⬇ | 接收到报文 | → | 事件处理的程序 |
⬇ | 用户输入 | → | 事件处理的程序 |
⬇ | 定时器到时 | → | 事件处理的程序 |
时间 |
事件 含义 on preStart 在总线“测量开始之前”触发 on start 在总线“测量开始时”触发 on preStop 在总线“测量将结束时”触发 on stopMeasurement 在总线“测试结束后”触发
事件 含义 on key 指定键 当指定键按下时触发 on timer 定时器 当“定时器计时到时”时触发
事件 含义 on message 指定报文 当接收到指定报文时触发
事件 含义 on signal 指定信号 当监测到指定信号值变化时触发 on signal_update 指定信号 当监测到指定信号值更新时触发 重点关注加粗字体的使用
事件 含义 on sysVar 系统变量 当监测到系统变量变化时触发 on sysVar_update 系统变量 当监测到系统变量更新时触发
- on sysvar 和 on sysvar_update 事件
on sysvar 系统变量名
{write("系统变量的值变化了: %d",@this);
}on sysvar_update 系统变量名
{write("系统变量的值更新了:%d",@this);
}
- 可以使用 @系统变量名 来获取或设置系统变量的值
- 还可以调用 sysGetVariableXxx( ) 函数来获取系统变量的值
- 还可以调用 sysSetVariableXxx( ) 函数来设置系统变量的值
- 在系统变量事件处理程序中,还可以使用 @this 来获取变量的值
on key 'a'
{//改变系统变量TurnLeftIndicator,赋值一个0到9的随机数 @Control::TurnLeftIndicator = random(10) > 7 ? 1 : 0;//sysSetVariableInt("Control","TurnLeftIndicator",random(10) > 4 ? 1 : 0 );
}//当系统变量Control::TurnLeftIndicator的值发生变化时,执行的代码
on sysvar Control::TurnLeftIndicator
{write("TurnLeftIndicator变量的值发生变化了:%d %d %d',@this, @Control::TurnLeftIndicator,sysGetVariableInt("Control","TurnLeftIndicator'));
}//当系统变量Control::TurnLeftIndicator的值发生更新时,执行的代码
on sysvar_update Control::TurnLeftIndicator
{write("TurnLeftIndicator变量的值发生更新了: %d %d %d", @this,@Control::TurnLeftIndicator,sysGetVariableInt("Control","TurnLeftIndicator'));
}
以上是关于CAPL语言中一些简单的总结。
希望对你有所帮助,谢谢观看。