【雕爷学编程】MicroPython手册之 RP2(Pico)计时器

在这里插入图片描述
MicroPython是为了在嵌入式系统中运行Python 3编程语言而设计的轻量级版本解释器。与常规Python相比,MicroPython解释器体积小(仅100KB左右),通过编译成二进制Executable文件运行,执行效率较高。它使用了轻量级的垃圾回收机制并移除了大部分Python标准库,以适应资源限制的微控制器。

MicroPython主要特点包括:
1、语法和功能与标准Python兼容,易学易用。支持Python大多数核心语法。
2、对硬件直接访问和控制,像Arduino一样控制GPIO、I2C、SPI等。
3、强大的模块系统,提供文件系统、网络、图形界面等功能。
4、支持交叉编译生成高效的原生代码,速度比解释器快10-100倍。
5、代码量少,内存占用小,适合运行在MCU和内存小的开发板上。
6、开源许可,免费使用。Shell交互环境为开发测试提供便利。
7、内置I/O驱动支持大量微控制器平台,如ESP8266、ESP32、STM32、micro:bit、掌控板和PyBoard等。有活跃的社区。

MicroPython的应用场景包括:
1、为嵌入式产品快速构建原型和用户交互。
2、制作一些小型的可 programmable 硬件项目。
3、作为教育工具,帮助初学者学习Python和物联网编程。
4、构建智能设备固件,实现高级控制和云连接。
5、各种微控制器应用如物联网、嵌入式智能、机器人等。

使用MicroPython需要注意:
1、内存和Flash空间有限。
2、解释执行效率不如C语言。
3、部分库函数与标准版有差异。
4、针对平台优化语法,订正与标准Python的差异。
5、合理使用内存资源,避免频繁分配大内存块。
6、利用原生代码提升速度关键部位的性能。
7、适当使用抽象来封装底层硬件操作。

总体来说,MicroPython让Python进入了微控制器领域,是一项重要的创新,既降低了编程门槛,又提供了良好的硬件控制能力。非常适合各类物联网和智能硬件的开发。
在这里插入图片描述
RP2(Pico)是树莓派基金会推出的一款微控制器开发板,基于自研的 RP2040 芯片,售价仅为 4 美元。它可以用 C/C++ 或 Python 语言编程,适合用于物联网、机器人、音乐等各种应用场景。技术参数:RP2(Pico)的技术参数如下:

1、搭载双核 ARM Cortex M0+ 处理器,运行频率 133 MHz
2、内置 264 KB 的片上 RAM,板载 2 MB 闪存
3、可通过专用 QSPI 总线支持最高 16 MB 的片外闪存
4、DMA 控制器
5、30 个 GPIO 引脚,其中 4 个可用作模拟输入
6、2 个 UART、2 个 SPI 控制器和 2 个 I2C 控制器
7、16 个 PWM 通道
8、USB 1.1 主机和设备支持
9、8 个树莓派可编程 I/O(PIO)状态机,用于自定义外围设备支持
10、支持 UF2 的 USB 大容量存储启动模式,用于拖放式编程

【雕爷学编程】MicroPython手册之 RP2(Pico)计时器_第1张图片
MicroPython的RP2(Pico)计时器是一种用于定时和计时任务的功能模块,它在嵌入式系统和物联网应用中具有广泛的应用。

主要特点:

精确计时能力:RP2(Pico)计时器提供了精确的计时功能,可以以微秒级或毫秒级的精度测量时间。这种高精度的计时能力使得它非常适合需要准确计时的应用场景,如数据采集、测量、调度等。

多种计时模式:RP2(Pico)计时器支持多种计时模式,包括单次触发模式、周期性触发模式和输入捕获模式。单次触发模式用于执行一次性的任务或延迟执行任务,周期性触发模式用于定时执行任务,而输入捕获模式用于捕获外部事件的时间戳。

多个计时器实例:RP2(Pico)计时器提供多个独立的计时器实例,可以同时处理多个计时任务。每个计时器实例都有自己的配置和回调函数,可以灵活地根据具体需求进行设置和管理。

应用场景:

嵌入式系统:RP2(Pico)计时器在嵌入式系统中具有广泛的应用。它可以用于精确的任务调度、周期性数据采集、定时触发传感器读取等场景,以满足实时性要求。

物联网应用:在物联网应用中,RP2(Pico)计时器可以用于设备之间的时序同步、事件触发和定时任务执行。例如,可以利用计时器实现多个传感器数据的同步采集,或者按照预定时间间隔发送数据等。

控制系统:RP2(Pico)计时器在控制系统中起到关键作用。它可以用于周期性控制任务的调度,例如定时控制电机转动、周期性检测传感器状态等。通过精确的计时能力,可以确保控制系统按照预期的时间间隔执行任务,提高系统的稳定性和可靠性。

