Forum: Mikrocontroller und Digitale Elektronik Interrupt Problem


von Peter (Gast)


Lesenswert?

1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
6
#define Takt      7372800
7
#define UART_Baudrate  9600
8
#define F_CPU      7372800
9
10
11
#define INT1_vect                       _VECTOR(2)
12
#define SIG_INTERRUPT1                  _VECTOR(2)
13
14
15
volatile int32_t a;
16
17
int32_t b;
18
19
20
21
ISR(INT1_vect)
22
{
23
24
b=3;
25
++a;
26
27
  if(a == 2)
28
    {
29
    PORTD |= (1<<PD5);
30
    loop_until_bit_is_clear(PIND, PD3);
31
    a=0;
32
    }
33
34
  PORTD &= ~(1<<PD5);
35
36
  sei();
37
}
38
39
40
int interrupt (void)
41
{
42
MCUCR= (1<<ISC11 ) | (1<<ISC10); // Interrupt steigende flanke
43
GICR= (1<<INT1);
44
}
45
46
47
int main (void)
48
{
49
DDRB = (1<<PB0) | (1<<PB1)| (1<<PB2)| (0<<PB3)| (1<<PB4)| (1<<PB5)| (1<<PB6)| (1<<PB7);
50
interrupt();
51
sei();
52
53
54
  while(1)
55
  {
56
    
57
  }
58
  
59
}
Hallo zusammen,
ich würde gerne erreichen das bei jedem dritten Interrupt PD5 ein high 
Signal ausgibt solange der Interrupt pin high ist. Leider scheint es so 
das die Variable a immer auf 0 zurückgesetzt wird und der uC immer a=1 
im Interrupt erkennt. An was liegt das ?
Gruß und Danke

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> Leider scheint es so
> das die Variable a immer auf 0 zurückgesetzt wird und der uC immer a=1
> im Interrupt erkennt. An was liegt das ?

vermutlich ist der µC nur so schnell das du es nicht siehst. Hast du 
einen Taster dran, wenn ja wird der interrupt wegen dem prellen mehrfach 
aufgerufen.

- a muss nicht volatile wenn sie nur im interupt verwendet wird, so 
sollte am besten static in der funktion liegen

- sei() in der ISR führt höchstes zu fehlern, macht aber bestimmt nicht 
das was du dir erfoffst.

- warten in der ISR ist eine sehr schlechte idee.

von Peter (Gast)


Lesenswert?

danke für die Hinweise, dass meiste ist einfach nur aus Verzweiflung 
enstanden. Wenn ich den code so ändere:

  if(a == 1)
    {
    PORTD |= (1<<PD5);
    loop_until_bit_is_clear(PIND, PD3);
    a=0;
    }

seh ich das Signal mit dem oszi bei jedem Interrupt nur wenn die zahl 
höher wie eins ist springt er nicht mehr in die if schleife. Auch wenn 
ich a=0 lösche

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> nur wenn die zahl
> höher wie eins ist springt er nicht mehr in die if schleife.

if(a == 1)

warum sollte er das auch machen, wenn du auf 1 abfragst?

von Peter II (Gast)


Lesenswert?

es gibt auch einen Simulator - teste es doch einfach dort drin, dann 
sieht du was er macht.

von Peter (Gast)


Lesenswert?

Peter II schrieb:
>> nur wenn die zahl
>> höher wie eins ist springt er nicht mehr in die if schleife.
>
> if(a == 1)
>
> warum sollte er das auch machen, wenn du auf 1 abfragst?

Ich mein wenn ich eine andere Zahl dort einsetze.

von Peter II (Gast)


Lesenswert?

dann zeig doch bitte richtigen code, wo auch die Frage dazu passt.

von Εrnst B. (ernst)


Lesenswert?

Und mach mal in deine main was rein, damit du dauernde Resets erkennen 
kannst.
z.B. einen 1-Sekunden Wait am Anfang, währenddessen eine LED leuchtet.

Und du hast vermutlich dem GCC nicht mitgeteilt, welchen µC du 
verwendest, sonst wären deine INT1_ defines überflüssig.

Schalte die Warnings vom GCC ein, reparier alles bis der nix mehr zu 
meckern findet.

von Peter (Gast)


Lesenswert?

Siehe erster Post :). Dort steht if(a == 3) und nichts funktioniert, bei 
if(a == 1) funktioniert es. Und das verstehte ich nicht weil, jede 50 ms 
ein Interrupt ausgelöst wird. Und a eigentlich von 0 bis 3 zählt und 
PD3 high wird und a wieder auf 0 zurückgesetzt. Aber es scheint so wie 
das in jedem sprung in den Interrupt a=0 ist, was ich nicht verstehe.

von Peter II (Gast)


Lesenswert?

