-1

我不知道按下开关时如何消除小振荡的影响。我有一个原始开关和一个 LED,我试图创建一个中断,使 LED 在按下开关时闪烁。我这样做的方式是在输入信号的下降沿触发中断。


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

ISR(INT0_vect){
    PORTD ^= 1;
}

int main(void)
{
    DDRD = 1;//we set for input D port
    PORTD |= 1<<2;//pull-up for interrupt pin
    EICRA &= ~3;//clear EICRA and activate INT0 on LOW
    EICRA |= 2;//activate INT0 on falling edge
    SREG |= 1<<7;//I bit from SREG has to be enabled
    EIMSK |= 1;//enable INT0
    while (1) 
    {
        EIFR |= 1;//I've tried to clear the corresponding flag, but in vain
    }
}

4

2 回答 2

-1

为了正确地去抖动,你必须以某种方式测量时间,你可以做两件事:

  1. 确保某个东西是稳定的(这实际上并不是去抖动)。例如,如果您的按钮有很长的电线,您可能会担心可能会污染信号的噪音。所以您读取一次信号,然后稍后再读取一次,以检查信号是否仍然存在并且它不是噪音。完美的方法是在一段时间内监视信号,并且只有在该信号在该时间段内没有变化的情况下,才将其视为有效。

  2. 适当的去抖动。当信号从非活动状态变为活动状态时,您必须忽略信号的短路下降 (active-inactive-active)。

你的按钮在按下时会给你一个低电平,你可以忽略噪音。因此,一旦信号变低,您就知道按钮已被按下。这是中断的完美场景。但是,如果按钮弹起,它会非常快速地降低和升高信号 - 对于人类来说太快了,但对于 MCU 来说不会太快。您需要做的是暂时忽略进一步的“压力”,例如 1 毫秒,或 5,或 1/100 秒左右。然后,您必须计算时间(大概是另一个中断)。

假设您有一个每毫秒触发一次的中断例程。在该例程中,递减一个计数器(如果它 > 0)。当按下按钮并且计数器为零时,接受按钮按下并将计数器设置为一个值。按钮的进一步压力将被忽略,直到计数器将“缓慢”衰减到零,这要归功于另一个测量时间的例程(在中断中)。

这只是一个想法,有很多方法可以做到相同甚至更好(降噪)。

在你的情况下,你也可以在你已经拥有的中断例程中(不漂亮)只 sleep() (或做一个延迟循环),或者在给定的时间内禁用该中断(所以你必须测量时间)。

于 2021-04-02T13:52:53.450 回答
-1

更正后的代码是:

#define F_CPU 16000000UL

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

ISR(INT0_vect){
    PORTD ^= 1;
    _delay_ms(10);
    EIFR |= 1;
}

int main(void)
{
    DDRD = 1;//we set for input D port
    PORTD |= 1<<2;//pull-up for interrupt pin
    EICRA &= ~3;//clear EICRA and activate INT0 on LOW
    EICRA |= 1;//activate INT0 on change
    SREG |= 1<<7;//I bit from SREG has to be enabled
    EIMSK |= 1;//enable INT0
    while (1) 
    {
        
    }
}

我提到它在尝试在电路的上升沿或下降沿触发时仍然存在问题。尝试这样做时,我注意到电路的行为就像被任何类型的边缘触发一样。

于 2021-04-02T18:30:08.657 回答