【问题标题】:ATMEGA328P external interrupt avr gcc won't happenATMEGA328P 外部中断 avr gcc 不会发生
【发布时间】:2016-02-17 10:43:47
【问题描述】:

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

#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
   }

【问题讨论】:

    标签: gcc interrupt avr atmega


    【解决方案1】:

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

    如何向 INT0 引脚发送 5V 电压?您的代码将 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
    

    【讨论】:

      【解决方案2】:

      如果您尝试从 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
      }
      

      【讨论】:

      • AVR 可以为 LED 提供和吸收充足的电流。
      • 对于一个小的是的,但我仍然认为吸收电流而不是提供电流是更好的做法。
      • 这是个人喜好还是一般建议? -- 尽管如此,AVR 的数据表中说“端口 B 输出缓冲器具有对称的驱动特性,具有很高的灌电流和拉电流能力。”所以在这方面没有什么可做的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 2019-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      相关资源
      最近更新 更多