如何让printf()仅在按键上升沿触发执行?基于mbed OS与Nucleo G071RB
问题分析与解决方案
首先明确上拉按键的电平逻辑:
- 按键未按下:
buttons[i]返回 1(内部上拉,默认高电平) - 按键按下:
buttons[i]返回 0(按键接地,拉低电平)
你的代码存在三个核心问题:
- 初始状态不匹配:
lastButtons初始化为{0,0},但按键默认是未按下状态(对应buttons[i]=1),初始状态不一致导致第一次按键判断逻辑混乱。 - 缺少按键消抖:机械按键按下/释放时会有几毫秒的电平抖动,频繁触发检测函数会导致误判,出现连续发送或触发多次的情况。
- 状态更新逻辑不完整:当前代码只在触发条件满足时更新
lastButtons,未处理按键释放后的状态同步,导致后续判断失效。
修正后的代码
#include "mbed.h" DigitalIn buttons[2]{{D6,PullUp},{D7,PullUp}}; bool lastButtons[2]{1,1}; // 初始化为按键未按下的状态(对应buttons[i]=1) Timeout debounceTimer; bool debounceEnabled = false; // 消抖回调:延迟后再检测按键状态,避免抖动干扰 void checkButtonState() { for(int i=0;i<2;i++) { // 检测按键从"未按下(1)"变为"按下(0)"的瞬间 if(!buttons[i] && lastButtons[i]) { printf("%c", '0' + i); // 原代码输出ASCII控制字符,改为输出数字字符更易调试 lastButtons[i] = buttons[i]; // 同步当前状态 } // 同步按键释放后的状态 else if(buttons[i] && !lastButtons[i]) { lastButtons[i] = buttons[i]; } } debounceEnabled = false; } void buttonFn() { // 消抖:如果正在消抖中,忽略本次触发 if(debounceEnabled) return; debounceEnabled = true; // 10ms消抖延迟,可根据按键特性调整 debounceTimer.attach(callback(&checkButtonState), 10ms); }
关键调整说明
- 初始状态修正:
lastButtons初始值改为{1,1},与按键未按下时的buttons[i]=1匹配,保证第一次判断逻辑正确。 - 添加消抖机制:用
Timeout实现10ms延迟检测,跳过按键抖动的不稳定阶段,彻底避免误触发。 - 完善状态同步:不仅在按下时更新
lastButtons,释放时也同步状态,确保每次状态变化都被正确记录。 - 输出修正:原代码
printf("%c",i)会输出ASCII码为0、1的控制字符,改成'0'+i会输出数字字符'0'、'1',更符合实际调试需求。
注意:需确保buttonFn是通过外部中断触发调用的(比如用InterruptIn绑定按键的下降沿),如果是主循环轮询调用,也要保证轮询间隔配合消抖时间,避免频繁检测。
内容的提问来源于stack exchange,提问作者Giles.Spreadborough
相关产品推荐
相关产品推荐

