ATMEGA328P外部中断avr gcc不会发生

时间:2016-02-17 10:43:48

标签: gcc interrupt avr atmega

当向int0提供5v输入时,应发生外部中断向量。 中断应改变易失性整数标志,以允许LED点亮连接到PORTB上的引脚。在Atmel工作室编译没有错误。问题是当向int0引脚发送5v电源时不会发生变化。这是中断没有触发吗?

#include <avr/io.h>
#include <stdio.h>

#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>

volatile int pwm_flag=0;



int main(void)

{

DDRD &= ~(1 << DDD2);     // Clear the PD2 pin
// PD2 (PCINT0 pin) is now an input

PORTD |= (1 << PORTD2);    // turn On the Pull-up
// PD2 is now an input with pull-up enabled

EICRA |= (1 << ISC00)|(1 << ISC10);    // set INT0 to trigger on       Rising     edge
EIMSK |= (1 << INT0);     // Turns on INT0
sei();                    // turn on interrupts
DDRB = 0xFF;
PORTB = 0x00;

while(1)
   {
    if(pwm_flag==1)//if flag is raised
       {
        PORTB = 0xFF;//turn on all pins of portb

         pwm_flag=0;//reset flag to 0
      }

   }
}

ISR (INT0_vect)
  {
  /* interrupt code here */

  pwm_flag =1;//raise flag
   }

2 个答案:

答案 0 :(得分:1)

  

问题是当5v电源发送到int0引脚时没有发生变化。

如何将5V送到INT0引脚?您的代码将INT0引脚设置为输入带上拉,所以除非您将它短接到地它处于5V

另外,你是什么意思没有发生变化? LED是打开还是关闭?

另一件事是该行:

EICRA |= (1 << ISC00)|(1 << ISC10);

将INT0和INT1设置为在相应引脚上的任何逻辑更改时发生。 名称为ISC0x控制INT0的位,名为ISC1x的位用于配置INT1。在您的代码中混合两者,最终得到以下配置:

ISC01 | ISC00 | meaning
-------------------------------------------------------------------------
    0 |     1 | any logical change on INT0 generates an interrupt request

ISC11 | ISC10 | meaning
-------------------------------------------------------------------------
    0 |     1 | any logical change on INT1 generates an interrupt request

答案 1 :(得分:0)

如果您尝试从PORTB上的引脚向LED提供5v,那么这可能就是您的问题。大多数微控制器引脚可以吸收比它们给出的电流更多的电流。也许你的LED没有得到它需要的电流?

您的接线应如下: 将LED的正极连接到5V。将负极连接到100-500欧姆的小电阻。将电阻的另一脚连接到PORTB上的引脚。

现在您可以将PORTB写入0x00以打开LED或0xFF以将其关闭。

要测试LED是否正常工作,请将PORTB写入低电平和高电平,测试主回路中的LED,并在两者之间有明显的延迟。

如果有效。然后测试你的ISR。如果ISR在这一点上不起作用,那么ISR就是问题所在。

请记住,在当前的EICRA配置中,您将在上升沿触发中断。因此,如果引脚已经为高电平,则不会发生中断。

我已经更改了下面的代码,因此LOW为ON,HIGH为OFF。

int main(void){
    DDRD &= ~(1 << DDD2); // set PD2 DDR as input
    PORTD |= (1 << PORTD2); // set PD2 as input pull-up

    EICRA |= (1 << ISC00)|(1 << ISC10); // set INT0 to trigger on rising edge
    EIMSK |= (1 << INT0); // Turns on INT0

    DDRB = 0xFF; // set PORTB as all outputs
    PORTB = 0xFF; // set PORTB high

    sei(); // turn on interrupts

    while(1){
        if(pwm_flag!=0){ // check flag
            PORTB = 0x00; // set PORTB low
            pwm_flag=0; // reset flag
    }
}

ISR (INT0_vect){
    pwm_flag = 1; // raise flag
}