Timer 定时器

祭出引脚图, 查看Timer资源

我们可以看到一共有两个定时器资源 TM1 , TM4 其他是没引出来的

Note: Timer(1) is used for the camera. Similarly, Timer(5) controls the servo driver, and Timer(6) is used for timed ADC/DAC reading/writing. It is recommended to use the other timers in your programs.

官方文档连接 http://docs.openmv.io/library/pyb.Timer.html?highlight=timer

意思也就是 Timer1 用于控制摄像头

Timer5用于控制舵机驱动, Timer6用于定时ADC/DAC 读或写

所以,我们编程的时候不能使用这三个。

那也就是说,可以用 2,3,4 喽

定时器的几种模式

  • 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改变时修改计数器

下面的教程, 只涉及最简单的模式, 阶段性调用某一个函数。

初始化Timer

from pyb import Timer

# Timer 传入的是Timer的序号, 选择第几个定时器
timer = Timer(4)

# 设置频率为10, 也就意味着1s执行10次, 也就是间隔100ms
timer.init(freq=10)

绑定事件的两种方式

方式1

# func会自动接收timer这个对象
def func(timer):
    print(timer.counter())

timer = Timer(4)
timer.init(freq=10)
# 定义回调函数
timer.callback(func)

样例代码

TODO

方式2

def func():
    ...

timer = Timer(4)
timer.init(freq=10)
# 定义回调函数
timer.callback(lambda t: func())

样例代码

利用定时器每隔100ms令LED闪烁一次

import time
from pyb import Timer
from pyb import LED


led = LED(1)
led.on()

def led_on_off():
    global led
    led.toggle()


timer = Timer(4)
timer.init(freq=10)
timer.callback(lambda t: led_on_off())


while True:
    # 这里只延时 啥也不干
    time.sleep(1000)

开辟缓存 ,显示报错信息

定时器调用的时候, 不可以开辟新的内存, 这一点很重要

当你在定时器的回调函数定义一个新的变量或者定义一个字符串的时候,就会提示有Memory Error的错误。

Note: Memory can’t be allocated during a callback (an interrupt) and so exceptions raised within a callback don’t give much information. Seemicropython.alloc_emergency_exception_buf() for how to get around this limitation.

同时也意味着如果定时器函数回调期间出现了BUG, 不能返回完整的报错信息。

所以我们需要提前申请一块缓存, 用于异常处理。

import micropython

micropython.alloc_emergency_exception_buf(100)

例如如下代码

未加紧急异常缓存的代码

import time
from pyb import Timer
from pyb import LED



led = LED(1)
led.on()

def led_on_off():
    global led
    led.toggle()


timer = Timer(4)
timer.init(freq=10)
timer.callback(led_on_off)


while True:
    # 这里只延时 啥也不干
    time.sleep(1000)

未加紧急异常缓存的报错信息

uncaught exception in Timer(4) interrupt handler
TypeError:

可以看到只有一个报错信息

加了紧急异常缓存的代码

import time
from pyb import Timer
from pyb import LED

# 申请一块紧急异常缓存
import micropython
micropython.alloc_emergency_exception_buf(100)

led = LED(1)
led.on()

def led_on_off():
    global led
    led.toggle()


timer = Timer(4)
timer.init(freq=10)
timer.callback(led_on_off)


while True:
    # 这里只延时 啥也不干
    time.sleep(1000)

加了紧急异常缓存之后的报错

uncaught exception in Timer(4) interrupt handler
TypeError: function takes 0 positional arguments but 1 were given

可以看到更加详细了

原因是,led_on_off没有任何传入参数, 但是callback(led_on_off)

就相当于传给led_on_off函数一个timer参数

修改之后的正确版本

import time
from pyb import Timer
from pyb import LED

import micropython
micropython.alloc_emergency_exception_buf(100)

led = LED(1)
led.on()
# 添加了一个timer参数, 但是可能用不到
def led_on_off(timer):
    global led
    led.toggle()


timer = Timer(4)
timer.init(freq=10)
timer.callback(led_on_off)


while True:
    # 这里只延时 啥也不干
    time.sleep(1000)

小灯正常闪烁

定时器的正确写法

假定现在我们有个需求, 需要使用定时器,阶段性的检查串口是否有数据, 并且将其读入。

如何实现? 如何克服我们之前说的那个, callback时不可以申请内存的问题?

解决方法是, 定时器只判断修改标志位(flag, 标志位设置为全局变量 global), 然后在while 循环里, 根据标志位,做相应的处理

TOOD: DEBUG

from pyb import UART

import micropython
micropython.alloc_emergency_exception_buf(100)


uart = UART(4, 115200)

has_data = False # 初始化为没有数据读入

def is_data_coming(timer):
    global uart
    global has_data

    if uart.any():
        has_data = True
    else:
        has_data = False


timer = Timer(4)
timer.init(freq=10)
timer.callback(led_on_off)


while True:
    # 这里只延时 啥也不干
    if has_data:
        data = uart.readline()
        print(data)
    time.sleep(1000)
Copyright 杭州云江科技有限公司 2017 all right reserved,powered by Gitbook该文件修订时间: 2018-04-02 09:53:12

results matching ""

    No results matching ""