【问题标题】:AVR Timer and Hardware interruptsAVR 定时器和硬件中断
【发布时间】:2021-10-22 18:00:02
【问题描述】:

我尝试在第一次检测到硬件中断检测下降沿时激活定时器,并在运行 8 次后停用定时器。但是当我停止定时器时,硬件中断再次触发并立即启动定时器。

在图像中,您可以忽略蓝色信号。紫色信号是定时器 1 切换引脚。绿色是切换引脚的硬件中断。

它所要做的就是在第一个下降沿触发,然后在一段时间内切换一个引脚。

我的问题是:为什么硬件中断会触发两次?

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

volatile int cnt = 0;
uint8_t data[8];

int main(void)
{
    // TIMER 1
    DDRB |= (1 << PORTB0);      // Set LED as output
    DDRB |= (1 << PORTB1);      // Set LED as output
    DDRB |= (1 << PORTB2);      // Set LED as output
    DDRD &= ~(1 << PORTD2);     // Set LED as INPUT
    PORTD |= (1 << PORTD2);     // PULLUP resistor
    
    TCCR1B |= (1 << WGM12);     // Configure timer 1 for CTC mode
    TIMSK1 &= ~(1 << OCIE1A);   // Disable CTC interrupt
    //TIMSK1 |= (1 << OCIE1A);  // Enable CTC interrupt
    OCR1A   = 1200;             // Set CTC compare value to 15873Hz at 16MHz AVR clock, with a prescaler of 1
    //TCNT0 = 0;
    TCCR1B |= ((1 << CS10));        // Start timer at Fcpu/1
    
    // Interrupt
    EICRA |= (1 << ISC01) | (1 << ISC11);       //ENABLE INT0 and INT1 ON falling EDGE
    EIMSK |= (1 << INT0);       //ENABLE INT0
    EIMSK |= (1 << INT1);       //ENABLE INT0
    sei();                      //  Enable global interrupts

    while (1)
    {
    }
}

ISR(TIMER1_COMPA_vect)
{
    cnt = cnt + 1;
    PORTB ^= (1 << PORTB0);                 // D8       

    if (cnt > 7)
    {
        TIMSK1 &= ~(1 << OCIE1A);               // stop CTC interrupt
        EIMSK |= (1 << INT0);                   //Enable INT0
        EIMSK |= (1 << INT1);                   //Enable INT0
        return;
    }
}

ISR(INT0_vect)                  //External interrupt_zero ISR
{
    EIMSK &= ~(1 << INT0);      //Disable INT0
    PORTB ^= (1 << PORTB2);     // Toggle the LED
    TCNT1 = 0;
    cnt = 0;
    TIMSK1 |= (1 << OCIE1A);    // Enable CTC interrupt
}

ISR(INT1_vect)                  //External interrupt_zero ISR
{
    PORTB ^= (1 << PORTB2);     // Toggle the LED
    EIMSK &= ~(1 << INT1);      //Disable INT0
    TCNT1 = 0;
    cnt = 0;
    TIMSK1 |= (1 << OCIE1A);    // Enable CTC interrupt
}

【问题讨论】:

标签: c interrupt avr atmel


【解决方案1】:

即使您禁用它,下降沿也会设置中断标志。这称为“未决”中断。一旦启用中断,就会调用其服务例程(假设满足所有其他启用条件)。

您需要在启用中断之前清除此挂起标志。

【讨论】:

  • 谢谢,你知道你需要清除哪个注册表吗?
  • 查看它的数据表,在 ATmega128 上它是EIFR,但你没有提到具体的 AVR。
  • 成功了,非常感谢!我用的是atmega328。对于那些会遇到这个问题的人,我使用了这行代码:EIFR |= (1
猜你喜欢
  • 1970-01-01
  • 2017-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-07
  • 1970-01-01
相关资源
最近更新 更多