当前位置: 首页 > news >正文

03-CAPL 常用函数大全

专栏:《CAPL 脚本编写实战指南》第 3 篇
作者:一线汽车电子测试工程师
适合人群:已掌握 CAPL 基础的测试人员、想系统学习 CAPL 函数的工程师


开篇:为什么要学 CAPL 函数?

这是我刚学 CAPL 时的真实经历。

当时的情况

  • 基础语法学会了
  • 但写脚本时不知道用什么函数
  • 每次都要查 Help 文档
  • 效率很低

后来我做了个函数速查表

  • 把常用函数分类整理
  • 每个函数配上示例代码
  • 打印出来贴在电脑旁
  • 写脚本时随时查阅

效果

  • 写脚本效率提升 50%
  • 不用每次都查文档
  • 3 个月后,常用函数都记住了

这篇教程,就是我把当年的速查表整理出来的。

建议

收藏这篇,写脚本时随时查阅。


一、输出函数

1.1 write()

功能:格式化输出到 Write 窗口

语法

write(format, arg1, arg2, ...);

示例

// 输出字符串 write("Hello CAPL"); // 输出整数 int value = 100; write("value = %d", value); // 输出多个值 int a = 10, b = 20; write("a = %d, b = %d", a, b); // 输出十六进制 byte data = 0xFF; write("data = 0x%x", data); // 输出浮点数 float pi = 3.14159; write("pi = %f", pi); // 换行输出 write("第一行"); write("第二行");

格式说明符

说明符类型示例
%d十进制整数write("%d", 100)→ “100”
%x十六进制整数write("%x", 255)→ “ff”
%f浮点数write("%f", 3.14)→ “3.140000”
%s字符串write("%s", "Hello")→ “Hello”
%c字符write("%c", 'A')→ “A”
%ld长整数write("%ld", 1000000L)

注意

  • write() 不会自动换行
  • 需要换行时加\nwrite("line1\nline2")
  • 或用多个 write():write("line1"); write("line2");

1.2 writeHex()

功能:以十六进制格式输出数据

语法

writeHex(format, value);

示例

// 输出十六进制 int value = 255; writeHex("value = %x", value); // "value = ff" // 输出报文数据 on message msg_Test { writeHex("报文数据:%x %x %x", this.byte(0), this.byte(1), this.byte(2)); }

1.3 output()

功能:发送 CAN 报文

语法

output(message);

示例

