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

MicroPython实现GPIO控制函数指定时机后台精准运行方法

MicroPython GPIO精准后台定时实现方案

问题本质

当前代码属于阻塞式顺序执行逻辑:主循环按顺序执行calc_one_two()→func()→some_other_actions(),只要some_other_actions()这类耗时任务在运行,后续的GPIO控制逻辑必须等它完全执行完才能启动;哪怕在func()里用time.sleep_ms()做延时,本质还是CPU空等阻塞,无法实现和其他耗时任务并行、精准时间点触发的需求。
原阻塞式问题代码如下:

import time
from machine import Pin

a_1 = Pin(21, Pin.OUT)
a_2 = Pin(20, Pin.OUT)

def do_something(x):
    print(x)

def some_other_actions():
    time.sleep(10)

def calc_one_two():
    return 1, 2

def func(a, b, on_tmr=2, off_tmr=1):

    a_1.on()
    do_something(a)
    time.sleep_ms(on_tmr)  # sleep for 2ms
    a_1.off()
    time.sleep_ms(off_tmr)  # sleep for 1ms

    a_2.on()
    do_something(b)
    time.sleep_ms(on_tmr)  # sleep for 2ms
    a_2.off()
    time.sleep_ms(off_tmr)  # sleep for 1ms

while True:
    one, two = calc_one_two()
    func(one, two)
    some_other_actions()  # actions that need some time

实现方法

用MicroPython内置的硬件定时器machine.Timer实现后台精准调度,硬件定时器由芯片内置定时器外设驱动,定时触发不受主循环阻塞任务影响,到点会自动抢占执行回调函数,从根源解决主循环阻塞导致的时序偏移问题。

改造后可直接运行的代码

import time
from machine import Pin, Timer

# 硬件初始化
a_1 = Pin(21, Pin.OUT)
a_2 = Pin(20, Pin.OUT)
tim = Timer(0)  # 调用硬件定时器0,不同芯片定时器编号可按需调整

# 时序状态机参数
current_step = 0
ON_DURATION = 2  # 高电平持续2ms
OFF_DURATION = 1 # 低电平间隔1ms
step_trigger_flag = 0  # 主从逻辑传递事件的标志位
a_val = 0
b_val = 0

def do_something(x):
    print(x)

def some_other_actions():
    time.sleep(10)

def calc_one_two():
    return 1, 2

# 定时器回调,1ms触发一次,仅执行微秒级快操作
def tmr_callback(t):
    global current_step, step_trigger_flag
    # 时序周期共6ms:a1高2ms→低1ms→a2高2ms→低1ms循环
    if current_step == 0:
        # 0ms位置:a1拉高
        a_1.on()
        step_trigger_flag = 1
        current_step += 1
    elif current_step == ON_DURATION:
        # 2ms位置:a1拉低
        a_1.off()
        current_step += 1
    elif current_step == ON_DURATION + OFF_DURATION:
        # 3ms位置:a2拉高
        a_2.on()
        step_trigger_flag = 2
        current_step += 1
    elif current_step == ON_DURATION + OFF_DURATION + ON_DURATION:
        # 5ms位置:a2拉低
        a_2.off()
        current_step += 1
    elif current_step == ON_DURATION*2 + OFF_DURATION*2:
        # 6ms位置:重置状态进入下一轮循环
        current_step = 0
    else:
        current_step += 1

# 初始化定时器,周期1ms循环触发
tim.init(period=1, mode=Timer.PERIODIC, callback=tmr_callback)

# 主循环,执行耗时任务不会影响GPIO时序精度
while True:
    one, two = calc_one_two()
    a_val, b_val = one, two
    # 检测定时器置位标志,执行打印等慢操作
    if step_trigger_flag == 1:
        do_something(a_val)
        step_trigger_flag = 0
    elif step_trigger_flag == 2:
        do_something(b_val)
        step_trigger_flag = 0
    # 哪怕此处休眠10s,GPIO输出时序依然精准运行
    some_other_actions()

关键注意事项

  • 定时器回调运行在中断上下文,绝对不能在回调里放耗时操作:包括print()、time.sleep()、内存分配、文件读写等,否则会导致时序抖动、系统崩溃,仅保留GPIO翻转、变量赋值这类几微秒就能完成的操作
  • 日志打印、复杂计算这类慢逻辑,通过标志位传递到主循环执行即可,不会影响GPIO控制精度
  • 硬件定时器的定时精度通常在10微秒以内,完全满足毫秒级GPIO时序要求,不会被主循环的长耗时任务阻塞
  • 不同型号MicroPython板卡的可用硬件定时器数量有差异,若定时器0被占用可更换其他编号

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:39:34