EmbDev.net

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


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


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:
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
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.) ?
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
0 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
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.