variables { message CANMessage msg_Test; } on start { msg_Test.canID = 0x123; msg_Test.dlc = 8; msg_Test.byte(0) = 0x10; output(msg_Test); // 发送报文 write("报文已发送"); }

扩展用法

// 周期发送 outputPeriod(msg_Test, 100); // 100ms 周期发送 // 停止发送 outputStop(msg_Test);

二、时间函数

2.1 timeNow()

功能:获取当前时间(毫秒)

语法

long time = timeNow();

示例

on start { long startTime = timeNow(); write("程序启动时间:%d ms", startTime); } on message msg_Test { long recvTime = timeNow(); write("收到报文时间:%d ms", recvTime); }

应用场景

  • 计算执行时间
  • 记录事件时间戳
  • 超时检测

2.2 time()

功能:等待指定时间(不阻塞)

语法

time(milliseconds);

示例

on start { write("开始等待"); time(1000); // 等待 1 秒 write("等待结束"); }

注意

  • time() 是不阻塞的
  • 实际等待时间可能略长于指定时间
  • 精确延时用定时器

2.3 testWaitForTimeout()

功能:测试等待(阻塞)

语法

testWaitForTimeout(milliseconds);

示例

on test { // 发送请求 sendRequest(); // 等待响应(阻塞) testWaitForTimeout(100); // 检查响应 checkResponse(); }

time() vs testWaitForTimeout()

函数阻塞用途
time()一般延时
testWaitForTimeout()测试等待

2.4 定时器函数

设置定时器

variables { msTimer myTimer; } on start { setTimer(myTimer, 100); // 100ms 后触发 } on timer myTimer { write("定时器触发"); setTimer(myTimer, 100); // 重新设置 }

取消定时器

killTimer(myTimer); // 取消定时器

检查定时器

if (timerActive(myTimer)) { write("定时器正在运行"); }

三、字符串函数

3.1 strlen()

功能:获取字符串长度

语法

int len = strlen(str);

示例

char message[100] = "Hello CAPL"; int len = strlen(message); write("长度:%d", len); // 输出:长度:10

3.2 strcpy()

功能:复制字符串

语法

strcpy(destination, source);

示例

char src[100] = "Hello"; char dest[100]; strcpy(dest, src); write("dest = %s", dest); // 输出:dest = Hello

注意

  • 目标缓冲区要足够大
  • 不会检查缓冲区溢出

3.3 strcmp()

功能:比较字符串

语法

int result = strcmp(str1, str2);

返回值

返回值说明
0两字符串相等
<0str1 < str2
>0str1 > str2

示例

char str1[100] = "Hello"; char str2[100] = "Hello"; char str3[100] = "World"; if (strcmp(str1, str2) == 0) { write("str1 等于 str2"); } if (strcmp(str1, str3) != 0) { write("str1 不等于 str3"); }

3.4 strcat()

功能:连接字符串

语法

strcat(destination, source);

示例

char str1[100] = "Hello"; char str2[100] = " CAPL"; strcat(str1, str2); write("str1 = %s", str1); // 输出:str1 = Hello CAPL

注意

  • 目标缓冲区要足够大
  • 不会检查缓冲区溢出

3.5 strstr()

功能:查找子串

语法

char* pos = strstr(str, substr);

返回值

  • 找到:返回子串位置指针
  • 未找到:返回 NULL

示例

char message[100] = "Hello CAPL World"; char* pos; pos = strstr(message, "CAPL"); if (pos != NULL) { write("找到子串"); } else { write("未找到子串"); }

3.6 sprintf()

功能:格式化字符串

语法

sprintf(buffer, format, arg1, arg2, ...);

示例

char buffer[100]; int value = 100; sprintf(buffer, "value = %d", value); write("buffer = %s", buffer); // 输出:buffer = value = 100 // 多个参数 int a = 10, b = 20; sprintf(buffer, "a = %d, b = %d", a, b); write("buffer = %s", buffer);

应用场景

  • 构造日志消息
  • 格式化输出数据
  • 动态生成字符串

四、数学函数

4.1 abs()

功能:求绝对值

语法

int result = abs(value);

示例

int a = abs(10); // 10 int b = abs(-10); // 10 write("a = %d, b = %d", a, b);

4.2 sqrt()

功能:求平方根

语法

float result = sqrt(value);

示例

float a = sqrt(16); // 4.0 float b = sqrt(2.0); // 1.414 write("a = %f, b = %f", a, b);

4.3 pow()

功能:求幂

语法

float result = pow(base, exponent);

示例

float a = pow(2, 3); // 8.0 float b = pow(10, 2); // 100.0 write("a = %f, b = %f", a, b);

4.4 三角函数

float angle = 3.14159 / 4; // 45 度(弧度) float sinVal = sin(angle); // 正弦 float cosVal = cos(angle); // 余弦 float tanVal = tan(angle); // 正切 write("sin = %f, cos = %f, tan = %f", sinVal, cosVal, tanVal);

注意

  • 角度单位是弧度,不是度
  • 转换:弧度 = 度 × π / 180

4.5 取整函数

float f = 3.7; int floorVal = floor(f); // 3(向下取整) int ceilVal = ceil(f); // 4(向上取整) int roundVal = round(f); // 4(四舍五入) write("floor = %d, ceil = %d, round = %d", floorVal, ceilVal, roundVal);

4.6 随机数函数

// 生成 0-99 随机数 int r1 = random(100); // 生成 -50 到 50 随机数 int r2 = random(-50, 50); write("r1 = %d, r2 = %d", r1, r2);

应用场景

  • 模拟随机事件
  • 生成测试数据
  • 压力测试

五、报文操作函数

5.1 发送相关

// 发送报文 output(msg); // 设置周期发送 outputPeriod(msg, 100); // 100ms 周期 // 停止发送 outputStop(msg);

5.2 接收相关

on message msgName { // 读取报文 ID long id = this.canID; // 读取 DLC int dlc = this.dlc; // 读取数据字节 byte data0 = this.byte(0); byte data1 = this.byte(1); // 读取信号(需要 DBC) long speed = $VehicleSpeed; }

5.3 信号操作

// 读取信号值 long speed = $VehicleSpeed; // 设置信号值 msg.VehicleSpeed = 100; // 检查信号是否存在 if (isSignalValid($VehicleSpeed)) { write("信号有效"); }

六、测试函数

6.1 testStep 系列

// 开始测试步骤 testStepBegin("测试步骤名"); // 测试通过 testStepPass("通过原因"); // 测试失败 testStepFail("失败原因"); // 测试不确定 testStepInconclusive("不确定原因");

完整示例

on test { testStepBegin("TC001_正常值测试"); // 测试代码 int result = testFunction(); if (result == 0) { testStepPass("测试通过"); } else { testStepFail("测试失败:错误码 %d", result); } }

6.2 测试报告函数

// 设置测试报告标题 testSetTitle("测试报告标题"); // 添加测试报告内容 testSetAttribute("版本", "1.0"); // 生成测试报告 testGenerateReport();

七、文件操作函数

7.1 文件打开

long handle; // 只读打开 handle = fileOpen("test.txt", FILE_READ); // 只写打开(覆盖) handle = fileOpen("test.txt", FILE_WRITE); // 追加打开 handle = fileOpen("test.txt", FILE_APPEND); if (handle < 0) { write("文件打开失败"); }

7.2 文件读取

long handle; char buffer[100]; handle = fileOpen("test.txt", FILE_READ); if (handle >= 0) { // 读取一行 fileReadLine(handle, buffer, sizeof(buffer)); write("读取内容:%s", buffer); fileClose(handle); }

7.3 文件写入

long handle; handle = fileOpen("log.txt", FILE_APPEND); if (handle >= 0) { fileWrite(handle, "日志内容\n"); fileClose(handle); }

7.4 文件操作

// 删除文件 fileDelete("test.txt"); // 重命名文件 fileRename("old.txt", "new.txt"); // 检查文件是否存在 if (fileExists("test.txt")) { write("文件存在"); }

八、系统函数

8.1 获取系统信息

// 获取系统时间 long sysTime = getSystemTime(); // 获取计算机名 char computerName[100]; getComputerName(computerName, sizeof(computerName)); write("计算机名:%s", computerName);

8.2 执行外部程序

// 执行命令 execute("notepad.exe"); // 执行带参数命令 execute("cmd.exe /c dir");

九、实用代码片段

9.1 格式化输出时间

proc void printTimestamp() { long time = timeNow(); long sec = time / 1000; long ms = time % 1000; write("[%d.%03d] ", sec, ms); } on start { printTimestamp(); write("程序启动"); }

9.2 数据日志

variables { long logHandle; } on start { logHandle = fileOpen("data_log.txt", FILE_WRITE); fileWrite(logHandle, "Time,Value\n"); } on message EngineSpeed { char buffer[100]; sprintf(buffer, "%d,%d\n", timeNow(), $EngineSpeed); fileWrite(logHandle, buffer); } on end { fileClose(logHandle); }

9.3 超时检测

variables { msTimer timeoutTimer; boolean msgReceived; } on start { setTimer(timeoutTimer, 1000); // 1 秒超时 } on message EngineSpeed { msgReceived = true; resetTimer(timeoutTimer); setTimer(timeoutTimer, 1000); } on timer timeoutTimer { if (!msgReceived) { write("EngineSpeed 信号超时!"); } msgReceived = false; setTimer(timeoutTimer, 1000); }

9.4 报文统计

variables { long msgCount; long byteCount; } on message * { msgCount++; byteCount += this.dlc; // 每 100 个报文输出一次统计 if (msgCount % 100 == 0) { write("收到%d个报文,共%d字节", msgCount, byteCount); } } on end { write("总计:%d个报文,%d字节", msgCount, byteCount); }

9.5 字符串处理

proc void trimString(char str[]) { // 去除首尾空格(简化版) int len = strlen(str); if (len > 0 && str[len-1] == ' ') { str[len-1] = '\0'; } } on start { char message[100] = "Hello CAPL "; trimString(message); write("trim 后:%s", message); }

十、函数速查表

10.1 输出函数

函数用途示例
write()格式化输出write("value = %d", v)
writeHex()十六进制输出writeHex("0x%x", v)
output()发送报文output(msg)

10.2 时间函数

函数用途示例
timeNow()获取当前时间long t = timeNow()
time()延时(非阻塞)time(100)
testWaitForTimeout()测试等待(阻塞)testWaitForTimeout(100)
setTimer()设置定时器setTimer(timer, 100)

10.3 字符串函数

函数用途示例
strlen()字符串长度strlen(str)
strcpy()字符串复制strcpy(dest, src)
strcmp()字符串比较strcmp(s1, s2)
strcat()字符串连接strcat(s1, s2)
strstr()查找子串strstr(str, sub)
sprintf()格式化字符串sprintf(buf, "%d", v)

10.4 数学函数

函数用途示例
abs()绝对值abs(-10)
sqrt()平方根sqrt(16)
pow()幂运算pow(2, 3)
sin()/cos()/tan()三角函数sin(3.14/2)
floor()/ceil()取整floor(3.7)
random()随机数random(100)

10.5 测试函数

函数用途示例
testStepBegin()开始测试步骤testStepBegin("TC001")
testStepPass()测试通过testStepPass("通过")
testStepFail()测试失败testStepFail("失败")

10.6 文件函数

函数用途示例
fileOpen()打开文件fileOpen("test.txt", FILE_READ)
fileRead()读取文件fileRead(h, buf, len)
fileWrite()写入文件fileWrite(h, "data")
fileClose()关闭文件fileClose(h)

十一、练习题目

练习 1:格式化输出

// 要求:用 write() 输出以下信息 // "当前时间:XXX ms,计数器:XXX"

练习 2:字符串处理

// 要求:用 sprintf() 构造消息 // "报文 ID: 0xXXX, 数据:XXX"

练习 3:超时检测

// 要求:实现 2 秒超时检测 // 超时后输出"超时"

练习 4:数据日志

// 要求:将收到的报文记录到文件 // 格式:时间,ID, 数据

练习 5:报文统计

// 要求:统计每种 ID 的报文数量 // 每 10 秒输出一次统计结果

十二、常见问题

Q1:write() 输出不显示?

:检查 CANoe 的 Write 窗口是否打开。

菜单:View → Write Window


Q2:定时器不触发?

:检查以下几点:

  1. 定时器变量是否在 variables 块定义
  2. 是否调用了 setTimer()
  3. on timer 事件名是否正确

Q3:文件写入失败?

:检查以下几点:

  1. 文件路径是否正确
  2. 是否有写权限
  3. 文件是否被其他程序占用
  4. 是否调用了 fileClose()

Q4:字符串函数乱码?

  1. 确保文件保存为 UTF-8 编码
  2. 尽量用英文字符串
  3. 中文字符串用 char 数组存储

十三、学习建议

13.1 记忆方法

不要死记硬背,要:

  1. 分类记忆— 按功能分类(输出、时间、字符串…)
  2. 理解记忆— 理解函数用途
  3. 实践记忆— 多用就记住了
  4. 速查表— 写代码时查阅

13.2 练习建议

  1. 每个函数都试试— 写小程序测试
  2. 组合使用— 多个函数配合
  3. 实际项目— 在项目中应用
  4. 总结归纳— 建立自己的速查表

13.3 推荐练习顺序

第 1 天:输出函数(write、output) 第 2 天:时间函数(timeNow、定时器) 第 3 天:字符串函数(strlen、strcpy、sprintf) 第 4 天:数学函数(abs、sqrt、random) 第 5 天:测试函数(testStep 系列) 第 6 天:文件函数(fileOpen、fileWrite) 第 7 天:综合练习

写在最后

CAPL 常用函数就这些。

难吗?不难,多用就记住了。

关键是什么?多练习,多在实际项目中使用。

这篇教程里的所有代码,我都建议你亲手敲一遍。

只有亲手敲过,才是你的知识。

建议

收藏这篇,写脚本时随时查阅。
用多了,常用函数就记住了。

下一篇预告:《第一个 CAPL 脚本:信号测试》

  • 完整项目示例
  • 从 0 到 1 编写
  • 运行和调试
  • 扩展练习

如果本文对你有帮助,欢迎点赞、收藏、关注专栏,第一时间获取更新!

有任何问题,欢迎在评论区留言,我会逐一回复。

练习答案会在第 4 篇公布,先自己试试看!

http://www.jsqmd.com/news/558908/

相关文章:

  • FireRedASR-AED-L模型推理优化:利用GPU算力提升识别速度
  • OpenClaw我的龙虾怎么识别不了图片
  • AI系统-21AI芯片之NoC总线
  • 绝地求生罗技鼠标宏自定义配置指南:性能优化与兼容性设置全攻略
  • 如何高效配置Unity插件框架:终极解决方案指南
  • 同态加密实战:基于TenSEAL的CKKS方案Python实现与性能调优
  • 集团型外勤管理系统怎么选?权限、数据与组织管控 - 企业数字化观察家
  • 半方差函数四大参数保姆级解读:从块金值到变程的空间自相关分析
  • 璀璨星河Starry Night效果展示:多风格并行生成(梵高/达芬奇/莫奈)
  • 旧笔记本别扔!用飞牛OS+阿里云DDNS,5分钟搞定个人云盘外网访问
  • AnimateDiff新手入门指南:从安装到生成你的第一个AI动态短片
  • 大盘风险控制策略分析报告 - 2026年03月30日
  • wan2.1-vae开源可部署价值:规避API调用限制、按需弹性扩展GPU资源
  • 终极指南:5分钟上手BepInEx,打造你的Unity游戏插件帝国 [特殊字符]
  • 双向往复式空气压缩机SOLIDWORKS模型
  • LiuJuan Z-Image效果对比展示:BF16 vs FP16在人像细节与稳定性上的差异
  • 【RAG】【embeddings26】LLMRails嵌入模型
  • Qwen3-4B-Instruct-2507工具调用实战:手把手教你搭建智能问答系统
  • Blender 3MF插件全攻略:提升3D打印工作流效率的关键技术
  • 别再死记硬背了!用LangChain的Tool装饰器,5分钟给你的LLM装上‘天气查询’和‘冷知识’插件
  • OpenCode零基础部署教程:5分钟搭建你的AI编程助手
  • 2026年热门的钛合金切削液/铝合金切削液/金属切削液/切削液值得信赖的生产厂家 - 行业平台推荐
  • RimSort:重构RimWorld模组管理的颠覆性解决方案
  • SAP PS 实战演练:从IDES环境到核心知识点全解析
  • HunyuanVideo-Foley 与LSTM网络结合:生成具有时序演进规律的音效
  • 04-第一个 CAPL 脚本:信号测试
  • 百度网盘Mac版SVIP特权完整解锁方案:3分钟实现高速下载
  • 阿里小云KWS模型Windows部署指南:从环境配置到实战应用
  • 2026养生壶最建议买的品牌推荐 - 品牌排行榜
  • Blender 3MF插件终极指南:无缝连接3D建模与打印工作流