我的中断并没有更新我的价值,我应该如何设置中断?

问题描述

我正在尝试构建一个程序,该程序的扫描灯至少带有5个led,一个按钮连接到外部中断引脚。按下一个按钮(然后松开)以启动扫描仪灯。按下(然后松开)再次停止扫描灯(依此类推...)。

  • 我在PD2上有一个接地侧开关
  • 我在PD3,PD4,PD5,PD6和PD7上有我的LED。
  • 我正在使用ATMega328P

我知道当我按下按钮时,高耸的灯就会起作用,但是当我再次按下时,感觉它并没有将值恢复为1。

我的代码

#ifndef F_cpu                   
#define F_cpu 1000000UL         
#endif

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

#define BIT_IS_CLEAR(byte,bit) (!(byte & (1 << bit)))

volatile int value = 1;
int main(void)
{
    DDRD = 0b111110000;
    DDRD &= ~(1 << PD2);        // clear DDRD bit 2,sets PD2 (pin 4) for input
    PORTD |= (1 << PD2);        // set PD2/INT0 (pin 4) internal pull-up resistor
    
    
    PCICR = 0b00000100;
    PCMSK2 = 0b00000100;
    sei();
    
    while (value==1) //when value is 1 it should start having a towerlight
    {
        PORTD= 0x80;
        _delay_ms(15000);
        PORTD= 0x40;
        _delay_ms(15000);
        PORTD= 0x20;
        _delay_ms(15000);
        PORTD= 0x10;
        _delay_ms(15000);
        PORTD= 0x08;
        _delay_ms(15000);
        
    }

}


ISR(PCINT2_vect)
{

    if(BIT_IS_CLEAR(PIND,PD2) & value==1) {            // if switch is pressed (logic low)
        value=0;
        } else if(value == 0) { 
        value=1;
        } else {
        // ideally should never get here,but may occasionally due to timing
    }
}```

解决方法

您正在使用按位与,此处应为逻辑与。更改

if(BIT_IS_CLEAR(PIND,PD2) & value==1)

对此

if(BIT_IS_CLEAR(PIND,PD2) && (0 != value))

比较非零(等于1)可防止value损坏;因为您想要零或非零条件。添加括号使意图非常明确。 Yoda比较(将常数放在左侧)可以防止意外分配。

要考虑的另一件事是您要对开关进行去抖动的操作-以模拟方式使用R-C + Schmitt或单稳态,或者以数字方式使用计时器程序,该程序经常对输入进行采样并计算“在最后一个样本(例如16个样本)中有1个或0个”?

我发现边沿触发的中断对于手动开关输入不是特别有效。

,

关于:

while (value==1)
{
    ....
}

value为0时,退出循环,然后执行退出程序。这是程序中的严重逻辑缺陷