dann resetet eventuell dein µC wie schon von Εrnst B✶ vermutet.

von Peter (Gast)


Lesenswert?

ok ich bastel mal was, danke

von Εrnst B. (ernst)


Lesenswert?

Wie gesagt, reparier erstmal deinen Code. das "sei()" in der ISR ist 
z.B. sehr unschön, kann zu stack-overflows führen, und hat keinerlei 
nutzen.
Dann zeig einen Kompilierbaren Code, verrate uns, welcher µC.

von Peter (Gast)


Lesenswert?

AVR Studio, Atmega16, Programmer AVRISPmk2

Es gibt keinen Reset eine LED mit einer sekunde wait leuchtet durch
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
6
#define Takt      7372800
7
#define UART_Baudrate          9600
8
#define F_CPU      7372800
9
10
11
#define INT1_vect                       _VECTOR(2)
12
#define SIG_INTERRUPT1                  _VECTOR(2)
13
14
15
int32_t a;
16
17
18
19
20
21
ISR(INT1_vect)
22
{
23
24
a++;
25
26
  if(a == 3)
27
    {
28
    PORTD |= (1<<PD5);
29
    loop_until_bit_is_clear(PIND, PD3);
30
    a=0;
31
    }
32
33
PORTD &= ~(1<<PD5);
34
35
36
}
37
38
39
int interrupt (void)
40
{
41
MCUCR= (1<<ISC11 ) | (1<<ISC10); // Interrupt steigende flanke
42
GICR= (1<<INT1);
43
}
44
45
46
int main (void)
47
{
48
49
DDRB = (1<<PB0) | (1<<PB1)| (1<<PB2)| (0<<PB3)| (1<<PB4)| (1<<PB5)| (1<<PB6)| (1<<PB7);
50
interrupt();
51
sei();
52
53
  while(1)
54
  {
55
    
56
  }
57
  
58
}

von Karl H. (kbuchegg)


Lesenswert?

Und schmeiss um Himmels willen die beiden
1
#define INT1_vect                       _VECTOR(2)
2
#define SIG_INTERRUPT1                  _VECTOR(2)
raus!

Wenn da etwas nicht stimmt, dann willst du eine Fehlermeldung vom 
Compiler und nicht selbst reparieren und Fehler machen.

von Karl H. (kbuchegg)


Lesenswert?

>    PORTD |= (1<<PD5);

wie gibst du denn auf einem Portpin etwas aus, der auf Eingang gestellt 
ist?

Und was hängt an deinem Eingangspin PD3? Liegt da ein sauberes Signal 
mit sauberen Flanken an oder muss da mit Prellen gerechnet werden?


> int32_t a;

es gäbe da auch noch int64_t!
Hat ja sonst nichts zu tun, der kleine µC. Um bis 3 zu zählen muss man 
schon ordentlich Bits spendieren.

von Peter (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
>>    PORTD |= (1<<PD5);
>
> wie gibst du denn auf einem Portpin etwas aus, der auf Eingang gestellt
> ist?
>
>
>
>> int32_t a;
>
> es gäbe da auch noch int64_t!
> Hat ja sonst nichts zu tun, der kleine µC. Um bis 3 zu zählen muss man
> schon ordentlich Bits spendieren.

Ganz ruhig, ich sag doch ich bin verzweifelt :).

> Und was hängt an deinem Eingangspin PD3? Liegt da ein sauberes Signal
> mit sauberen Flanken an oder muss da mit Prellen gerechnet werden?

 Ein schmitt trigger, saubere Steile 5V flanken.

-.-

code update
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
6
#define Takt      7372800
7
#define UART_Baudrate  9600
8
#define F_CPU      7372800
9
10
int8_t a;
11
12
13
ISR(INT1_vect)
14
{
15
16
a++;
17
18
  if(a == 3)
19
    {
20
    PORTD |= (1<<PD5);
21
    loop_until_bit_is_clear(PIND, PD3);
22
    a=0;
23
    }
24
PORTD &= ~(1<<PD5);
25
}
26
27
28
int interrupt (void)
29
{
30
MCUCR= (1<<ISC11 ) | (1<<ISC10); // Interrupt steigende flanke
31
GICR= (1<<INT1);
32
}
33
34
35
int main (void)
36
{
37
38
DDRD = (1<<PD0) | (0<<PD1)| (0<<PD2)| (0<<PD3)| (0<<PD4)| (1<<PD5)| (0<<PD6)| (0<<PD7);
39
DDRC=0xFF;
40
DDRB = (1<<PB0) | (1<<PB1)| (1<<PB2)| (0<<PB3)| (1<<PB4)| (1<<PB5)| (1<<PB6)| (1<<PB7);
41
interrupt();
42
sei();
43
44
  while(1)
45
  {
46
    
47
  }
48
  
49
}

