定时器¶
概要¶
本文介绍了定时器与回调函数的概念,以及如何在MicroPython-ESP32中使用定时器,最后用定时器控制LED进行周期的闪烁。
keywords Timer callback led blink
什么是定时器?¶
定时器你可以理解为一个闹钟,你可以设定特定时间之后执行某件事情,也可以周期的执行某件事情,比如每隔1s钟变换一下LED的亮灯状态。
定时器与utime
模块中的sleep
延时函数最大区别在于,延时函数期间,CPU就如同进入了睡眠,之后的事情只有等睡醒之后再做,这种情况我们称之为阻塞, 睡觉阻塞了cpu去完成其他的任务,必须等待CPU睡醒;而定时器是非阻塞的,在未到达定时器定时周期结束之前,CPU可以去做别的事情,等到定时器计时完毕,便会去通知CPU,CPU再去执行回调函数 (在你设定闹钟之前,你决定要在闹钟响了之后去做的事情)。
定时器每个周期都会产生一次中断,然后调用特定的 回调函数callback, 定时器中断属于内部中断.
中断¶
CPU的中断分为很多种,不同的中断拥有不同的优先级别。当多个中断同时发生时,计算机按照优先级来以此处理
Timer-常用API¶
Timer
类被封装在machine
模块中。
from machine import Timer
实例化一个Timer
对象,传入一个任意正整数作为ID。
例如:
timer = Timer(1)
然后需要 初始化定时器:
timer.init(period=1000, mode=Timer.PERIODIC , callback=callback)
-
period
定时器执行的周期,单位是ms
, 隔period ms 执行一次。 period取值范围:0 < period <= 3435973836
-
mode
定时器的执行模式 -
Timer.PERIODIC
周期执行 -
Timer.ONE_SHOT
只执行一次,执行完了定时器就结束 -
callback
: 定时器的回调函数,传入的一个参数是timer
如果你想在callback函数里面传入其他参数,可以参照下方 定时器控制LED闪烁 中的 Lambda表达式 的方法。
timer.init(period=period, mode=Timer.PERIODIC, callback=lambda t:led_toggle(led_pin))
最后,定时器使用完了记得要释放定时器资源,键盘中断并不会销毁定时器,定时器会一直产生回调函数。
timer.deinit()
定时器控制LED闪烁¶
定时器控制LED闪烁 timer_led_blink.py
from machine import Timer,Pin import utime def toggle_led(led_pin): ''' LED状态反转 ''' led_pin.value(not led_pin.value()) def led_blink_timed(timer, led_pin, freq=10): ''' led 按照特定的频率进行闪烁 LED闪烁周期 = 1000ms / 频率 状态变换间隔(period) = LED闪烁周期/ 2 ''' # 计算状态变换间隔时间 ms period = int(0.5 * 1000 / freq) # 初始化定时器 # 这里回调是使用了lambada表达式,因为回调函数需要传入led_pin timer.init(period=period, mode=Timer.PERIODIC, callback=lambda t:toggle_led(led_pin)) # 声明引脚 D2 作为LED的引脚 led_pin = Pin(2, Pin.OUT) timer = Timer(1) # 创建定时器对象 led_blink_timed(timer, led_pin, freq=20)
效果展示:
工程经验¶
注意,不要在定时器回调函数里面创建变量,可以使用 全局变量 global,因为定时器每次都创建变量比较消耗内存。
在毫秒级周期执行的定时器回调函数里面,
千万不要在终端里面Print
千万不要在终端里面Print
千万不要在终端里面Print
因为在终端Print打印会干扰Timer回调函数执行频率。而且定时器在产生按键中断CTRL+C
的时候 并不会注销,如果定时器回调函数一直在打印,它会一直打印 占用REPL资源,影响你使用REPL。