3.3. 虚拟定时器¶
计时 页面介绍了时间戳以及由 time.ticks_diff() 驱动的非阻塞循环。虚拟定时器则是另一面:软件请求运行时按某个时间表调用一个函数,而运行时会调用该回调,无需脚本自己去检查时钟。
3.3.1. machine.Timer 类¶
machine.Timer 用于构造一个虚拟定时器。跨移植版本的行为需要使用特殊的 id -1;其他一切——周期、模式、回调——都通过关键字参数设置:
from machine import Timer
def tick(t):
print("tick")
tim = Timer(-1)
tim.init(period=100, callback=tick) # 10 Hz
回调像任何普通函数调用一样被调用——它可以分配对象、调用 print() 以及调用其他库代码,没有任何特殊限制。
3.3.2. 周期性与单次¶
有两种模式可供选择:
Timer.PERIODIC(默认)。回调每隔period毫秒触发一次,永远持续,直到调用deinit()或重新初始化定时器。Timer.ONE_SHOT。回调在init()之后period毫秒触发一次,随后定时器停止。
Timer(-1).init(mode=Timer.ONE_SHOT, period=2000, callback=fire)
deinit() 停止一个周期性定时器并取消任何待处理的回调:
tim.deinit()
3.3.3. 何时该使用定时器¶
虚拟定时器和 计时 中的 ticks_diff() 轮询模式从相反的方向解决同一个问题。轮询循环每次迭代都检查时钟,并在过去了足够时间时动作;定时器则请求运行时在过去了足够时间时唤醒脚本。
轮询式
ticks_diff。一切都保持在一处——循环掌管着计时,没有额外的回调需要跟踪。最适合那些短小、定义明确、把多个时间驱动任务联系在一起的工作。虚拟定时器。把时间表从循环体中移出去。最适合周期性任务独立于主流程的情形(心跳 LED、周期性传感器采样),并让主循环把时间花在其他工作上。
两种方法都使用同一个底层时钟,在毫秒或更长的周期上给出相同的精度。两者都不适合精确的引脚翻转或亚毫秒级的波形生成——回调延迟在调度器 tick 这个量级上,而不是纳秒级。