【问题标题】:c arduino button interrupts (isr), make multiple leds go on and offc arduino 按钮中断(isr),使多个 LED 点亮和熄灭
【发布时间】:2020-08-13 08:54:47
【问题描述】:

我一直在尝试通过按下相应的按钮来让我的 Arduino 上的 LED 亮起和熄灭。

我正在使用中断来实现它,并且按钮按下确实被注册,但由于某种原因它不会改变全局变量的值(int button_pressed1,...);

应该发生的是,当我按下按钮 1 时,Led 1 应该会亮起和熄灭,与按钮 2 和按钮 3 相同。

非常感谢您看一看,中断对我来说很新,所以它可能是一个小的疏忽。

*我省略了按钮 2 和 3 的代码。如果我可以让按钮 1 上的 LED 亮起,我就能让其他按钮亮起。

#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart.h"

#define LED_DDR DDRB
#define LED_PORT PORTB

#define BUTTON_DDR DDRC
#define BUTTON_PORT PORTC
#define BUTTON_PIN PINC

int button_pressed1 = 0; //globale variabele to turn on functions

ISR(PCINT1_vect)
{
    if (bit_is_clear(BUTTON_PIN, PC1))
    {                
        _delay_us(500); //debounce
        if (bit_is_clear(BUTTON_PIN, PC1))
        {

            button_pressed1 = 1;
            printf("button 1 pressed\n");
        }
    }
}

int main()
{
    LED_DDR |= _BV(PB2) | _BV(PB3) | _BV(PB4); //registrer pins  output(bit = 1)
    LED_PORT |= _BV(PB2) | _BV(PB3) | _BV(PB4);

    BUTTON_DDR &= ~_BV(PC1) & ~_BV(PC2) & ~_BV(PC3); //registrer inputs(bit = 0)
    BUTTON_PORT |= _BV(PC1) | _BV(PC2) | _BV(PC3);   // pull up ( bit =1 )

    PCICR |= _BV(PCIE1);                      //type pins doorgeven
    PCMSK1 |= _BV(PC1) | _BV(PC2) | _BV(PC3); //pin/button doorgeven aan change mask

    initUSART(); 

    sei();

    while (1)
    { //infinte loop
        if (button_pressed1 == 1)
        {
            LED_PORT &= ~_BV(PB2); //turn led on
            _delay_ms(500);
            LED_PORT |= _BV(PB2); //turn led off
            _delay_ms(500);
        }
    }

    return 0;
}

【问题讨论】:

  • 像这样声明你的变量:volatile int button_pressed1 = 0;
  • 哦,是的,我读到 arduino 确实需要 volatiles,但不确定它是如何与之交互的,但代码现在可以工作了!非常感谢,真的很感激!
  • interrupts are pretty new to me 。中断并不意味着处理按钮按下,并使该任务比必要的更复杂。 _delay_us(500); //debounce 在 ISR 中非常糟糕
  • @datafiddler 可能是这样,我一定会记住这一点,但这是一个学校项目。我不能偏离他们的做法

标签: c arduino interrupt atmega led


【解决方案1】:

几个基本问​​题:

  • 与 ISR 共享的所有变量都应声明为 volatile 并具有针对竞争条件的保护。详情请见this
  • ISR 中不应存在忙延迟。相反,您应该设置定时器中断以在特定时间段内再次触发。通常,很难将 GPIO 中断专门用于按钮,最好从循环定时器中断轮询。您可以使用中断,但它相当复杂,详情here
  • 500us 可能不足以进行去抖动。机械信号反弹相对较慢。等待约 10 毫秒左右更为常见。您可以很容易地用示波器测量反弹特性,方法是向按钮添加电源,然后按下它并捕获边缘。它看起来像一个正弦曲线,您可以轻松测量它的持续时间。
  • 主循环中的 500 毫秒延迟将被用户体验为“滞后”。他们可能会开始怀疑按钮坏了。您可能希望至少跳过关闭延迟。

【讨论】:

  • 你是救命稻草,我正在学习我大学的课程,现在我们仍在使用延迟而不是计时器。可能是我们稍后会学到的东西仍然非常感谢您的提示,您是一流的!
猜你喜欢
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
相关资源
最近更新 更多