文章目录
1. CAN信号
CAN信号是封装在CAN报文中的数据片段。
1.1 定义
CAN信号在CANdb(.dbc)文件中定义,包括:
- 信号名称、长度(位)
- 字节顺序(Intel/Motorola)
- 精度(因子)、偏移量
- 最小值、最大值、单位
1.2 在CAPL中的使用
读取信号物理值:
on message EngineData
{
// 直接使用信号名读取物理值
float currentRPM = EngineSpeed;
int currentTemp = EngineTemperature;
// 使用this关键字
float currentRPM = this.EngineSpeed;
write("当前转速: %f rpm", currentRPM);
}
读取信号总线值(使用$):
on message EngineData
{
// 使用$读取信号的总线值
long rawRPM = $EngineSpeed;
float physicalRPM = EngineSpeed;
write("原始值: %d, 物理值: %f", rawRPM, physicalRPM);
}
赋值/写入:
on key 'a'
{
// 设置信号物理值
BodyControl.LightSwitch = 1;
output(BodyControl);
// 设置信号总线值
$BodyControl.LightSwitch = 0xFF;
output(BodyControl);
}
1.3 使用场景
- 常规数据处理使用物理值(直接信号名)
- 校验和、多路复用器、诊断等底层处理使用总线值($信号名)
2 LIN信号
LIN信号存在于LIN帧中,定义在LDF(.ldf)文件中。
2.1 在CAPL中的使用
读取:
on linFrame MyLinFrame
{
// 读取物理值
byte doorStatus = DoorContact;
// 读取总线值
byte rawDoorStatus = $DoorContact;
write("车门状态: %d (原始值: %d)", doorStatus, rawDoorStatus);
}
赋值/写入:
on key 'b'
{
// 设置物理值
MyLinFrame.InteriorLight = 50;
output(MyLinFrame);
// 设置总线值
$MyLinFrame.InteriorLight = 0x7F;
output(MyLinFrame);
}
3 系统变量
系统变量是CANoe内部使用的全局变量,用于在不同模块间传递数据。
3.1 定义
在System Variable Group (SVG) 文件中定义。
3.2 在CAPL中的使用(使用@符号)
读取:
on sysvar MyNamespace::EngineState
{
// 使用@读取系统变量
int state = @MyNamespace::EngineState;
write("引擎状态变为: %d", state);
}
void myFunction()
{
int currentState = @MyNamespace::EngineState;
}
赋值/写入:
on key 'c'
{
// 使用@设置系统变量
@Sysvar::CarCockpit::Ignition = 1;
@Sysvar::Display::Message = "系统就绪";
@Debug::MotorValue::EngineSpeed = $EngineSpeed;
}
常见相关函数:
使用以SysGetVariable开头和SysSetVariable开头的访问函数。
如SysGetVariableInt、SysGetVariableFloat、SysSetVariableInt、SysSetVariableFloat;
系统变量的初始值需要定义明确。如果在使用过程中没有定义初始值,如果涉及到系统变量reset,那么将无法完成reset功能。
4 环境变量
环境变量用于CANoe与外部环境的交互。
4.1 定义
在Environment Variable窗口中定义。
4.2 在CAPL中的使用
环境变量和系统变量用法类似;
比较通用的访问操作方式是使用函数getValue()和putValue()
注意事项:
- 环境变量的使用必须要以DBC的格式来使用,并且需要将DBC添加到CAN网络中。
- 环境变量在CANoe 12.0版本之后不适用。
读取:
on envVar MyEnvironmentVar
{
long value;
getValue(MyEnvironmentVar, value);
write("环境变量值变为: %d", value);
}
void readEnvVar()
{
long val;
getValue(MyEnvironmentVar, val);
}
赋值/写入:
on key 'd'
{
putValue(ExternalControl, 100);
}
5 系统变量和环境变量
相同点:
- 都可以作为ECU、面板和CAPL程序相连接的媒介。
- 直接引用时都要添加@符号;
不同点:
系统变量有命名空间的概念,而环境变量则没有这种概念
环境变量:@envKL30
系统变量:@sysvar::EngineModule::EngineSpeed
注意系统变量其实可以理解为sysvar,是一个命名空间,然后又嵌套了一个名为EngineModule的命名空间。
6 $ 与 @ 符号的详细对比
6.1 $符号 - 信号总线值访问
用途: 访问CAN/LIN信号的总线值
使用场景:
- 多路复用报文处理
on message MultiplexedMessage
{
switch($MuxSignal) // 读取MUX原始值
{
case 0:
value1 = SignalA; // 物理值
rawValue1 = $SignalA; // 原始值
break;
case 1:
value2 = SignalB;
break;
}
}
- 校验和计算
on message MyMessage
{
byte checksum = $Signal1 + $Signal2 + $Signal3;
if(checksum != $ChecksumSignal)
{
write("校验和错误!计算值: %d, 接收值: %d", checksum, $ChecksumSignal);
}
}
6.2 @符号 - 系统变量访问
用途: 访问系统变量的物理值
使用场景:
- 响应系统变量变化
on sysvar EngineState
{
int state = @EngineState; // 使用@读取系统变量
write("引擎状态变为: %d", state);
if(state == 2)
{
@Sysvar::Display::Message = "引擎已启动"; // 使用@设置系统变量
}
}
- 测试用例控制
testcase CheckEngineStart()
{
@Ignition = 1; // 设置系统变量
@Starter = 1;
TestWaitForTimeout(3000);
if(@EngineSpeed > 500) // 读取系统变量
{
TestStepPass("引擎成功启动");
}
}
6.3 核心区别总结
| 特性 | $ 符号 | @ 符号 |
|---|---|---|
| 变量类型 | CAN/LIN信号(原始值) | 系统变量 |
| 代表的值 | 报文中信号的原始值 | 系统变量的物理值 |
| 数据类型 | 通常是long(整数) | 取决于系统变量定义(int, float, string等) |
| 使用场景 | 校验和、多路复用器、诊断等底层处理 | 系统状态控制、HMI交互、模块间通信 |
| 访问方式 | $SignalName | @SysvarName |
| 值转换 | 原始值 × 因子 + 偏移量 = 物理值 | 直接操作物理值 |
7 应用示例
variables
{
message EngineMsg * myEngineMsg = {dlc = 8};
}
on sysvar Sysvar::StartSimulation
{
// 系统变量控制仿真启动
if (@Sysvar::StartSimulation == 1)
{
putValue(ExtApp_StartCommand, 1); // 环境变量通知外部程序
}
}
on envVar ExtApp_TargetSpeed
{
// 环境变量接收外部指令
long targetSpeed;
getValue(ExtApp_TargetSpeed, targetSpeed);
// 转换为CAN信号(使用物理值)
myEngineMsg.TargetSpeed = targetSpeed;
output(myEngineMsg);
// 使用原始值进行校验和计算
$myEngineMsg.Checksum = calculateChecksum();
output(myEngineMsg);
// 更新系统变量用于显示
@Sysvar::Display::TargetSpeed = targetSpeed;
}
on message VehicleSpeed
{
// 处理CAN信号
float physicalSpeed = VehicleSpeed; // 物理值
long rawSpeed = $VehicleSpeed; // 原始值
// 更新系统变量显示
@Sysvar::Display::ActualSpeed = physicalSpeed;
// 使用原始值进行诊断检查
if(rawSpeed == 0xFFFF)
{
@Sysvar::Errors::InvalidSpeed = 1;
}
}
long calculateChecksum()
{
// 使用原始值计算校验和
return ($Signal1 + $Signal2 + $Signal3) & 0xFF;
}
8 关键要点总结
-
正确选择变量类型:
- 总线通信:CAN/LIN信号
- 内部状态管理:系统变量
- 外部系统集成:环境变量
-
正确使用访问符号:
- 信号物理值:直接使用信号名
- 信号原始值:
$信号名 - 系统变量:
@变量名、SysGetVariableInt/SysGetVariableFloat/SysSetVariableInt/SysSetVariableFloat - 环境变量:
@变量名、getValue()/putValue()
-
值转换关系:
- 物理值 = (原始值 × 因子) + 偏移量
- 原始值 = (物理值 - 偏移量) / 因子
| 特性 | CAN 信号 | LIN 信号 | 系统变量 | 环境变量 |
|---|---|---|---|---|
| 来源/定义 | CANdb (.dbc) 文件 | LDF (.ldf) 文件 | System Variable Group | Environment Variable |
| 作用域 | 特定CAN报文 | 特定LIN帧 | 全局(CANoe内部) | 全局(CANoe与外部) |
| 主要用途 | 在CAN总线上交换数据 | 在LIN总线上交换数据 | CANoe内部模块间数据共享和状态管理 | 与外部应用或硬件(VT)交互 |
| CAPL读取 | 直接使用信号名(读取物理值)、$信号名(读取总线值) | 直接使用信号名(读取物理值)、$信号名(读取总线值) | @变量名、SysGetVariableInt、SysGetVariableFloat | @变量名、getValue(变量名, value) |
| CAPL写入 | 报文.信号 = 物理值; $报文.信号 = 总线值; output(报文); | 帧.信号 = 物理值;$报文.信号 = 总线值; output(帧); | @变量名 = 值;、SysSetVariableInt、SysSetVariableFloat | @变量名 = 值;、putValue(变量名, 值); |
| 触发事件 | on message | on linFrame | on sysvar | on envVar |
| 核心区别 | 总线数据,物理通信 | 总线数据,物理通信 | 内部状态,逻辑控制 | 外部接口,系统集成 |
理解这些区别和正确使用方法,对于编写高效、可靠的CAPL脚本至关重要。
CAPL中信号与变量使用详解
3215






