【MicroPython】使用定时器

dcexpert   2016-3-15 21:54 楼主
在micropython中使用定时器也是非常轻松简单的。要使用定时器,先需要导入Timer库。
from pyb import Timer

先看看基本用法,后面在详细说明

  • 定义Timer
    tm=Timer(n)
    n=1-14,但是3用于内部程序,5/6用于伺服系统和ADC。

更多定义方式:
tm=Timer(1, freq=100)
tm=Timer(4, freq=200, callback=f)

  • 设置频率
    tm.freq(100)

  • 定义回调函数(中断)
    tm.callback(f)

  • 禁用回调函数
    tm.callback(None)

例程:
在定时器1中翻转LED1,频率是1Hz
  1. from pyb import Timer

  2. tim = Timer(1, freq=1)
  3. tim.callback(lambda t: pyb.LED(1).toggle())

一个呼吸灯的例子:
  1. from pyb import Timer

  2. i = 0
  3. def f(t):
  4.     global i
  5.     i = (i+1)%255
  6.     pyb.LED(4).intensity(i)

  7. tm=Timer(4, freq=200, callback=f)

Timer库说明

  • class pyb.Timer(id, ...)
    创建定时器对象,id范围是[1..14]
  • timer.init(*, freq, prescaler, period)
    定时器初始化。
    • freq,频率
    • prescaler,预分频,[0-0xffff],定时器频率是系统时钟除以(prescaler + 1)。定时器2-7和12-14最高频率是84MHz,定时器1、8-11是168MHz
    • peroid,周期值(ARR)。定时器1/3/4/6-15是 [0-0xffff],定时器2和5是[0-0x3fffffff]。
    • mode,计数模式
      • Timer.UP - 从 0 到 ARR (默认)
      • Timer.DOWN - 从 ARR 到 0.
      • Timer.CENTER - 从 0 到 ARR,然后到 0.
    • div,用于数值滤波器采样时钟,范围是1/2/4。
    • callback,定义回调函数,和Timer.callback()功能相同
    • deadtime,死区时间,通道切换时的停止时间(两个通道都不会工作)。范围是[0..1008],它有如下限制:
      • 0-128 in steps of 1.
      • 128-256 in steps of 2,
      • 256-512 in steps of 8,
      • 512-1008 in steps of 16
      deadtime的测量是用source_freq 除以 div,它只对定时器1-8有效。

  • timer.deinit()
    禁止定时器,禁用回调函数,禁用任何定时器通道

  • timer.callback(fun)
    设置定时器回调函数

  • timer.channel(channel, mode, ...)
    设置定时器通道
    • channel,定时器通道号
    • mode,模式
      • Timer.PWM,PWM模式(高电平方式)
      • Timer.PWM_INVERTED,PWM模式(反相方式)
      • Timer.OC_TIMING,不驱动GPIO
      • Timer.OC_ACTIVE,比较匹配,高电平输出
      • Timer.OC_INACTIVE,比较匹配,低电平输出
      • Timer.OC_TOGGLE,比较匹配,翻转输出
      • Timer.OC_FORCED_ACTIVE,强制高,忽略比较匹配
      • Timer.OC_FORCED_INACTIVE,强制低,忽略比较匹配
      • Timer.IC,输入扑捉模式
      • Timer.ENC_A,编码模式,仅在CH1改变时修改计数器
      • Timer.ENC_B,编码模式,仅在CH2改变时修改计数器
    • callback,每个通道的回调函数
    • pin,驱动GPIO,可以是None

    在 Timer.PWM 模式下的参数
    • pulse_width,脉冲宽度
    • pulse_width_percent,百分比计算的占空比

    在 Timer.OC 模式下的参数
    • compare,比较匹配寄存器初始值
    • polarity,极性
      • Timer.HIGH,输出高
      • Timer.LOW,输出低

    在 Timer.IC 模式下的参数(捕捉模式只有在主通道有效)
    • polarity
      • Timer.RISING,上升沿捕捉
      • Timer.FALLING,下降沿捕捉
      • Timer.BOTH,上升下降沿同时捕捉

    Timer.ENC 模式:
    • 需要配置两个Pin
    • 使用 timer.counter() 方法读取编码值
    • 只在CH1或CH2上工作(CH1N和CH2N不工作)
    • 编码模式时忽略通道号

  • timer.counter([value])
    设置或获取定时器计数值

  • timer.freq([value])
    设置或获取定时器频率

  • timer.period([value])
    设置或获取定时器周期

  • timer.prescaler([value])
    设置或获取定时器预分频

  • timer.source_freq()
    获取定时器源频率(无预分频)



【MicroPython】教程



回复评论 (17)

通俗易懂,赞一个。
    懒得很
点赞  2016-3-16 09:29
不错。。。
点赞  2016-3-16 17:15
老大,我现在卡在ADC定时采样上了。好像和ISR不能够使用对象有关联。

  1. from pyb import ADC, Timer, Pin

  2. def daq():
  3.     x = ADC(Pin('X19'))
  4.     print x

  5. tm = Timer(4, freq=10, callback=daq)