von Εrnst B. (ernst)


Lesenswert?

Der GCC hat noch ein paar Anmerkungen:

 avr/include/util/delay.h:89:3: Warnung: #warning "F_CPU not defined for 
<util/delay.h>"

 avr/include/avr/signal.h:36:2: Warnung: #warning "This header file is 
obsolete.  Use <avr/interrupt.h>."

Warnung: »F_CPU« redefiniert

In Funktion »interrupt«:
 Warnung: control reaches end of non-void function

von Εrnst B. (ernst)


Lesenswert?

Das hier macht der GCC bei mir aus deiner ISR. Schaut korrekt aus.
1
.global __vector_2
2
        .type   __vector_2, @function
3
__vector_2:
4
        push __zero_reg__
5
        push r0
6
        in r0,__SREG__
7
        push r0
8
        clr __zero_reg__
9
        push r24
10
/* prologue: Signal */
11
/* frame size = 0 */
12
/* stack size = 4 */
13
.L__stack_usage = 4
14
        lds r24,a
15
        subi r24,lo8(-(1))
16
        sts a,r24
17
        cpi r24,lo8(3)
18
        breq .L6
19
        cbi 50-0x20,5
20
/* epilogue start */
21
        pop r24
22
        pop r0
23
        out __SREG__,r0
24
        pop r0
25
        pop __zero_reg__
26
        reti
27
.L6:
28
        sbi 50-0x20,5
29
.L3:
30
        sbic 48-0x20,3
31
        rjmp .L3
32
        sts a,__zero_reg__
33
        cbi 50-0x20,5
34
/* epilogue start */
35
        pop r24
36
        pop r0
37
        out __SREG__,r0
38
        pop r0
39
        pop __zero_reg__
40
        reti
41
        .size   __vector_2, .-__vector_2

von Peter (Gast)


Lesenswert?

Jetzt nicht mehr
1
#define F_CPU      7372800
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
6
int16_t a;
7
8
ISR(INT1_vect)
9
{
10
11
a++;
12
13
  if(a == 2)
14
    {
15
    PORTD |= (1<<PD5);
16
    PORTC |= (1<<PC0);
17
    loop_until_bit_is_clear(PIND, PD3);
18
    a=0;
19
    }
20
21
PORTD &= ~(1<<PD5);
22
23
}
24
25
26
int interrupt (void)
27
{
28
MCUCR= (1<<ISC11 ) | (1<<ISC10); // Interrupt steigende flanke
29
GICR|= (1<<INT1);
30
31
return 0;
32
}
33
34
35
int main (void)
36
{
37
38
DDRD = (1<<PD0) | (0<<PD1)| (0<<PD2)| (0<<PD3)| (0<<PD4)| (1<<PD5)| (0<<PD6)| (0<<PD7);
39
DDRC=0xFF;
40
DDRB = (1<<PB0) | (1<<PB1)| (1<<PB2)| (0<<PB3)| (1<<PB4)| (1<<PB5)| (1<<PB6)| (1<<PB7);
41
interrupt();
42
sei();
43
44
  while(1)
45
  {
46
    
47
  }
48
  
49
}

von Peter (Gast)


Lesenswert?

hmm der Controller ist es auch nicht hab ihn grad getauscht. Alles sehr 
merkwürdig

von Εrnst B. (ernst)


Lesenswert?

mach mal testweise aus
if(a == 2)

ein
if(a >= 2)

und probiers nochmal.

Aber eigentlich: Der generierte ASM-Code schaut korrekt aus.

von Peter (Gast)


Lesenswert?

Leider keine Veränderung. Kann der Uc reseten ohne das man an den 
Augangspins bemerkt?

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> Leider keine Veränderung. Kann der Uc reseten ohne das man an den
> Augangspins bemerkt?

kommt auf das Progamm an, das "reseten" geht ja in ein paar µC in der 
Zeit sind die Ausgänge halt Eingänge das kann man aber schlecht von 
aussen feststellen.

Noch mal die Frage, warum startest du nicht einfach mal den simulator?

von Pipeline (Gast)


Lesenswert?

Peter schrieb:
> int16_t a;
>
> ISR(INT1_vect)
> {
>
> a++;

mit welchem Wert ist a vorbelegt?
1
ISR(INT1_vect)
2
{
3
   static int16_t a = 0;
4
5
   a++;
6
...

von Pipeline (Gast)


Lesenswert?

Peter schrieb:
> if(a == 2)

ach ja, und bei Zählern
1
   if(a>=2)
2
...
oder einen rettendes
1
else
als default Zweig

von Peter (Gast)


Lesenswert?

Das Problem war, dass im AVR Studio ein Atmega 32 eingestellt war, aber 
ein Atmega 16 benutzt wurde. Danke für die viele Hilfen

Gruß Peter

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.