EmbDev.net

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


von Alex K. (Company: ---) (akap)


Rate this post
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:
1
PORTD |= 0x04;                //Activate pull up resistor of PD2
1
GICR |= (1 << INT0);          //Enable INT0
1
MCUCR |= (1<<ISC00);          //INT0 is executed on every edge

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

The variable v is defined as : volatile int v.
1
 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.
1
 ISR (INT0_vect)
1
 {
1
     /* interrupt code here */
1
     v = 1;               //sets interrupt variable v to 1
1
 }
1
 int main(void)
1
 {
1
    USART_Init();
1
    I2C_init();
1
    //int a;                      //test variable
1
    PORTD |= 0x04;                //Activate pull up resistor of PD2
1
    GICR |= (1 << INT0);          //Enable INT0
1
    MCUCR |= (1<<ISC00);          //INT0 is executed on every edge
1
    sei();
1
    unsigned char a;
1
    a = USART_Receive();
1
 while(1)
1
    {
1
        //TODO:: Please write your application code
1
        do
1
        {
1
        } while (v == 0);     //Wait for interrupt
1
        v = 0;
1
        _delay_ms(10000);
1
  //Communication protocol between MCU unit and GUI software application
1
            //Block 1
1
            USART_Transmit(0xFF);                           //Header start command
1
            USART_Transmit(0x00);
1
            USART_Transmit(0x08);
1
            USART_Transmit(0x00);
1
            USART_Transmit(0x09);
1
            USART_Transmit(0x02);
1
            USART_Transmit(0x04);
1
            USART_Transmit(0x05);
1
            USART_Transmit(0x06);
1
            USART_Transmit(0x00);
1
            USART_Transmit(0xFE);                           //Header finish command
1
            do
1
            {
1
            } while (v == 0);          //Wait for interrupt
1
            v = 0;
1
        _delay_ms(10000);
1
 //Block 2
1
            USART_Transmit(0xFF);                           //Header start command
1
            USART_Transmit(0x00);
1
            USART_Transmit(0x01);
1
            USART_Transmit(0x00);
1
            USART_Transmit(0x01);
1
            USART_Transmit(0x01);
1
            USART_Transmit(0x01);
1
            USART_Transmit(0x01);
1
            USART_Transmit(0x01);
1
            USART_Transmit(0x01);
1
            USART_Transmit(0xFE);                           //Header finish command
1
          }
1
     return 0;
1
 }
[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.

von Marc Vesely (Guest)


Rate this post
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.) ?
1
 
2
ISR (INT0_vect) 
3
{ 
4
                v = 1;          //sets interrupt variable v to 1 
5
} 
6
7
 volatile int v = 0; 
8
9
 int main(void) 
10
 { 
11
    USART_Init(); 
12
    I2C_init(); 
13
    PORTD |= 0x04;                //Activate pull up resistor of PD2 
14
    GICR |= (1 << INT0);          //Enable INT0 
15
    MCUCR |= (1<<ISC00);          //INT0 is executed on every edge 
16
    sei(); 
17
    unsigned char a; 
18
    a = USART_Receive(); 
19
20
 while(1) 
21
    { 
22
        do 
23
        { } while (v == 0);     //Wait for interrupt 
24
        v = 0; 
25
        _delay_ms(10000); 
26
  //Communication protocol between MCU unit and GUI software application 
27
  //Block 1 
28
            USART_Transmit(0xFF);                           //Header start command 
29
            USART_Transmit(0x00); 
30
            USART_Transmit(0x08); 
31
            USART_Transmit(0x00); 
32
            USART_Transmit(0x09); 
33
            USART_Transmit(0x02); 
34
            USART_Transmit(0x04); 
35
            USART_Transmit(0x05); 
36
            USART_Transmit(0x06); 
37
            USART_Transmit(0x00); 
38
            USART_Transmit(0xFE);                           //Header finish command 
39
40
        do 
41
        { } while (v == 0);          //Wait for interrupt 
42
        v = 0; 
43
        _delay_ms(10000); 
44
 //Block 2 
45
            USART_Transmit(0xFF);                           //Header start command 
46
            USART_Transmit(0x00); 
47
            USART_Transmit(0x01); 
48
            USART_Transmit(0x00); 
49
            USART_Transmit(0x01); 
50
            USART_Transmit(0x01); 
51
            USART_Transmit(0x01); 
52
            USART_Transmit(0x01); 
53
            USART_Transmit(0x01); 
54
            USART_Transmit(0x01); 
55
            USART_Transmit(0xFE);                           //Header finish command 
56
          } 
57
 
58
     return 0; 
59
 }
 If so, pls. post as such and not as bedsheet with unnecessary
 empty lines.
 Do you have TxBuffer ?

von Martin (Guest)


Rate this post
useful
not useful
Try to use this instead of the _delay_ms(10000):
1
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.

von Martin (Guest)


Rate this post
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);

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.