如何在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
相关产品推荐
相关产品推荐

