这里为什么使用双边沿触发中断而不直接用上升沿触发中断?既然使用双边沿触发中断,为什么没有出现按下按键后灯亮,此时松开按键后灯灭的情景?

该问题来自社区帖: https://bbs.csdn.net/topics/615579614.为符合问答规范, 该问题经过ChatGPT优化
为何使用双边沿触发中断而非上升沿触发中断?为什么按下按键后灯未亮,并在松开按键后熄灭?请参考以下代码和电路图:

此代码中选用双边沿触发中断,因为按键的机械特性会导致电平从高到低、低到高来回切换,双边沿触发中断可以将所有触发边缘有效地捕获。同时,在按下按键时,电平需要切换两次才能达到有效触发中断的状态,因此使用上升沿触发中断无法满足要求。

而按下按键后灯未亮,是因为按键的电路结构修改了芯片上拉(或下拉)电阻的电平,导致电平状态被改变。因此需要在代码中添加相应的判断语句,对电平状态的变化进行识别并执行相应的操作。下面是完整的优化代码:

```html

// 电路图见上图 const int buttonPin = 2; // 按键连接到引脚2 const int ledPin = 13; // LED连接到引脚13 int buttonState = 0; // 初始化按键状态为0 void setup() { pinMode(ledPin, OUTPUT); // 初始化LED为输出 pinMode(buttonPin, INPUT_PULLUP); // 初始化按键为输入上拉 attachInterrupt(buttonPin, buttonInterrupt, CHANGE); // 绑定中断函数 } void loop() { } void buttonInterrupt() { // 按键触发中断函数 buttonState = digitalRead(buttonPin); // 读取按键状态 if (buttonState == LOW) { // 判断按键状态是否低电平 digitalWrite(ledPin, HIGH); // 点亮LED } else { // 按键状态非低电平,即松开按键,熄灭LED digitalWrite(ledPin, LOW); } }

```


```c
// 电路图见上图   
const int buttonPin = 2; // 按键连接到引脚2   
const int ledPin = 13; // LED连接到引脚13   
int buttonState = 0; // 初始化按键状态为0   
  
void setup() {   
  pinMode(ledPin, OUTPUT); // 初始化LED为输出   
  pinMode(buttonPin, INPUT_PULLUP); // 初始化按键为输入上拉   
  attachInterrupt(buttonPin, buttonInterrupt, CHANGE); // 绑定中断函数 }   
  
void loop() { }   
  
void buttonInterrupt() { // 按键触发中断函数   
  buttonState = digitalRead(buttonPin); // 读取按键状态   
  if (buttonState == LOW) { // 判断按键状态是否低电平   
    digitalWrite(ledPin, HIGH); // 点亮LED   
  } else { // 按键状态非低电平,即松开按键,熄灭LED   
    digitalWrite(ledPin, LOW);   
  }   
}

```

  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/392412
  • 除此之外, 这篇博客: 启航篇——四旋翼飞行器之入坑两年心路历程和毕设总结中的     这个阶段姑且称它为入门阶段吧,在这个时候最感谢的应该就是梁工了,在做第一代飞控的时候帮助我们很多,是将我们带进四旋翼这个新领域的领路人。在他的帮助下,我们知道怎么自己组一台四旋翼,从自己做机架开始,自己画板、自己焊板、自己调试、自己编程、自己手飞测试,在他的帮助下我们真的少走了很多弯路。在这个过程中,我们学会了工程化的代码是怎么写的,知道了怎么用定时器时分复用,四旋翼飞行器代码整个框架是怎么做的,PID参数调试大概要怎么调,如何用示波器和串口调试。在调试中也遇到很多问题,也解决了很多问题。虽然,对于四旋翼核心的算法部分我们还是半知半解,但是在这个比赛中,我们收获很多,结果不重要,过程才是最重要的。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  •  

  • 以下回答由chatgpt基于相关博客总结生成:

    我可以回答这个问题。

    对于双边沿触发中断和上升沿触发中断的问题,一般来说,常用的触发方式是上升沿触发中断,因为大部分普通开关都能满足。但是对于一些机械特性不太好的按键开关,比如有些按键的接点会在按下瞬间反弹一次,或者因为机械结构不好等原因,在按下和放开的瞬间都会有电平变化,这样仅仅采用上升沿触发中断会出现误触发的情况,为了解决这个问题,我们可以采用双边沿触发中断来处理按键输入。对于双边沿触发中断来说,整个按键动作产生的电平变化都可以被捕获,避免了上升沿触发中断出现的误触发问题。

    关于按下按键后,某些电路会保持状态,而其他电路则会在松开按键后立即恢复状态的问题,一般是由于电路中加入了RC电路导致的。对于加入RC电路的电路,在按下按键的时候,RC电路会缓慢充电,当充电时间足够长之后,电路中的信号才能够稳定下来,所以在这种情况下,电路中的元器件会保持在原来的状态下。而当按键放开之后,RC电路会缓慢放电,导致电路状态恢复到初始状态,所以在这种情况下,电路中的元器件会在放开按键之后立即恢复状态。

    以下是一个参考代码和电路图示例来解决这个问题。(使用Arduino编写)

    #define BUTTON_PIN 2 // 定义按键连接的引脚
    #define LED_PIN 13 // 定义灯连接的引脚
    #define DEBOUNCE_DELAY 50 // 消除抖动的延时时间
    
    int buttonState = HIGH; // 按键的初始状态为高电平
    int lastButtonState = HIGH; // 上一个按键状态,用于消除抖动
    unsigned long lastDebounceTime = 0; // 上次消除抖动的时间
    
    void setup() {
      pinMode(BUTTON_PIN, INPUT_PULLUP); // 输入模式,使用内部上拉电阻
      pinMode(LED_PIN, OUTPUT); // 输出模式
    }
    
    void loop() {
      int reading = digitalRead(BUTTON_PIN); // 读取按键状态
      if (reading != lastButtonState) { // 当按键状态改变时需要消除抖动
        lastDebounceTime = millis(); // 记录当前时间
      }
      if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) { // 延时结束
        if (reading != buttonState) {
          buttonState = reading; // 当按键状态改变时更新状态
          if (buttonState == LOW) { // 当按键按下时
            digitalWrite(LED_PIN, HIGH); // 点亮LED
          } else { // 当按键放开时
            digitalWrite(LED_PIN, LOW); // 关闭LED
          }
        }
      }
      lastButtonState = reading; // 更新上一个按键状态值
    }
    

    以上代码中使用了按键消除抖动的方法来解决按键状态切换不稳定的问题,可以快速稳定地读取按键状态。

    以下是一个使用RC电路的电路图示例。(多用于模拟量信号输入)

    RC电路的电路图示例

    此电路中,当按键按下后,C1电容通过R1电阻慢慢充电,因此在按下按键后,LED灯不会立即亮起,而是需要等到C1电容充电时间足够长之后才会稳定亮起。当按键放开后,C1电容通过R1电阻缓慢放电,因此LED灯也不会立即灭掉,而是需要等到C1电容放电时间足够长之后才会稳定熄灭。