抛出这个错误:

  1. uncaught exception in Timer(4) interrupt handler
  2. TypeError:
点赞  2016-7-8 09:51
继续,我加了一个紧急异常buf。

  1. import micropython
  2.     micropython.alloc_emergency_exception_buf(100)


错误是:

  1. >>> tm = Timer(4, freq=10, callback=daq)
  2. >>> uncaught exception in Timer(4) interrupt handler
  3. TypeError: function takes 0 positional arguments but 1 were given
点赞  2016-7-8 09:58
引用: allankliu 发表于 2016-7-8 09:51
老大,我现在卡在ADC定时采样上了。好像和ISR不能够使用对象有关联。



抛出这个错误:

在timer的callback函数中,需要定义一个空参数:

  1. from pyb import ADC, Timer, Pin

  2. x=ADC(Pin('X19'))

  3. def daq(t):
  4.     print(x.read())

  5. tm = Timer(4, freq=1, callback=daq)
点赞  2016-7-8 11:21
工作了!

现在看来x=ADC(Pin('X19'))是创建对象,的确不应该放在ISR函数里。

但是文档里哪里有关于"空"参数说明么?ISR里一定要放一个不用的参数。否则就真的抛出那个错误来。
点赞  2016-7-8 11:44
引用: allankliu 发表于 2016-7-8 11:44 工作了! 现在看来x=ADC(Pin('X19'))是创建对象,的确不应该放在ISR函数里。 但是文档里哪里有关于" ...
应该是micropython的bug,这个问题也困扰了我很久。 还有很多函数没有文档,在慢慢琢磨。如pyb中有很多函数还不知道怎样使用: pyb.pwm pyb.SDCard pyb.Flash 本帖最后由 dcexpert 于 2016-7-8 11:53 编辑
点赞  2016-7-8 11:48
多谢了,我把这个t打印出来了。有意义,居然是定时器对象呵。

  1. x = ADC(Pin('X19'))

  2. def daq(t):
  3.     print(t)
  4.         
  5. tim = Timer(1, freq=1, callback=daq)

  1. Timer(1, freq=1, prescaler=3124, period=53759, mode=UP, div=1, deadtime=0)
  2. Timer(1, freq=1, prescaler=3124, period=53759, mode=UP, div=1, deadtime=0)
  3. Timer(1, freq=1, prescaler=3124, period=53759, mode=UP, div=1, deadtime=0)
  4. Timer(1, freq=1, prescaler=3124, period=53759, mode=UP, div=1, deadtime=0)
点赞  2016-7-8 11:51
引用: allankliu 发表于 2016-7-8 11:51
多谢了,我把这个t打印出来了。有意义,居然是定时器对象呵。

看来是irq函数有一些要求,和普通函数不一样
点赞  2016-7-8 11:54
引用: allankliu 发表于 2016-7-8 11:51
多谢了,我把这个t打印出来了。有意义,居然是定时器对象呵。

利用定时器采样可以吗?我也遇到这个问题了,dht11.measure抛出异常
点赞  2018-5-8 16:49
引用: dcexpert 发表于 2016-7-8 11:54
看来是irq函数有一些要求,和普通函数不一样

大神现在知道irq函数的要求了吗?
点赞  2018-5-8 16:51
引用: wqnow 发表于 2018-5-8 16:51
大神现在知道irq函数的要求了吗?

没有特别要求,主要是不能在回调函数中分配内存。
点赞  2018-5-8 17:24
没用过中断的小白终于突然明白定时器作用,以前一直没找到组织,现在才发现这里有这么多好教程
点赞  2020-3-26 07:28

求教一下定时器怎么关闭,现在陷入了死循环,回调函数写错了,现在就一直报错,代码改成pass烧入进去了 image.png   但是已经不管用了,一上点板子就报之前的错误

image.png

点赞  2020-6-10 15:43
引用: grey27 发表于 2020-6-10 15:43 求教一下定时器怎么关闭,现在陷入了死循环,回调函数写错了,现在就一直报错,代码改成pass烧入进去了  ...

先把main.py文件改名,这样上电就不会自动运行了,然后再修改文件。

点赞  2020-6-10 21:01
dcexpert 发表于 2020-6-10 21:01 先把main.py文件改名,这样上电就不会自动运行了,然后再修改文件。

没有代码的方法关闭定时器吗?我试了一下第一次回调函数打印"1",之后又改成了打印"2",没有断电直接再次烧入,结果时1和2都会打印,证明之前一次的定时器其实并没又关闭。只有断电后第一次的定时器才会被取消

点赞  2020-6-11 16:04
引用: grey27 发表于 2020-6-11 16:04 dcexpert 发表于 2020-6-10 21:01 先把main.py文件改名,这样上电就不会自动运行了,然后再修改文件。 ...

如果在REPL下,需要将callback设置为None,这样就可以取消定时器的回调函数了。

 

tim.callback(None)

点赞  2020-6-11 17:57
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复