需要注意的事项:

计时器资源限制:RP2(Pico)上的计时器资源是有限的,因此在使用计时器时需要注意资源的分配和管理。如果需要多个计时器实例,确保合理分配计时器资源,并避免资源冲突。

中断处理:RP2(Pico)计时器通常通过中断来触发计时任务。在编写计时器的回调函数时,应注意避免阻塞或长时间执行的操作,以免影响系统的响应性能。

精度误差:尽管RP2(Pico)计时器提供了高精度的计时能力,但在实际应用中,由于硬件和软件的限制,可能存在一定的计时误差。在对计时精度要求较高的应用中,需要进行适当的校准和补偿,以确保精确的计时结果。

总之,MicroPython的RP2(Pico)计时器是一种强大的计时和定时功能模块,具有精确计时能力、多种计时模式和多个计时器实例等特点。它在嵌入式系统和物联网应用中有广泛的应用。在使用RP2(Pico)计时器时,需要注意合理分配计时器资源、避免阻塞操作、处理计时精度误差等事项。这样才能充分利用计时器的功能,满足实时性要求,并提高系统的稳定性和可靠性。

参考代码案例:

案例1:控制 LED 闪烁:这是一个简单的程序,用于控制 Pico 开发板上的内置 LED(GPIO 25)闪烁。代码如下:

# 导入 machine 模块,用于控制 GPIO 和 Timer
import machine

# 创建一个 Pin 对象,表示 GPIO 25 引脚
led = machine.Pin(25, machine.Pin.OUT)
# 创建一个 Timer 对象,设置为周期性模式,周期为 1 秒
tim = machine.Timer(period=1000, mode=machine.Timer.PERIODIC)
# 定义一个回调函数,用于切换 led 引脚的电平
def toggle(t):
    led.toggle()
# 将回调函数绑定到 Timer 对象上
tim.callback(toggle)

测量排序算法时间:这是一个稍微复杂的程序,用于测量不同排序算法(冒泡排序和选择排序)对同一组数据进行排序所需的时间。代码如下:

# 导入 time 模块,用于计时
import time
# 导入 random 模块,用于生成随机数据
import random

# 定义一个冒泡排序算法的函数
def bubble_sort(data):
    # 获取数据的长度
    n = len(data)
    # 遍历数据的每个元素
    for i in range(n):
        # 遍历数据的剩余元素
        for j in range(n - i - 1):
            # 如果前一个元素大于后一个元素,则交换它们的位置
            if data[j] > data[j + 1]:
                data[j], data[j + 1] = data[j + 1], data[j]

# 定义一个选择排序算法的函数
def selection_sort(data):
    # 获取数据的长度
    n = len(data)
    # 遍历数据的每个元素
    for i in range(n):
        # 假设当前元素是最小的元素
        min_index = i
        # 遍历数据的剩余元素
        for j in range(i + 1, n):
            # 如果找到比当前元素更小的元素,则更新最小元素的索引
            if data[j] < data[min_index]:
                min_index = j
        # 如果最小元素不是当前元素,则交换它们的位置
        if min_index != i:
            data[i], data[min_index] = data[min_index], data[i]

# 创建一个空列表,用于存储随机数据
data = []
# 生成 1000 个随机整数,并添加到列表中
for i in range(1000):
    data.append(random.randint(0, 10000))

# 复制一份原始数据,用于冒泡排序
data1 = data.copy()
# 获取当前的微秒计数器值,作为冒泡排序的开始时间
start1 = time.ticks_us()
# 调用冒泡排序算法的函数,对数据进行排序
bubble_sort(data1)
# 获取当前的微秒计数器值,作为冒泡排序的结束时间
end1 = time.ticks_us()
# 计算冒泡排序所需的时间,单位为微秒
time1 = time.ticks_diff(end1, start1)

# 复制一份原始数据,用于选择排序
data2 = data.copy()
# 获取当前的微秒计数器值,作为选择排序的开始时间
start2 = time.ticks_us()
# 调用选择排序算法的函数,对数据进行排序
selection_sort(data2)
# 获取当前的微秒计数器值,作为选择排序的结束时间
end2 = time.ticks_us()
# 计算选择排序所需的时间,单位为微秒
time2 = time.ticks_diff(end2, start2)

# 在 REPL 上打印两种排序算法的时间比较结果
print("Bubble sort time: {} us".format(time1))
print("Selection sort time: {} us".format(time2))

案例3:生成 PWM 信号:这是一个较为高级的程序,用于生成 PWM(脉宽调制)信号来控制电机或 LED。代码如下:

# 导入 machine 模块,用于控制 GPIO 和 Timer
import machine

