CAPL Script

什么是 CAPL 脚本?

学习目标

完成本篇后,你将能够:

  • 理解 CAPL 在汽车电子开发测试中的定位与价值
  • 说出 CAPL 的四大核心应用场景
  • 认识 CAPL 程序的基本结构和事件驱动特性
  • 对整个教程系列有清晰的学习路线图

从一个真实场景说起

假设你是一名汽车电子工程师,正在开发一个车门控制器(ECU)。这个控制器需要:

  • 接收中控锁的上锁/解锁命令
  • 控制车窗升降
  • 向仪表盘反馈门锁状态

问题来了:你的 ECU 还在开发中,但仪表盘、中控锁等其他 ECU 也没准备好。你怎么测试自己的代码?

这时候,你需要一个工具来"假装"其他 ECU 存在,发送测试命令,检查你的 ECU 是否正确响应。

这个工具就是 CANoe,而让 CANoe "听话"的语言,就是我们今天要认识的 CAPL。


CAPL 是什么?

CAPL(Communication Access Programming Language,通信访问编程语言)是 Vector 公司为 CANoe/CANalyzer 软件开发的专用编程语言。

你可以把它理解为:

CAPL 是 CANoe 的"脚本语言",让你能编程控制总线上的一切。

如果你熟悉 C 语言,你会发现 CAPL 的语法非常相似。但 CAPL 有两个显著特点:

1. 事件驱动

传统 C 程序从 main() 开始顺序执行。而 CAPL 程序是被动响应的——它等待事件发生,然后做出反应。

比如:

  • 收到一条 CAN 消息 → 触发 on message 事件
  • 按下键盘某个键 → 触发 on key 事件
  • 定时器到期 → 触发 on timer 事件

2. 面向总线

CAPL 天生就是为汽车总线设计的。它内置了 message(消息)、signal(信号)等数据类型,可以直接读写 CAN/LIN/FlexRay 等总线数据。


CAPL 能做什么?

CAPL 有四大核心应用场景:

1. 仿真(Simulation)

模拟一个还不存在的 ECU。

回到开篇的例子:你可以用 CAPL 写一个"虚拟中控锁",周期性发送上锁/解锁命令,让你的车门控制器以为真的有个中控锁在工作。

variables
{
    msTimer SendLockCommand;  // Timer declaration
}

on start
{
    setTimer(SendLockCommand, 1000);  // Start timer on measurement start
}

on timer SendLockCommand
{
    message CAN1.0x200 lockCmd;
    lockCmd.RTR = 0;
    lockCmd.DLC = 1;
    lockCmd.byte(0) = 0x01;  // Lock command
    output(lockCmd);
    setTimer(SendLockCommand, 1000);  // Repeat every 1 second
}

2. 测试(Test)

通过新观察和有界等待检查明确的要求。

缓存中的 doorStatus == 1 可能来自上一次报文。发送新命令、等待 500 ms 再读取它,即使没有任何新响应也可能误报成功。测试必须确认数据新鲜度,校验触发事件的通道、方向与 DLC,并定义响应和请求的对应规则。

先从范围较窄的心跳可用性测试开始。它分别处理超时、中断、数据提取与载荷错误;通过只表示观察到了有效心跳,不表示车门已经锁定。真实命令测试需要 ECU 的实际协议和关联规则。

3. 诊断(Diagnostics)

发送和响应诊断请求。

当你需要读取 ECU 的故障码、刷写软件、或执行 UDS(统一诊断服务)时,CAPL 可以帮你构造和解析诊断报文。

4. 网关/分析

在不同总线之间转发消息,或监控分析数据流。

比如,把 CAN1(CAN 总线 1)上的消息转发到 CAN2(CAN 总线 2):

on message CAN1.*
{
    // Special syntax: create a message for CAN2 with same ID as received message
    message CAN2.* msg;
    if (this.dir != rx) return;  // Only process received messages
    msg = this;  // Copy received frame
    msg.CAN = 2;  // Select destination after copying
    output(msg);
}

范围:此转发片段用于隔离的经典 CAN 配置。通配报文对象通过赋值获得 ID,复制后应显式设置目标通道。没有防环路设计时,不要再增加反向转发路径。


CAPL 程序长什么样?

让我们看一个最简单的 CAPL 程序:

on key 'a'
{
    write("Hello CAPL!");
}

这段代码做了什么?

  1. on key 'a' — 当用户按下键盘上的 a 键时
  2. write("Hello CAPL!") — 在 CANoe 的 Write 窗口输出一行文字

就这么简单!没有 main() 函数,没有复杂的初始化。事件发生,代码执行。

再看一个稍微复杂的例子——响应 CAN 消息:

// Note: EngineData message and EngineSpeed signal must be defined in DBC database
on message EngineData
{
    if (this.EngineSpeed > 3000)
    {
        write("Warning: Engine speed is high!");
    }
}

这段代码会在收到名为 EngineData 的 CAN 消息时,检查其中的 EngineSpeed(发动机转速)信号。如果转速超过 3000,就输出警告。

提示:this.EngineSpeed 这种直接访问信号的方式需要先在 DBC 数据库中定义 EngineData 消息和 EngineSpeed 信号。


本教程的学习路线图

本系列共 8 篇文章,将带你从零开始掌握 CAPL:

篇章 主题 你将学会
第一篇 什么是 CAPL? 认知与定位(本篇)
第二篇 开发环境搭建 创建并运行第一个 CAPL 程序
第三篇 编程基础 变量、函数、CAPL 特有类型
第四篇 核心交互 事件驱动模型、数据库集成
第五篇 调试技巧 断点、日志、错误排查
第六篇 仿真节点开发 构建一个完整的虚拟 ECU
第七篇 测试模块开发 编写自动化测试用例
第八篇 综合项目 仿真与测试的完整闭环

第六、八篇共用车门模型。第七篇通过独立心跳协议学习有界等待;只有改写预期协议之后,才能把该方法接到车门项目。


本篇总结

通过本篇的学习,我们了解了:

  • CAPL 是 CANoe/CANalyzer 的专用编程语言,用于仿真、测试、诊断和分析
  • CAPL 是事件驱动的:程序响应事件(消息到达、按键、定时器)而执行
  • CAPL 是面向总线的:内置 message、signal 等数据类型
  • CAPL 语法类似 C 语言,有编程基础的工程师可以快速上手

课后练习

  1. 思考题:在你当前的工作中,有哪些场景可以用 CAPL 解决?(提示:考虑仿真、测试、诊断三个方向)

  2. 预习任务:如果你已经安装了 CANoe,尝试打开一个示例工程,找到其中的 .can 文件(这就是 CAPL 源代码),浏览一下它的结构。