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