# 创建一个 Pin 对象,表示 GPIO 0 引脚(连接电机或 LED)
pin = machine.Pin(0, machine.Pin.OUT)
# 创建一个 Timer 对象,设置为 PWM 模式,频率为 50 Hz
tim = machine.Timer(freq=50, mode=machine.Timer.PWM)
# 定义一个回调函数,用于改变 PWM 的占空比
def change_duty(t):
    # 获取当前的占空比
    duty = t.duty_u16()
    # 如果占空比达到最大值,则减小占空比
    if duty == 65535:
        t.duty_u16(duty - 1000)
    # 如果占空比达到最小值,则增大占空比
    elif duty == 0:
        t.duty_u16(duty + 1000)
    # 否则,根据当前的方向来改变占空比
    else:
        direction = t.direction()
        if direction == 1:
            t.duty_u16(duty + 1000)
        else:
            t.duty_u16(duty - 1000)
# 将回调函数绑定到 Timer 对象上,并设置周期为 0.1 秒
tim.callback(change_duty, period=0.1)
# 将 Timer 对象连接到 Pin 对象上,开始输出 PWM 信号
tim.channel(pin)

案例4:使用计时器实现周期性的任务调度:

import machine
import utime

# 定义任务1的回调函数
def task1_callback(timer):
    print("执行任务1")

# 定义任务2的回调函数
def task2_callback(timer):
    print("执行任务2")

# 初始化计时器1
timer1 = machine.Timer()

# 设置计时器1参数
timer1.init(mode=machine.Timer.PERIODIC, period=1000, callback=task1_callback)

# 初始化计时器2
timer2 = machine.Timer()

# 设置计时器2参数
timer2.init(mode=machine.Timer.PERIODIC, period=500, callback=task2_callback)

# 主循环
while True:
    # 执行其他任务
    # ...

    utime.sleep_ms(100)  # 给其他任务留出时间片

这个程序使用计时器实现周期性的任务调度。

定义了两个任务的回调函数 task1_callback 和 task2_callback,分别在计时器触发时执行相应的任务。

使用 machine.Timer() 初始化两个计时器对象 timer1 和 timer2。

分别使用 timer1.init() 和 timer2.init() 方法设置计时器的参数,参数 mode 设置定时器模式为周期性,period 设置计时器的周期,单位是毫秒,callback 设置计时器触发时调用的回调函数。

在主循环中可以执行其他任务,通过调用 utime.sleep_ms() 方法留出时间片给其他任务。

案例5:使用计时器实现一次性延迟任务:

import machine
import utime

# 定义延迟任务的回调函数
def delay_task_callback(timer):
    print("延迟任务执行")

# 初始化计时器
timer = machine.Timer()

# 设置延迟任务的参数
timer.init(mode=machine.Timer.ONE_SHOT, period=5000, callback=delay_task_callback)

# 主循环
while True:
    # 执行其他任务
    # ...

    utime.sleep_ms(100)  # 给其他任务留出时间片

这个程序使用计时器实现一次性的延迟任务。

定义了延迟任务的回调函数 delay_task_callback,在计时器触发时执行延迟任务。

使用 machine.Timer() 初始化计时器对象 timer。

使用 timer.init() 方法设置延迟任务的参数,参数 mode 设置定时器模式为一次性,period 设置延迟任务的延迟时间,单位是毫秒,callback 设置计时器触发时调用的回调函数。

在主循环中可以执行其他任务,通过调用 utime.sleep_ms() 方法留出时间片给其他任务。

案例6:使用计时器实现精确的时间测量:

import machine
import utime

# 定义开始时间和结束时间
start_time = 0
end_time = 0

# 定义计时器回调函数
def timer_callback(timer):
    global end_time
    end_time = utime.ticks_us()

# 初始化计时器
timer = machine.Timer()

# 设置计时器参数
timer.init(mode=machine.Timer.ONE_SHOT, period=5000, callback=timer_callback)

# 执行需要计时的代码
# ...

# 获取经过的时间
elapsed_time = utime.ticks_diff(end_time, start_time)
print("执行时间:", elapsed_time, "微秒")

这个程序使用计时器实现精确的时间测量。定义了开始时间 start_time 和结束时间 end_time,用于记录时间戳。定义了计时器回调函数 timer_callback,在计时器触发时记录结束时间。使用 machine.Timer() 初始化计时器对象 timer。使用 timer.init() 方法设置计时器的参数,参数 mode 设置定时器模式为一次性,period 设置计时器的延迟时间,单位是毫秒,callback 设置计时器触发时调用的回调函数。执行需要计时的代码段之前,使用 utime.ticks_us() 方法获取开始时间,返回的是微秒级的时间戳。在计时器触发的回调函数中,使用 utime.ticks_us() 方法获取结束时间,并将其赋值给全局变量 end_time。在需要计时的代码段之后,使用 utime.ticks_diff() 方法计算经过的时间,参数是结束时间和开始时间,返回的是微秒级的时间差。通过打印语句输出执行时间。这样可以实现对代码段执行时间的精确测量。

