CAPL 编程系列第十五期-第十九期回顾

第十五期 (回顾 - 函数基础

  1. 知识回顾: 定义函数的主要目的是什么?(至少说出两点)
  2. 知识回顾: CAPL 函数定义的基本结构包含哪几个主要部分?
  3. 知识回顾: 如果一个 CAPL 函数不需要返回任何计算结果,其返回值类型应该声明为什么?
  4. 知识回顾: 函数定义中的参数称为什么参数?函数调用时传递的参数称为什么参数?
  5. 知识回顾: return 语句在函数中的作用是什么?
  6. 逻辑推理: 定义函数 int calculate(int x) { return x * x; } 后,执行 int result = calculate(5);,变量 result 的值是多少?
  7. 知识回顾: 函数体(花括号 {} 内的部分)中定义的变量属于什么类型的作用域(全局还是局部)?
  8. 逻辑推理: 如果定义了一个函数 float get Pi() { return 3.14; },那么语句 write("Pi is %d", getPi()); 是否能正确输出 Pi 的值?为什么?
  9. 知识回顾: 函数定义完成后,函数体内的代码会立即执行吗?如果不会,在什么时候执行?
  10. 逻辑推理: 定义函数 void printMsg() { write("Hello"); },在 on key 'a' 事件中写 printMsg;(注意没有小括号),按下 'a' 键后会输出 "Hello" 吗?为什么?

第十六期 回顾 - 函数进阶

  1. 知识回顾: 在 CAPL 中,如果一个函数没有返回值,其返回值类型 void 是否可以省略?
  2. 知识回顾: 定义一个不需要任何输入参数的函数时,函数名后面的小括号 () 是否可以省略?
  3. 知识回顾: 什么是函数重载 (Function Overloading)?重载的函数必须满足哪些条件?
  4. 逻辑推理: 定义了 int add(int a, int b)float add(float a, float b) 这两个函数,这在 CAPL 中构成合法的重载吗?为什么?
  5. 逻辑推理: 定义了 int add(int a, int b)int add(int numbers[]) 两个函数,调用 add(5, 10) 时会执行哪个函数?调用 int data[3]={1,2,3}; add(data); 时会执行哪个函数?
  6. 知识回顾: 当数组作为函数参数传递时,函数内部对形参数组的修改是否会影响到调用者传入的原始实参数组?这种传递方式类似于值传递还是引用传递?
  7. 知识回顾: CAPL 函数能否直接将数组作为返回值类型来返回?
  8. 知识回顾: 如果函数需要“返回”一个数组,通常采用什么变通的方法来实现?
  9. 逻辑推理: 在斐波那契数列的例子中,函数 generateFibonacci(int n, int numbers[]) 的返回值类型为什么是 void (或省略)?它是如何将计算结果“传递”给调用者的?
  10. 知识回顾: 在函数体内部使用不带值的 return; 语句的作用是什么?通常用在什么类型的函数中?

第十七期 回顾 - 定时器 (Timer)

  1. 知识回顾: CAPL 中提供哪两种类型的定时器?它们的主要区别是什么?
  2. 知识回顾: 定时器变量必须在 CAPL 脚本的哪个区域声明?
  3. 知识回顾: 每个声明的定时器变量需要对应定义一个什么事件处理块?其语法是怎样的?
  4. 知识回顾: setTimer(TimerName, DelayTime) 函数的作用是什么?它启动的定时器会触发几次?
  5. 知识回顾: cancelTimer(TimerName) 函数的作用是什么?
  6. 逻辑推理: 如何使用 setTimer 函数实现一个周期性(例如每 500 毫秒)触发的定时器逻辑?关键代码应该写在哪里?
  7. 知识回顾: setTimerCyclic(msTimerName, CycleTime) 函数是专门用于哪种类型的定时器?它与在 on timer 中重新调用 setTimer 相比有什么优点?
  8. 逻辑推理: 执行 msTimer myMsTimer; setTimerCyclic(myMsTimer, 0, 500); 后,on timer myMsTimer 事件处理块大约在什么时候会第一次被触发?之后会以什么频率触发?
  9. 逻辑推理: 如果在一个 on timer myTimer { ... } 事件处理块中忘记了再次调用 setTimer(myTimer, ...) (假设是用 setTimer 启动的),这个 on timer 事件会被再次触发吗?
  10. 逻辑推理: 如果在 on key 'a' 中启动了一个周期定时器 timerA,在 on key 'b' 中调用 cancelTimer(timerA),在 on timer timerA 中又调用了 setTimer(timerA, 100)。那么当按下 'a' 键开始周期触发后,再按下 'b' 键,定时器 timerA 是否还会继续触发?

第十八期 回顾 - Message 与报文发送基础

  1. 知识回顾: 在 CAPL 中,代表 CAN 报文的数据类型关键字是什么?
  2. 知识回顾: 声明一个 ID 为 0x7DF 的报文变量 responseMsg 的语法是什么?
  3. 知识回顾: 如何设置报文变量 responseMsg 的数据长度码 (DLC) 为 8?使用哪个选择器?
  4. 知识回顾: 如何设置报文变量 responseMsg 的第一个数据字节 (索引为 0) 的值为 0x02?使用哪个选择器?
  5. 知识回顾: 使用 .word(index) 选择器给报文赋值时,需要注意字节顺序的哪个细节?例如 msg.word(0) = 0xABCD;msg.byte(0)msg.byte(1) 的值分别是多少?
  6. 知识回顾: 用于将配置好的报文变量发送到总线上的 CAPL 内置函数是什么?
  7. 逻辑推理: 如果声明 message 0x188 msg; 但没有设置 .dlc 和任何数据字节,直接调用 output(msg);,总线上发出的报文 DLC 和数据是怎样的?
  8. 知识回顾: 除了在声明后单独赋值,还可以在声明报文变量时使用什么语法进行初始化?
  9. 逻辑推理: message 0x123 msg = { dlc=5, byte(0)=1, byte(4)=2 }; 这句代码执行后,msg.byte(1), msg.byte(2), msg.byte(3) 的值是多少?
  10. 逻辑推理: 声明 message 0x100 msgA;message 0x100 msgB; 后,执行 msgA.byte(0)=0xAA; msgB=msgA; output(msgB); 发送出的报文 msgB 的第一个字节是什么?这说明 message 变量的赋值是怎样的行为?(类似值类型还是引用类型?)

第十九期 回顾 - 基于 DBC 的报文与信号操作

  1. 知识回顾: 与直接使用报文 ID 相比,在加载了 DBC 文件后,使用 DBC 中定义的报文名称来声明 message 变量有什么主要优点?
  2. 知识回顾: 假设 DBC 中定义了报文 EngineData 包含信号 EngineSpeed,如何声明该报文变量并将其 EngineSpeed 信号的物理值设置为 2500?
  3. 知识回顾: 在 CAPL 中通过信号名称访问或赋值时(如 msg.EngineSpeed = 2500;),我们操作的是信号的物理值还是原始值?CAPL 如何处理底层的位操作和转换?
  4. 逻辑推理: 如果 DBC 文件中定义 EngineSpeed 信号的 Factor=0.1, Offset=0。在 CAPL 中执行 msg.EngineSpeed = 150.5; 后,报文中对应 EngineSpeed 的原始值(整数)应该是多少?
  5. 知识回顾: 为什么说在有 DBC 文件的情况下,通过信号名操作报文比通过 .byte().word() 操作字节方便得多?
  6. 逻辑推理: 能否在一个没有加载 DBC 文件的 CAPL 节点中,使用 msg.EngineSpeed = 3000; 这样的语法?为什么?
  7. 知识回顾: 如何在声明 message 变量的同时,通过信号名称初始化其包含的信号值?写出基本语法结构。
  8. 逻辑推理: message EngineState myMsg = { EngineSpeed = 1000 }; 这句代码中,myMsgOnOff 信号(假设它也在 EngineState 中定义)的值会是多少?
  9. 知识回顾: 结合定时器和信号赋值,可以实现什么常见的仿真或测试场景?
  10. 逻辑推理: 在一个周期定时器事件 on timer tSend { ... } 中,连续执行 msg.SignalA = 10; output(msg); msg.SignalA = 20; output(msg);,总线上会发出几条报文?第二条报文中 SignalA 的值是多少?