延时器与定时器
1 延时器
让cpu暂停一下(自己控制时长),然后再继续工作。
前面已经实现的LED闪烁和PWM里面的呼吸灯,都有用到延时功能。
1.1 延时模块utime
在micropython中,系统延时需要用到utime
模块。该模块下有以下三个sleep
函数:
utime.sleep(seconds)
以秒为单位的延时utime.sleep_ms(ms)
毫秒级的延时utime.sleep_us(us)
微秒级的延时
例如延时1秒(也即1000毫秒)
utime.sleep(1)
utime.sleep_ms(1000)
1.2 示例再来一遍
# 控制LED闪烁
from machine import Pin
import utime # 直接用time模块也是可以的
led = Pin(2, Pin.OUT)
while 1:
utime.sleep_ms(500) # 延时 500ms
led.value(not led.value()) # 切换亮灭状态
2 定时器
2.1 与延时器的区别
定时器与utime模块中的sleep延时函数最大区别在于,延时函数期间,CPU就如同进入了睡眠,之后的事情只有等睡醒之后再做,这种情况我们称之为阻塞, 睡觉阻塞了cpu去完成其他的任务,必须等待CPU睡醒;
而定时器是非阻塞的,在未到达定时器定时周期结束之前,CPU可以去做别的事情,等到定时器计时完毕,便会去通知CPU,CPU再去执行回调函数 。定时器每个周期都会产生一次中断,然后调用特定的 回调函数callback, 定时器中断属于内部中断.
2.2 定时器模块Timer
from machine import Timer
timer = Timer(-1)
实例化时,给Timer()传递了一个id=-1构造参数,指的是创建一个虚拟设备定时器,当时id>=0时,需要对应到真实的物理硬件,这里先不扩展了。
定时器的执行方法:
timer.init(*, mode=Timer.PERIODIC, period=-1, callback=None)
- period 定时器执行的周期,单位是ms, 隔period ms 执行一次。 period取值范围: 0 < period <= 3435973836
- mode 定时器的执行模式
- Timer.PERIODIC 周期执行
- Timer.ONE_SHOT 只执行一次,执行完了定时器就结束
- callback: 定时器的回调函数,传入的一个参数是timer
2.3 来个完整的示例
from machine import Timer,Pin
def toggle_led(led_pin):
led_pin.value(not led_pin.value())
led_pin = Pin(2, Pin.OUT)
timer = Timer(-1)
timer.init(period=500, mode=Timer.PERIODIC, callback=lambda t:toggle_led(led_pin))
2.4 销毁定时器
定时器实例是在上下文任务中单独执行的,如果在REPL环境中执行上面的示例,使用CTRL+C
并不能中断定时器回调函数的执行,所以需要调整实例的注销方法来释放定时器资源
timer.deinit()
3 扩展一下:看门狗和喂狗时间
看门狗就是一个守护线程,平时不需要关心它,我们所写的代码是在主线程中执行的。当守护线程识别到主线程没反应的时候,就会软重启来复位所有的信息。
那怎么识别呢,主要是通过看门狗提供的feed
喂狗方法来实现,主线程需要定时喂狗来告诉看门狗,我还在工作呢,你继续守你的大门啊。
例如:
from machine import WDT
wdt = WDT(timeout=5000) #允许狗子饿肚子5秒
wdt.feed()
看门狗官方文档中介绍的esp8266芯片是不允许自定义timeout
参数的,饿肚子超时时间系统底层决定
我们在REPL中实测一下:
>>> from machine import WDT
>>> wdt = WDT()
>>> wd... # wdt.feed()
实例化了看门狗对象中,手打喂狗代码的功夫,系统已经软重启了。。。。 狗子你太狠