案例7:使用RP2(Pico)计时器测量时间间隔

import time
from machine import Pin, Timer

# 初始化引脚和计时器
pin = Pin(13, Pin.OUT)
timer = Timer(-1)

# 设置计时器回调函数
def callback(timer):
    print('Timer expired!')

# 启动计时器,每隔1秒触发一次回调函数
timer.init(period=1000, mode=Timer.PERIODIC, callback=callback)

# 主循环
while True:
    pin.value(1)  # 设置引脚为高电平
    time.sleep_ms(500)  # 延时500毫秒
    pin.value(0)  # 设置引脚为低电平
    time.sleep_ms(500)  # 延时500毫秒

案例8:使用RP2(Pico)计时器实现倒计时功能

import time
from machine import Pin, Timer

# 初始化引脚和计时器
pin = Pin(13, Pin.OUT)
timer = Timer(-1)

# 设置计时器回调函数
def callback(timer):
    print('Timer expired!')
    if timer.time >= 10:  # 倒计时10秒
        timer.cancel()  # 取消计时器
        pin.value(0)  # 设置引脚为低电平
    else:
        timer.init(period=1000, mode=Timer.PERIODIC, callback=callback)

# 启动计时器,每隔1秒触发一次回调函数
timer.init(period=1000, mode=Timer.PERIODIC, callback=callback)

# 主循环
while True:
    pass

案例9:使用RP2(Pico)计时器实现闹钟功能

import time
from machine import Pin, Timer

# 初始化引脚和计时器
pin = Pin(13, Pin.OUT)
timer = Timer(-1)

# 设置计时器回调函数
def callback(timer):
    print('Alarm!')
    timer.cancel()  # 取消计时器
    pin.value(0)  # 设置引脚为低电平

# 设置闹钟时间(单位:毫秒)
alarm_time = 5000  # 闹钟响铃时间为5秒后

# 启动计时器,每隔1秒触发一次回调函数
timer.init(period=1000, mode=Timer.PERIODIC, callback=callback)

# 等待闹钟时间到达
while timer.time < alarm_time:
    pass

# 取消计时器
timer.cancel()

案例10:简单的计时器程序

import machine  
import utime  
  
# 配置GPIO引脚为输出模式  
led = machine.Pin(25, machine.Pin.OUT)  
  
def timer_callback():  
    print("计时器回调函数被触发!")  
  
# 创建计时器对象,设置回调函数和超时时间  
timer = utime.Timer(1.0, timer_callback)  
  
while True:  
    led.toggle()  # 翻转LED状态  
    utime.sleep(0.5)  # 等待0.5秒  
  
    # 重启计时器  
    timer.init(1.0, timer_callback)

案例11:倒计时程序

import machine  
import utime  
  
# 配置GPIO引脚为输出模式  
led = machine.Pin(25, machine.Pin.OUT)  
  
def timer_callback():  
    print("计时器回调函数被触发!")  
  
# 创建计时器对象,设置回调函数和超时时间  
timer = utime.Timer(1.0, timer_callback)  
  
# 设置倒计时时间(单位:秒)  
countdown_time = 10  
  
while True:  
    led.toggle()  # 翻转LED状态  
    utime.sleep(0.5)  # 等待0.5秒  
  
    # 更新倒计时时间,并显示剩余时间  
    countdown_time -= 0.5  
    print("剩余时间:", countdown_time, "秒")  
  
    # 如果倒计时时间到达0,则停止计时器并退出循环  
    if countdown_time <= 0:  
        timer.deinit()  # 停止计时器  
        break

案例12:周期性触发程序

import machine  
import utime  
  
# 配置GPIO引脚为输出模式  
led = machine.Pin(25, machine.Pin.OUT)  
  
def timer_callback():  
    print("计时器回调函数被触发!")  
    led.toggle()  # 翻转LED状态  
  
# 创建计时器对象,设置回调函数和超时时间,并设置周期性触发标志位  
timer = utime.Timer(1.0, timer_callback, periodic=True)  
  
while True:  
    utime.sleep(0.5)  # 等待0.5秒

请注意,以上案例只是为了拓展思路,可能存在错误或不适用的情况。不同的硬件平台、使用场景和MicroPython版本可能会导致不同的使用方法。在实际编程中,您需要根据您的硬件配置和具体需求进行调整,并进行多次实际测试。

【雕爷学编程】MicroPython手册之 RP2(Pico)计时器_第2张图片

你可能感兴趣的:(MicroPython手册,单片机,嵌入式硬件,python,MicroPython,RP2(Pico)计时器)