EmbDev.net

Forum: µC & Digital Electronics AVR - ATmega8A - External Interrupt - Sometimes odd behaviour


Author: Alex Kapphahn (Company: ---) (akap)
Posted on:

Rate this post
0 useful
not useful
Hi,

I am currently working on a MCU unit which will respond to external 
interrupts in order to perform specific tasks. The controller I am 
using: ATmega8A.

The external interrupt is defined as followed:
PORTD |= 0x04;                //Activate pull up resistor of PD2 
GICR |= (1 << INT0);          //Enable INT0 
MCUCR |= (1<<ISC00);          //INT0 is executed on every edge 

The ISR:
ISR (INT0_vect) 
{ 
                /* interrupt code here */ 
 
                v = 1;          //sets interrupt variable v to 1 
} 

The variable v is defined as : volatile int v.
 volatile int v = 0; 

I am currently testing the behavior of the external interrupts. Whenever 
an external interrupt is detected a particular code block should be 
executed. The interrupt is applied to the INT0 by any logic change.
 ISR (INT0_vect) 
 { 
     /* interrupt code here */ 
 
     v = 1;               //sets interrupt variable v to 1  
 } 
 
 
 int main(void) 
 { 
    USART_Init(); 
    I2C_init(); 
 
    //int a;                      //test variable 
 
    PORTD |= 0x04;                //Activate pull up resistor of PD2 
    GICR |= (1 << INT0);          //Enable INT0 
    MCUCR |= (1<<ISC00);          //INT0 is executed on every edge 
 
    sei(); 
 
    unsigned char a; 
    a = USART_Receive(); 
 
 while(1) 
    { 
        //TODO:: Please write your application code 
 
        do 
        { 
 
        } while (v == 0);     //Wait for interrupt 
 
        v = 0; 
 
        _delay_ms(10000); 
 
  //Communication protocol between MCU unit and GUI software application 
 
            //Block 1 
 
            USART_Transmit(0xFF);                           //Header start command 
            USART_Transmit(0x00); 
            USART_Transmit(0x08); 
            USART_Transmit(0x00); 
            USART_Transmit(0x09); 
 
 
            USART_Transmit(0x02); 
 
 
            USART_Transmit(0x04); 
 
            USART_Transmit(0x05); 
            USART_Transmit(0x06); 
            USART_Transmit(0x00); 
 
            USART_Transmit(0xFE);                           //Header finish command 
 
            do 
            { 
            } while (v == 0);          //Wait for interrupt 
 
            v = 0; 
 
        _delay_ms(10000); 
 
 //Block 2 
 
            USART_Transmit(0xFF);                           //Header start command 
            USART_Transmit(0x00); 
            USART_Transmit(0x01); 
            USART_Transmit(0x00); 
            USART_Transmit(0x01); 
 
 
            USART_Transmit(0x01); 
 
 
            USART_Transmit(0x01); 
 
            USART_Transmit(0x01); 
            USART_Transmit(0x01); 
            USART_Transmit(0x01); 
 
            USART_Transmit(0xFE);                           //Header finish command 
 
 
          } 
 
     return 0; 
 } 
 
[c]

Testing the code, I can say that the interrupts are recognized and the 
code is functioning. However, it seems that there is a little bug or 
logic error. When the first interrupt occurs (before block 1), block 1 
is supposed to be executed. Now, if the second interrupt occurs, the 2nd 
block should be executed.

I can see this execution sequence in a pre-written GUI application, 
however, most of the time block 1 (when applying the interrupt) is 
executed many times after another and than block 2.

It should always be the following sequence: block 1 than block 2 and so 
on. I think that this is a timing issue. But I cannot debug this 
problem.

I am also wondering if there is a code in C that tells the program to 
wait for an external interrupt signal and than continues the program?

Thank you very much in advance.

Author: Marc Vesely (Guest)
Posted on:

Rate this post
0 useful
not useful
Alex Kapphahn wrote:
> It should always be the following sequence: block 1 than block 2 and so
> on. I think that this is a timing issue. But I cannot debug this
> problem.

Is this now your complete code ( Except diverse #include etc.) ?
 
ISR (INT0_vect) 
{ 
                v = 1;          //sets interrupt variable v to 1 
} 

 volatile int v = 0; 

 int main(void) 
 { 
    USART_Init(); 
    I2C_init(); 
    PORTD |= 0x04;                //Activate pull up resistor of PD2 
    GICR |= (1 << INT0);          //Enable INT0 
    MCUCR |= (1<<ISC00);          //INT0 is executed on every edge 
    sei(); 
    unsigned char a; 
    a = USART_Receive(); 

 while(1) 
    { 
        do 
        { } while (v == 0);     //Wait for interrupt 
        v = 0; 
        _delay_ms(10000); 
  //Communication protocol between MCU unit and GUI software application 
  //Block 1 
            USART_Transmit(0xFF);                           //Header start command 
            USART_Transmit(0x00); 
            USART_Transmit(0x08); 
            USART_Transmit(0x00); 
            USART_Transmit(0x09); 
            USART_Transmit(0x02); 
            USART_Transmit(0x04); 
            USART_Transmit(0x05); 
            USART_Transmit(0x06); 
            USART_Transmit(0x00); 
            USART_Transmit(0xFE);                           //Header finish command 

        do 
        { } while (v == 0);          //Wait for interrupt 
        v = 0; 
        _delay_ms(10000); 
 //Block 2 
            USART_Transmit(0xFF);                           //Header start command 
            USART_Transmit(0x00); 
            USART_Transmit(0x01); 
            USART_Transmit(0x00); 
            USART_Transmit(0x01); 
            USART_Transmit(0x01); 
            USART_Transmit(0x01); 
            USART_Transmit(0x01); 
            USART_Transmit(0x01); 
            USART_Transmit(0x01); 
            USART_Transmit(0xFE);                           //Header finish command 
          } 
 
     return 0; 
 } 
 If so, pls. post as such and not as bedsheet with unnecessary
 empty lines.
 Do you have TxBuffer ?

Author: Martin (Guest)
Posted on:

Rate this post
0 useful
not useful
Try to use this instead of the _delay_ms(10000):
for (uint16_t i=0; i<=10000) _delay_ms(1);

The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one, 
_delay_ms() provides a decreased resolution functionality. In this mode 
_delay_ms() will work with a resolution of 1/10 ms, providing delays up 
to 6.5535 seconds (independent from CPU frequency). The user will not be 
informed about decreased resolution.

Author: Martin (Guest)
Posted on:

Rate this post
0 useful
not useful
Martin wrote:
> for (uint16_t i=0; i<=10000) _delay_ms(1);

for (uint16_t i=0; i<=10000; i++) _delay_ms(1);

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.