CAPL 编程系列教程 - 第十七期:定时器 (Timer)

CAPL 编程系列教程的第十七期内容,主要讲解 CAPL 中的一个特殊且重要的数据类型/机制:定时器 (Timer)

CAPL 编程系列教程 - 第十七期:定时器 (Timer)

一、 课程回顾与本期目标

  • 回顾: 前面学习了 CAPL 的基础数据类型、复合数据类型(数组、结构、枚举)、运算符、分支和循环结构、函数定义与调用。
  • 本期目标: 学习 CAPL 中的定时器,理解如何使用定时器实现延迟执行或周期性执行代码块。

二、 定时器 (Timer) 的基本概念

  • 作用: 用于在指定的时间间隔后执行某段代码,或者按照设定的周期重复执行某段代码 。这在需要模拟周期性行为(如周期发送报文)或在特定延迟后执行动作的场景中非常关键
  • 数据类型: CAPL 提供两种定时器类型
    • timer: 秒级定时器,时间单位是秒。
    • msTimer: 毫秒级定时器 (millisecond timer),时间单位是毫秒。
  • 事件驱动关联: 定时器变量本身不直接赋值,而是与一个事件处理代码块 (on timer) 相关联,该代码块定义了定时器到期(触发)时需要执行的操作

三、 定时器的声明与事件处理

  1. 声明定时器变量:
    • 必须在全局变量区 variables { ... } 内声明 不能在局部代码块(如 on key 或函数内部)声明。
    • 语法:timer TimerName1;msTimer TimerName2;
    • 示例:
      Code snippet
      variables {
          timer timer1; // 声明一个秒级定时器变量 timer1
          msTimer timer2; // 声明一个毫秒级定时器变量 timer2
      }
      
    • 声明后,CAPL Browser 可能会有绿色下划线提示,表明尚未定义对应的 on timer 事件处理块
  2. 定义 on timer 事件处理块:
    • 必须为每个声明的定时器变量定义一个对应的 on timer 事件处理块
    • 语法:
      Code snippet
      on timer TimerName { // TimerName 必须与 variables 中声明的定时器变量名一致
          // 定时器到期(触发)时执行的代码
      }
      
    • 作用: 定义当名为 TimerName 的定时器到期被触发时,需要执行的具体操作(如发送报文、修改变量、调用函数等)
    • 示例:
      Code snippet
      on timer timer1 {
          write("timer1 定时器触发了!");
      }
      on timer timer2 {
          write("timer2 定时器触发了!");
      }
      

四、 启动和控制定时器

  1. 启动单次定时器 (setTimer):

    • 作用: 设置一个定时器,在指定的时间之后触发一次其对应的 on timer 事件
    • 语法: setTimer(TimerName, DelayTime);
    • TimerName: 要启动的定时器变量名。
    • DelayTime: 延迟的时间。如果 TimerNametimer 类型,单位是秒;如果是 msTimer 类型,单位是毫秒
    • 示例:
      Code snippet
      on key 'a' {
          setTimer(timer1, 2);  // 2 秒后触发 timer1 一次
          setTimer(timer2, 4000); // 4000 毫秒 (4秒) 后触发 timer2 一次
      }
      
  2. 实现周期性定时器 (使用 setTimer):

    • 思路: 在定时器的 on timer 事件处理块内部,执行完所需操作后,再次调用 setTimer 为其自身设置下一次触发
    • 示例:
      Code snippet
      on timer timer1 {
          write("timer1 定时器触发了!(每 2 秒一次)");
          setTimer(timer1, 2); // 再次设置 2 秒后触发
      }
      on timer timer2 {
          write("timer2 定时器触发了!(每 5 秒一次)");
          setTimer(timer2, 5000); // 再次设置 5000 毫秒后触发
      }
      on key 'a' {
          setTimer(timer1, 2);  // 首次启动
          setTimer(timer2, 5000); // 首次启动
      }
      
    • 这种方式对 timermsTimer 都适用
  3. 启动周期性毫秒定时器 (setTimerCyclic):

    • 作用: 专门用于启动毫秒级 (msTimer) 定时器,使其按照指定的周期自动重复触发
    • 语法: setTimerCyclic(msTimerName, CycleTime);setTimerCyclic(msTimerName, FirstDelay, CycleTime);
    • msTimerName: 必须是 msTimer 类型的定时器变量名。不能用于 timer 类型的变量
    • CycleTime: 重复触发的周期,单位是毫秒
    • FirstDelay (可选): 第一次触发前的延迟时间,单位是毫秒。如果省略,则第一次触发也在 CycleTime 之后;如果为 0,则几乎立即触发第一次
    • 优点: 比在 on timer 中手动重置 setTimer 更简洁方便
    • 示例:
      Code snippet
      variables { msTimer timer4; }
      on timer timer4 { write("timer4 定时器触发!(周期 4 秒)"); }
      on key 'a' {
          // 几乎立即触发第一次,然后每 4000ms (4秒) 触发一次
          setTimerCyclic(timer4, 0, 4000); 
      }
      
  4. 取消/停止定时器 (cancelTimer):

    • 作用: 停止一个已经启动(无论是用 setTimer 还是 setTimerCyclic 启动)的定时器,使其不再触发
    • 语法: cancelTimer(TimerName);
    • TimerName: 要停止的定时器变量名。
    • 调用时机: 可以在任何需要停止定时器的地方调用,例如:
      • 在另一个事件(如 on key 'b')中手动停止
      • 在定时器自身的 on timer 事件中,当满足某个条件时(如达到执行次数)停止
      • 在另一个定时器的 on timer 事件中停止其他定时器
    • 示例:
      Code snippet
      on key 'b' {
          cancelTimer(timer1); // 按 B 键停止 timer1
          write("timer1 定时器取消了");
      }
      
      variables { int timer2Count = 0; }
      on timer timer2 {
          write("timer2 定时器触发!");
          timer2Count++;
          if (timer2Count >= 5) { // 触发 5 次后停止
              cancelTimer(timer2);
              write("timer2 定时器已取消 (达到次数)");
          } else {
              setTimer(timer2, 5000); // 继续下一次 (如果用 setTimer 启动)
          }
      }
      

五、 总结与后续

  • 本期学习了 CAPL 中定时器 timer (秒级) 和 msTimer (毫秒级) 的使用方法。
  • 重点掌握了定时器的声明 (在 variables 区)、on timer 事件处理、启动 (setTimer, setTimerCyclic) 和停止 (cancelTimer)。
  • 理解了如何使用定时器实现延迟执行和周期性执行。
  • 定时器是实现时间相关逻辑(如周期发送、超时处理)的基础。
  • 下一期将讲解 CAPL 中非常核心的概念:message (报文) 类型变量。