You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Raspberry Pi Pico中用utime.ticks_us精准测量方波周期

Raspberry Pi Pico精准测量方波周期的优化方案

你的代码采用软件轮询方式检测方波边沿,误差主要来自CPU轮询的延迟和函数调用的开销——每次检查Pin.value()和调用utime.ticks_us()都会消耗微秒级的CPU周期,导致边沿检测和时间记录的时刻不准,最终产生数微秒偏差。以下是几种精准度从高到低的优化方案:

方案一:硬件定时器输入捕获(最高精度)

利用Pico的硬件定时器输入捕获功能,完全由硬件记录边沿时间,无需CPU干预,精度可达定时器时钟级(默认1MHz下为1μs),几乎无误差。

import utime
from machine import Pin, Timer

period = 0
last_capture = 0

def capture_handler(timer):
    global period, last_capture
    current = timer.channel(0, Timer.CAPTURE).value()
    if last_capture != 0:
        period = current - last_capture
    last_capture = current

# 初始化定时器:1MHz时钟,计数单位1μs
timer = Timer(0)
timer.init(freq=1000000)
# 配置通道0为输入捕获模式,引脚2上升沿触发
timer.channel(0, Timer.CAPTURE, pin=Pin(2), trigger=Timer.RISING, callback=capture_handler)

while True:
    if period != 0:
        print(period)
        period = 0  # 重置避免重复打印
    utime.sleep_ms(100)

方案二:外部中断捕获边沿(次高精度)

用硬件中断触发边沿检测,代替软件轮询,中断响应速度远快于轮询,能大幅降低检测延迟。

import utime
from machine import Pin

last_edge = 0
period = 0

def edge_handler(pin):
    global last_edge, period
    now = utime.ticks_us()
    if last_edge != 0:
        period = utime.ticks_diff(now, last_edge)
    last_edge = now

# 配置引脚2为输入,上升沿触发中断
in_pin = Pin(2, Pin.IN)
in_pin.irq(trigger=Pin.IRQ_RISING, handler=edge_handler)

while True:
    if period != 0:
        print(period)
        period = 0
    utime.sleep_ms(100)

注意:中断回调函数要尽量简短,避免执行耗时操作,否则会影响中断响应速度。

方案三:多次测量取平均(快速优化现有代码)

如果暂时不想改动硬件相关逻辑,可通过多次测量取平均值抵消随机误差,让结果更接近真实值。

import utime
from machine import Pin

inPin = Pin(2, Pin.IN)

def get_single_period():
    # 等待第一个上升沿
    while inPin.value() != 0:
        pass
    while inPin.value() == 0:
        pass
    start = utime.ticks_us()
    # 等待下一个上升沿(完成一个周期测量)
    while inPin.value() != 0:
        pass
    while inPin.value() == 0:
        pass
    end = utime.ticks_us()
    return utime.ticks_diff(end, start)

while True:
    sample_count = 10
    total = 0
    for _ in range(sample_count):
        total += get_single_period()
    avg_period = total // sample_count
    print(avg_period)

内容的提问来源于stack exchange,提问作者thoriq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:05:30