简体   繁体   中英

Why does my input signal timing change when changing interrupt method?

The AVR in use is ATmega2560.

I've got an input signal that has a pulse width of 1 second that is generated.

This signal is attached to an external interrupt pin on my AVR (INT0).

INT0 is being initialized as follows:

Code:

DDRD &= ~(1 << PD0);
PORTD |= (1 << PD0);
EIMSK  = 1 << INT0; // enable
EICRA |= (1 << ISC00) | (1 << ISC01); // trigger on rising edge

sei(); //global interrupts

The mission of the ISR for this external interrupt is to a) figure out which edge (first case should be rising) and b) perform action based on which edge

The ISR looks something like this:

Code:

ISR(INT0_vect)
{

if(EICRA == 0x02)
{
    // falling edge detected
    doFallingEdgeFunction_lightLED0();

    // quickly change the trigger to capture opposite edge
    EICRA |= (1 << ISC00) | (1 << ISC01); // trigger on rising edge

}

else if(EICRA == 0x03)
{
    doRisingEdgeFunction_lightLED1();

    // change trigger on falling edge
    EICRA = (1 << ISC01);
    EICRA &= ~(1 << ISC00);
}

}

It is able to detect the edges; the correct LEDs light up, but for some reason changing the edge interrupt bit in the ISR decreases my input signal to 0.1 second width instead of the full 1 second width.

On the scope, I see the original signal being mirrored but with 10x less width! If I remove the "switching trigger" items, the signal is fine.

From section 15.2.2, p. 114

Note: 1. n = 3, 2, 1or 0. When changing the ISCn1/ISCn0 bits, the interrupt must be disabled by clearing its Interrupt Enable bit in the EIMSK Register. Otherwise an interrupt can occur when the bits are changed.

EDIT:

EIFR – External Interrupt Flag Register

• Bits 7:0 – INTF7:0: External Interrupt Flags 7 - 0

When an edge or logic change on the INT7:0 pin triggers an interrupt request, INTF7:0 becomes set (one). If the I-bit in SREG and the corresponding interrupt enable bit, INT7:0 in EIMSK, are set (one), the MCU will jump to the interrupt vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing a logical one to it.

Try clearing the flag in the interrupt

EIFR = (1 << INT0); 

Don't use

EIFR |= (1<< INT0);  // DO NOT USE

That will clear all pending flags.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM