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 0x200 lockCmd;
    lockCmd.byte(0) = 0x01;  // Lock command
    output(lockCmd);
    setTimer(SendLockCommand, 1000);  // Repeat every 1 second
}

2. 测试(Test)

自动化验证 ECU 的行为是否符合预期。

你可以编写测试用例:发送一个命令,检查 ECU 的响应是否正确。

variables
{
    byte doorStatus = 0x00;  // Global variable to store received door status
}

// Handler for receiving door status response from ECU
// Note: This must be defined for the test case to work correctly
on message 0x201  // ECU door status response message ID
{
    doorStatus = this.byte(0);  // Update door status from response
}

testcase TC_LockCommand()
{
    // Send lock command
    message 0x200 lockCmd;
    lockCmd.byte(0) = 0x01;
    output(lockCmd);

    // Wait and check response
    testWaitForTimeout(500);

    // Verify door status (updated by on message handler)
    if (doorStatus == 0x01)
        testStepPass("Door locked successfully");
    else
        testStepFail("Door lock failed");
}

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 entire message to CAN2
    output(msg);
}

说明message CAN2.* msg; 是 CAPL 的特殊语法,用于创建与接收消息相同 ID 的 CAN2 消息。


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 是面向总线的:内置 messagesignal 等数据类型
  • CAPL 语法类似 C 语言,有编程基础的工程师可以快速上手

课后练习

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

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