CAPL 编程系列教程的第二期内容,主要讲解在 CANoe 中 CAPL 的运行机制以及基本代码结构,并演示如何创建和运行一个简单的 CAPL 程序。
CAPL 编程系列教程 - 第二期:运行机制与代码结构
一、 学习 CAPL 的前置知识要求
- 重要性: 先了解运行环境和基本结构,才能更好地学习和实践 CAPL 编程
。 - 必备知识:
- 了解 CAN 总线和 CAN 协议基础概念(ECU、报文、信号等)
。 - 熟悉 CANoe 基本操作(创建工程、配置节点、观察报文等)
。 - 熟悉 DBC 文件及其作用(包含报文和信号定义)
。
- 了解 CAN 总线和 CAN 协议基础概念(ECU、报文、信号等)
- 可选知识 (用于高阶学习):
- 了解 UDS 诊断协议(用于学习诊断自动化测试脚本编写)
。
- 了解 UDS 诊断协议(用于学习诊断自动化测试脚本编写)
- 编程基础: 没有编程基础也没关系,课程会从零开始
。
二、 在 CANoe 中准备 CAPL 编程环境
- 创建 CANoe 工程:
- 启动 CANoe
。 File->New-> 选择 CAN 网络模板 (如CAN 500 kBit/s Single Channel) 创建新工程。 - 保存工程 (
Ctrl+S),建议创建专用项目文件夹 (如Learning_CAPL01),配置文件名与文件夹名一致 (Learning_CAPL01.cfg)。
- 启动 CANoe
- 整理 CANoe 界面:
- 保留
Configuration桌面的Simulation Setup面板(用于添加节点)。 - 保留
Trace桌面的Trace窗口(用于观察报文)。 - 保留
Analysis桌面的Data和Graphics窗口(用于观察信号,可选)。
- 保留
- 加载 DBC 文件:
- 在项目工程目录下创建
can_db文件夹。 - 将所需的 DBC 文件(如
virtual_network.dbc)放入该文件夹。 - 在 CANoe
Simulation Setup面板的Databases节点下,右键 ->Add,添加该 DBC 文件。
- 在项目工程目录下创建
- 添加网络节点 (Network Node):
- CAPL 代码通常需要依附于某个节点运行(模拟 ECU 或测试模块)
。 - 在
Simulation Setup的 CAN 总线上右键 ->Insert Network Node(用于仿真 ECU)。 - 替代方案 (后续学习):
Insert Test Module(用于编写测试用例)。 - 右键新添加的节点 ->
Configuration,可以修改节点名称 (如EMS)。
- CAPL 代码通常需要依附于某个节点运行(模拟 ECU 或测试模块)
三、 创建并关联 CAPL 文件 (.can)
- 创建 .can 文件:
- 在节点的
Configuration窗口(或右键节点 ->Edit)中,点击 CAPL 文件编辑框旁的按钮。 - 建议在项目工程目录下创建
Nodes文件夹。 - 在此文件夹下,输入 CAPL 文件名(通常与节点名一致,如
EMS.can),点击“打开”或“保存”来创建文件。
- 在节点的
- CAPL Browser (浏览器/编辑器):
- 创建
.can文件后,会自动使用CAPL Browser工具打开该文件进行编辑。这是 Vector 提供的 CAPL 代码编辑器,随 CANoe 安装 。 - CANoe 和 CAPL Browser 是两个独立的窗口
。
- 创建
- 关联: 创建并保存后,
.can文件就与 CANoe 中的仿真节点关联起来了。后续可以通过双击 CANoe 中的节点图标或点击 Edit按钮重新打开 CAPL Browser 编辑代码。
四、 CAPL Browser 界面简介
- 左侧大纲区: 显示代码的重要结构,如
includes(导入其他文件)、variables(全局变量区)、事件处理函数、自定义函数等。 - 右侧主要编辑区: 编写 CAPL 代码
。 - 右侧辅助面板:
- CAPL Functions: 列出并可搜索 CAPL 内置函数,方便查找和使用
。 - Symbols: 显示当前工程加载的 DBC 文件中的报文 (Frames)、信号 (Signals) 等符号信息,方便在编码时查阅
。
- CAPL Functions: 列出并可搜索 CAPL 内置函数,方便查找和使用
- 底部 Output 窗口: 显示编译信息,包括错误和警告
。
五、 CAPL 核心概念:事件驱动模型
- CAPL (Communication Access Programming Language): Vector 公司设计的、类 C 的、用于 CANoe/CANalyzer 等工具的编程语言
。 - 事件驱动: CAPL 不是像传统程序那样从头执行到尾,而是基于事件来触发代码执行
。 - 运行机制: CANoe 工程运行后,总线上会发生各种事件(如测量开始/结束、按键按下、收到特定报文、信号值变化等)
。 - 代码执行: 当某个事件发生时,如果 CAPL 文件中编写了处理该事件的代码块(通常以
on SomeEvent {...}形式定义),那么该代码块内的语句就会被执行。
六、 CAPL 代码结构与基础示例
- 文件编码: 文件开头的
encoding 936注释允许在代码中使用中文注释。 includes段: 用于导入其他 CAPL 文件(模块化编程时使用)。 variables段: 全局变量定义区。在此定义的变量可以在文件内所有事件处理代码块中使用。 - 事件处理代码块:
on start: 当 CANoe 测量开始时(即点击启动按钮后)执行一次。 - 示例:在此事件中发送单帧报文。
message 0x196 msg196;: 定义一个 ID 为 0x196 的报文变量msg196。可以基于 ID 或 DBC 中的报文名称定义 。 msg196.EMS_EngineSpeed.phys = 2800;: 设置报文中EMS_EngineSpeed信号的物理值为 2800。 .phys表示物理值。 output(msg196);: 使用output()内置函数将配置好的报文发送到总线上。
- 示例:在此事件中发送单帧报文。
on timer <timer_variable>: 当指定的定时器超时时执行。 - 示例:实现周期性发送报文。
msTimer timerSendMessage196;: 在variables全局区定义一个毫秒级定时器变量timerSendMessage196。需要全局定义,因为要在多个事件中使用 。 on start { setTimerCyclic(timerSendMessage196, 100); }: 在on start事件中,使用setTimerCyclic()函数启动定时器,周期为 100 毫秒。 on timer timerSendMessage196 { ... }: 定义定时器超时事件的处理代码。将之前发送单帧报文的代码(定义报文变量、赋值、output)放入此代码块内,即可实现每 100ms 发送一次更新后的报文。
- 示例:实现周期性发送报文。
on key '<key_char>': 当按下键盘上指定的按键时执行。 - 示例:按 'x' 键停止周期发送。
on key 'x' { cancelTimer(timerSendMessage196); }: 定义按键 'x' 的事件处理。使用cancelTimer()函数停止之前启动的周期定时器。
- 示例:按 'x' 键停止周期发送。
- 编译与运行:
- 编写代码后,按
Compile(编译) 按钮或Ctrl+S保存(通常会自动编译),检查 Output 窗口是否有错误。 - 回到 CANoe 窗口,点击启动按钮运行工程。
- 观察 Trace、Data、Graphics 窗口验证 CAPL 代码是否按预期执行(如报文是否发送、信号值是否正确、周期发送是否能被按键停止等)
。
- 编写代码后,按
- 获取帮助: 在 CAPL Browser 中,将光标放在函数或关键字上,按
F1可以打开 CANoe 帮助文档,查看详细说明和用法。
七、 总结与后续
- 本期重点理解了 CAPL 的事件驱动模型,并通过实例演示了如何在 CANoe 中创建、编写和运行基础的 CAPL 代码,涉及了
on start,on timer,on key三种常用事件。 - 后续将深入学习 CAPL 的语法细节
。