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

如何在While循环中兼顾按键输入响应与I2C数据定时刷新?

解决while循环中按键响应与I2C定时更新的冲突问题

问题核心在于time.sleep(1)是阻塞式操作,会让整个循环暂停1秒,导致按键检测无法及时响应。解决关键是用非阻塞的时间判断替代阻塞休眠,让循环快速执行按键检测,同时仅在达到指定时间间隔时更新I2C数据。

方案一:基于时间戳的非阻塞判断

通过记录上次更新I2C的时间,每次循环计算当前时间与上次时间的差值,当差值达到1秒时才执行I2C更新。这样循环可高速运行,保证按键检测的灵敏性。

修正后的代码示例:

from machine import Pin
from time import sleep, ticks_ms, ticks_diff

up_button = Pin(13, Pin.IN)
last_i2c_update = ticks_ms()  # 记录上次I2C更新的毫秒时间戳

while True:
    # 实时检测按键状态
    logic_state = up_button.value()
    if logic_state == True:
        print("Button Pressed")
    
    # 检查是否到了I2C更新时间
    current_time = ticks_ms()
    if ticks_diff(current_time, last_i2c_update) >= 1000:  # 间隔≥1000毫秒(1秒)
        update_i2c_data()  # 轮询I2C设备获取新数据
        last_i2c_update = current_time  # 更新时间戳
    
    # 可选:微小休眠降低CPU占用,不影响按键响应
    sleep(0.01)

代码说明:

  • ticks_ms()获取系统运行的毫秒级时间戳,ticks_diff()计算时间差,避免时间溢出问题(适配MicroPython环境)。
  • 循环每次都会快速检测按键状态,仅在时间间隔满足时执行I2C更新,兼顾响应速度与更新频率。
  • 最后的sleep(0.01)可降低CPU占用,10毫秒的间隔完全不会影响按键响应的感知。

方案二:使用定时器中断(进阶)

如果硬件支持定时器中断,可将I2C更新操作放到中断回调函数中,让系统自动定时执行,主循环仅专注于按键检测,效率更高。

示例代码:

from machine import Pin, Timer
from time import sleep

up_button = Pin(13, Pin.IN)

# 定义I2C更新的中断回调函数
def update_i2c_timer(timer):
    update_i2c_data()

# 创建周期为1秒的定时器
i2c_timer = Timer(-1)
i2c_timer.init(period=1000, mode=Timer.PERIODIC, callback=update_i2c_timer)

while True:
    # 实时检测按键状态
    logic_state = up_button.value()
    if logic_state == True:
        print("Button Pressed")
    
    # 微小休眠降低CPU占用
    sleep(0.01)

方案对比:

  • 方案一实现简单,无需额外硬件资源,适合大多数场景。
  • 方案二将定时任务交给硬件定时器处理,主循环更轻量化,适合复杂系统或实时性要求极高的场景。

额外优化:按键防抖

实际使用中,按键按下/释放时会有抖动,可能导致多次触发检测。可加入简单防抖处理:

from machine import Pin
from time import sleep, ticks_ms, ticks_diff

up_button = Pin(13, Pin.IN)
last_i2c_update = ticks_ms()
last_button_state = False
debounce_delay = 50  # 防抖延迟50毫秒
last_debounce_time = ticks_ms()

while True:
    current_state = up_button.value()
    current_time = ticks_ms()
    
    # 按键防抖逻辑
    if current_state != last_button_state:
        last_debounce_time = current_time
    
    if ticks_diff(current_time, last_debounce_time) >= debounce_delay:
        if current_state != last_button_state:
            last_button_state = current_state
            if last_button_state == True:
                print("Button Pressed")
    
    # I2C定时更新
    if ticks_diff(current_time, last_i2c_update) >= 1000:
        update_i2c_data()
        last_i2c_update = current_time
    
    sleep(0.01)

内容的提问来源于stack exchange,提问作者em-steven

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:17:30