本帖最后由 z01228 于 2020-3-22 09:20 编辑
我们在平时项目交互制作时离不开轻触按键.编码器这样的硬件。避免不了的问题就是按键抖动。具体的原因大家通过上图可以看出理想波形与实际波形之间是有区别的,实际波形在按下和释放的瞬间都有抖动的现象,抖动时间的长短和按键的机械特性有关,一般为5~10ms。通常我们手动按键然后释放,这个动作中稳定闭合的时间超过了20ms。因此单片机在检测键盘是否按下时都要加上去抖动操作,有专用的去抖动电路,也有专门的去抖动芯片,但通常我们采用软件延时的方法就可以解决抖动问题。
方法一:检测到按键,先判断1次,再进行延迟, 再判断[mw_shl_code=arduino,true]if (digitalRead(kg)==LOW) // 如果有键按下(按键kg的模式是输入上拉模式)
{
delay(5); // 延时一段时间消抖
if (digitalRead(kg)==LOW) // 如果真的有键按下检测到的是稳定闭合状态
{
......; // 按键实现的功能
}
while (digitalRead(kg)==LOW); // 俗称“死等”, 松手检测,如果按住不放则一
// 直在while()循环里
}
[/mw_shl_code]
方法二:利用时间函数,以按键动作持续时间进行判断
[mw_shl_code=arduino,true]// 定义按键输入针脚号常量,
// 并初始化为2号针脚。
const int buttonPin = 2;
// 定义LED输入针脚号常量,
// 并初始化为13号针脚。
// 注:此处我们使用的LED神灯是Arduino UNO电路板自带,
// 此神灯对应的针脚号默认为13,此数值不得随意更改,
// 所以这里定义的数值13是为了和默认值相对应。
const int ledPin = 13;
// 定义记录LED神灯当前状态的变量,
// 并初始化状态为HIGH。
int ledState = HIGH;
// 定义记录按键当前状态的变量
int buttonState;
// 定义记录按键最近一次状态变化的变量,
// 并初始化状态为LOW。
int lastButtonState = LOW;
// 定义记录最近一次抖动的时间变量,
// 并初始化时间为0毫秒。
long lastDebounceTime = 0;
// 定义延迟抖动的时间变量,
// 并初始化为50毫秒。
long debounceDelay = 50;
// 对Arduino电路板或相关状态进行初始化方法
void setup() {
// 设置按键的针脚为输入状态
pinMode(buttonPin, INPUT);
// 设置电路板上LED神灯的针脚状态为输出状态
pinMode(ledPin, OUTPUT);
// 设置电路板上LED神灯的初始状态,
// 此处因为变量ledState的初始状态为HIGH,
// 所以LED神灯的初始状态为亮。
digitalWrite(ledPin, ledState);
}
// 系统调用,无限循环方法
void loop() {
// 读取按键的状态
int reading = digitalRead(buttonPin);
// 判断当前的按键状态是否和之前有所变化
if (reading != lastButtonState) {
// 如果按键发生了变化,
// 则重新设置最近一次抖动的时间。
lastDebounceTime = millis();
}
// 判断按键按下或抬起的状态时间间隔是否大于延迟抖动的时间长度。
// 方法millis()可以获取当前时间,单位统一为毫秒。
if ((millis() - lastDebounceTime) > debounceDelay) {
// 判断当前的按键状态是否和之前有所变化
if (reading != buttonState) {
// 如果发生了变化,
// 则更新按键状态变量。
buttonState = reading;
// 判断按键的状态是否为按下,
// 只有在按键按下的时候,
// 才改变LED神灯的状态。
if (buttonState == HIGH) {
// 如果LED神灯当前为亮度,
// 则变为灭。如果为灭,
// 则变为亮。
ledState = !ledState;
}
}
}
// 最终改变电路板上LED神灯的状态
digitalWrite(ledPin, ledState);
// 更新按键最近一次状态变化的变量
lastButtonState = reading;
}
[/mw_shl_code]
方法3:加进按键松开判断[mw_shl_code=arduino,true] if(digitalRead(3)==LOW){
delay(10);
if(digitalRead(3)==LOW){
while(digitalRead(3)==LOW)//死循环判断按键松开
//需要执行的函数
}
}[/mw_shl_code]
方法4:使用状态机进行按键判断(低电平触发)
[mw_shl_code=arduino,true]
int var =1; //状态机标志
int anj =2; //引脚编号
void setup() {
pinMode(2,INPUT_PULLUP);//输入上拉
}
void loop() {
switch (var) {
case 1:
if (digitalRead(anj)==LOW){var=2;}
break;
case 2:
if (digitalRead(anj)==LOW){
//需要执行的函数
var=3;
}
break;
case 3:
if (digitalRead(anj)==HIGH){var=1;}
break;
default:
var=1;
break;
delay(10);
}
}[/mw_shl_code]
|