Arduino RichShield计算器修改长按按键连续跳状态问题咨询
Arduino RichShield计算器按键误触发修复方案
问题根源
现有代码采用电平触发逻辑判断按键输入,长按按键时IO口电平持续为LOW,状态切换后的固定延时结束后,下一轮loop循环会再次检测到低电平,触发连续状态跳转。
修复思路
改用下降沿触发+软件消抖逻辑:
- 仅检测按键从松开(HIGH)到按下(LOW)的跳变瞬间才触发状态切换
- 加入50ms消抖时长过滤按键机械抖动导致的异常电平跳变
- 用非阻塞的millis()计时替代原代码中分散的阻塞延时,避免影响按键检测灵敏度
修改后完整代码
#include "Display.h" // 按键和LED引脚定义 const int PIN_BUTTON = 9; const int PIN_LEDR = 4; const int PIN_LEDG = 5; const int PIN_LEDB = 6; const int PIN_LEDY = 7; // 新增按键消抖相关变量 int lastButtonState = HIGH; unsigned long lastDebounceTime = 0; const unsigned long debounceDelay = 50; // 可根据实际按键手感调整消抖时长 // 电位计相关变量 const int PIN_POTMETER = 14; int MAX_NUM = 20; int MIN_NUM = -20; int potValue = 0; int potValueForCalculations = 0; // 运算相关变量 int buttonCounter = 0; float inputValue1; float inputValue2; float result; char mathOperator; void setup() { pinMode(PIN_LEDR, OUTPUT); pinMode(PIN_LEDG, OUTPUT); pinMode(PIN_LEDB, OUTPUT); pinMode(PIN_LEDY, OUTPUT); pinMode(PIN_POTMETER, INPUT); pinMode(PIN_BUTTON, INPUT_PULLUP); Display.show("----"); delay(3000); } void loop() { // 按键消抖&有效按下检测逻辑 int currentButtonState = digitalRead(PIN_BUTTON); bool buttonPressed = false; if (currentButtonState != lastButtonState) { lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // 仅检测从松开到按下的下降沿,触发一次有效按下 if (currentButtonState == LOW && lastButtonState == HIGH) { buttonPressed = true; } } lastButtonState = currentButtonState; // 状态1:选择第一个操作数 if (buttonCounter == 0) { potValue = analogRead(PIN_POTMETER); potValueForCalculations = map(potValue, 0, 1023, MIN_NUM, MAX_NUM); Display.show(potValueForCalculations); delay(100); if (buttonPressed) { inputValue1 = potValueForCalculations; buttonCounter = 1; } } // 状态2:选择运算符 else if (buttonCounter == 1) { potValue = analogRead(PIN_POTMETER); if (potValue <= 256) { Display.show("a"); mathOperator = 'a'; } else if (potValue > 256 && potValue <= 512) { Display.show("s"); mathOperator = 's'; } else if (potValue > 512 && potValue <= 768) { Display.show("t"); mathOperator = 't'; } else { Display.show("d"); mathOperator = 'd'; } if (buttonPressed) { buttonCounter = 2; } } // 状态3:选择第二个操作数 else if (buttonCounter == 2) { potValue = analogRead(PIN_POTMETER); potValueForCalculations = map(potValue, 0, 1023, MIN_NUM, MAX_NUM); Display.show(potValueForCalculations); delay(100); if (buttonPressed) { inputValue2 = potValueForCalculations; buttonCounter = 3; } } // 状态4:展示运算结果 else if (buttonCounter == 3) { digitalWrite(PIN_LEDG, HIGH); digitalWrite(PIN_LEDR, LOW); if (mathOperator == 'a') { result = inputValue1 + inputValue2; Display.show(result); } else if (mathOperator == 's') { result = inputValue1 - inputValue2; Display.show(result); } else if (mathOperator == 't') { result = inputValue1 * inputValue2; Display.show(result); } else if (mathOperator == 'd') { if (inputValue2 == 0) { digitalWrite(PIN_LEDR, HIGH); digitalWrite(PIN_LEDG, LOW); Display.show("Err"); } else { result = inputValue1 / inputValue2; Display.show(result); } } if (buttonPressed) { buttonCounter = 4; } } // 重置状态 else if (buttonCounter >= 4) { digitalWrite(PIN_LEDR, LOW); digitalWrite(PIN_LEDG, LOW); digitalWrite(PIN_LEDB, LOW); digitalWrite(PIN_LEDY, LOW); Display.show(""); buttonCounter = 0; } }
效果说明
修改后仅短按按键会触发状态切换,长按、按键抖动都不会触发异常跳转,操作响应流畅度也会比原来加阻塞延时的方案更好。
内容的提问来源于stack exchange,提问作者daniil
相关产品推荐
相关产品推荐

