Forum: Compiler & IDEs Problem mit Interrupt


von Alexander B. (Gast)


Lesenswert?

Hey,

 ich habe die letzten Tage versucht mit meinen Testboard ( AVR-P40-USB), 
die externe Interrupt Geschichte zu verstehen.

Ich habe einen ATMEGA32 auf dem Board.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/delay.h>
4
#define CPU_F 8000000UL
5
6
7
uint8_t flag;  //globale Variable
8
9
int port_init (void)
10
{
11
DDRB |= (1<<PB0);  //LED PB0 auf Ausgang
12
DDRB &= ~ (1<<PB1); //Taster PB1 auf Eingang
13
PORTB = (1<<PB0);    //LED aus
14
15
DDRD &= ~ (1<<PD2); //INT0 auf Eingang
16
PORTD = (1<<PD2);   // interner Pullup Widerstand 
17
18
return 0;
19
}
20
21
22
23
int interrupt_init (void)
24
{ 
25
26
MCUCR = 0b00000011; //Steigende Flanke erzeugt Interrupt
27
GICR = 0b01000000; //INT0 aktiviert
28
29
return 0;
30
31
}
32
33
34
ISR (INT0_vect)
35
{
36
flag = 1; // Variable setzen
37
}
38
39
40
41
42
43
44
45
int main (void)
46
{
47
  port_init();          // Init 
48
  interrupt_init();     //Init
49
 
50
  
51
52
PORTB &=~ (1<<PB0); // LED TEST
53
_delay_ms (500);    // LED TEST
54
PORTB = (1<< PB0);  // LED TEST
55
56
sei();
57
 
58
  while (1)  
59
   {
60
  if (flag == 1)          // Variable abfragen
61
    {
62
     PORTB &=~ (1<<PB0);  // LED Anschalten
63
    }
64
   }
65
66
67
}


Der LED test funktioniort auf dem Board . Jedoch wenn ich den Taster 
drücke passiert nichts.

LED ist active low;
Taster active high  an int0 mit internem pullup widerstand.

Bitte um Hilfe.

Danke im voraus

von Stefan E. (sternst)


Lesenswert?

volatile

von Oliver (Gast)


Lesenswert?

Alexander Bartler schrieb:
> Taster active high  an int0 mit internem pullup widerstand.

Damit liefert der gedrückte Taster high, der ungedrückte auch. Das 
verwirrt den AVR dann so sehr, daß er gar nichts macht ;-)

Ansonsten heisst die Antwort auf dein Problem "volatile".

Oliver

von Alexander B. (Gast)


Lesenswert?

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/delay.h>
4
#define CPU_F 8000000UL
5
6
7
volatile uint8_t flag;  //globale Variable
8
9
int port_init (void)
10
{
11
DDRB |= (1<<PB0);  //LED PB0 auf Ausgang
12
DDRB &= ~ (1<<PB1); //Taster PB1 auf Eingang
13
PORTB = (1<<PB0);    //LED aus
14
15
DDRD &= ~ (1<<PD2); //INT0 auf Eingang
16
PORTD = (1<<PD2);   // interner Pullup Widerstand 
17
18
return 0;
19
}
20
21
22
23
int interrupt_init (void)
24
{ 
25
26
MCUCR = 0b00000001; //Steigende Flanke erzeugt Interrupt
27
GICR = 0b01000000; //INT0 aktiviert
28
29
return 0;
30
31
}
32
33
34
ISR (INT0_vect)
35
{
36
flag = 1; // Variable setzen
37
}
38
39
40
41
42
43
44
45
int main (void)
46
{
47
  port_init();          // Init 
48
  interrupt_init();     //Init
49
 
50
  
51
52
PORTB &=~ (1<<PB0); // LED TEST
53
_delay_ms (500);    // LED TEST
54
PORTB = (1<< PB0);  // LED TEST
55
56
57
cli ();
58
59
uint8_t led;
60
61
flag = led;
62
63
sei();
64
 
65
  while (1)  
66
   {
67
  if (led == 1)          // Variable abfragen
68
    {
69
     PORTB &=~ (1<<PB0);  // LED Anschalten
70
    }
71
   }
72
73
74
}

Funktioniert immer noch nicht, stimmt das so mit volatile ?
Oder soll ich einfach mal einen externen Pullup Widerstand verwenden ?

mfg Alex

von Karl H. (kbuchegg)


Lesenswert?

Alexander Bartler schrieb:

> Oder soll ich einfach mal einen externen Pullup Widerstand verwenden ?

Wenn dein Taster wirklich 'active high' ist,
dann brauchst du einen Pull-DOWN und keinen Pull-UP

von Alexander B. (Gast)


Lesenswert?

JA meine ich damit, aber ich hatte es neulich schonmal versucht aber es 
hatte nicht geklappt.  Stimmt das so mit dem volatile ? an was könnte es 
sonst noch liegen?

von Karl H. (kbuchegg)


Lesenswert?

Alexander Bartler schrieb:
1
  cli ();
2
  uint8_t led;
3
  flag = led;
4
  sei();
5
  
6
   while (1)
7
   {
8
     if (led == 1)          // Variable abfragen
9
     {
10
       PORTB &=~ (1<<PB0);  // LED Anschalten
11
     }
12
   }
13
}

>
> Funktioniert immer noch nicht,

und wie stellst du dir vor, dass die Variable led innerhalb der while 
Schleife jemals einen anderen Wert bekommen soll?

von Karl H. (kbuchegg)


Lesenswert?

Ich denke ein nicht unerhebliches Problem in deiner Programmierung ist 
die schlecht Code-Formatierung bzw. schlechte Wahl von Variablennamen.

Mit den vielen Leerzeilen ziehst du dir den Code auf dem Bildschirm 
unnötig in die Länge und verlierst dabei den Überblick.

Nichts gegen Aufteilung in Funktionen.
Aber diese beiden init Funktionen erzeugen dir mindestens 25 Zeilen im 
Quelltext, die du auf 5 reduzieren könntest, wenn du die 
Initialisierungen ganz einfach in main machen würdest.
Dein Code würde kürzer und damit leichter zu überblicken. Die 
Komplexität in main() steigt durch die Initialisierungen aber nicht 
wesentlich.

von Karl H. (kbuchegg)


Lesenswert?

Alexander Bartler schrieb:
> JA meine ich damit,

Na dann.
Dann haben wir:

* Ist der Taster nicht gedrückt, hält der Pullup Widerstand den
  Eingang auf +5V, also high

* Ist der Taster gedrückt, 'zieht' der Taster die Leitung auf +5V,
  also ebenfalls high

Für den µC präsentiert sich also der Eingang ständig auf high.
Wie soll der dann erkennen, dass du den Taster gedrückt hast?

von Alexander B. (Gast)


Lesenswert?

Danke erst mal,

also mit den Variablennamen bin ich nicht so einfallsreich, und das mit 
den vielen leerzeilen.. ich finde es für mich übersichtlicher --> 
Ansichtssache.

Ich hab jetzt den Taster  mit pull-DOWN widerstand eingelötet. 
Funktioniert immer noch nicht.

Das mit der while-Schleife stelle ich mir so vor, dass dort immer die 
variable abgefragt wird, und wenn der interrupt auslöst wird ja der Wert 
der Variable geändert. ich habe jetzt in der Whileschleife direkt "flag" 
genommen für die If-bedingung
1
  while (1) {
2
      if (flag == 1)          // Variable abfragen
3
    {
4
     PORTB &=~ (1<<PB0);  // LED Anschalten
5
    }
6
   }

Aber es funktioniert nicht.  Leider.

von Alexander B. (Gast)


Lesenswert?

Zum avtive high und Pulldown Widerstand--> Versorgungsspannung geht auf 
Taster danach geht taster auf den Widerstand danach zu masse. Der Pin 
wird zwischen Widerstand und Taster abgegriffen.  Somit ist bei offenem 
Schalter keine Spannung vorhanden da ohne Strom auch keine Spannung am 
Widerstand abfallen kann.. wird der Taster geschlossen so fließt strom 
durch den Widerstand und dort fällt die gesamt Spannung gezwungenermaßen 
ab, da der Schalter im geschlossenen Zustand keinen Widerstand hat.


Umformatiertet Code ;)
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#define CPU_F 8000000UL
5
6
7
volatile uint8_t flag;  //globale Variable
8
9
int init (void)
10
{
11
DDRB |= (1<<PB0);  //LED PB0 auf Ausgang
12
DDRB &= ~ (1<<PB1); //Taster PB1 auf Eingang
13
PORTB = (1<<PB0);    //LED aus
14
DDRD &= ~ (1<<PD2); //INT0 auf Eingang
15
MCUCR = 0b00000001; //Steigende Flanke erzeugt Interrupt
16
GICR = 0b01000000; //INT0 aktiviert
17
return 0;
18
}
19
20
21
ISR (INT0_vect)
22
{
23
flag = 1; // Variable setzen
24
}
25
26
27
int main (void)
28
{
29
init();          // Init 
30
PORTB &=~ (1<<PB0); // LED TEST
31
_delay_ms (500);    // LED TEST
32
PORTB = (1<< PB0);  // LED TEST
33
sei();
34
while (1) 
35
36
   {
37
      if (flag == 1)          // Variable abfragen
38
    {
39
     PORTB &=~ (1<<PB0);  // LED Anschalten
40
    }
41
   }
42
}

von Karl H. (kbuchegg)


Lesenswert?

Alexander Bartler schrieb:
> Zum avtive high und Pulldown Widerstand--> Versorgungsspannung geht auf
> Taster danach geht taster auf den Widerstand danach zu masse. Der Pin
> wird zwischen Widerstand und Taster abgegriffen.  Somit ist bei offenem
> Schalter keine Spannung vorhanden da ohne Strom auch keine Spannung am
> Widerstand abfallen kann.. wird der Taster geschlossen so fließt strom
> durch den Widerstand und dort fällt die gesamt Spannung gezwungenermaßen
> ab, da der Schalter im geschlossenen Zustand keinen Widerstand hat.

Alles schön und gut.


> int init (void)
> {
> DDRB |= (1<<PB0);  //LED PB0 auf Ausgang
> DDRB &= ~ (1<<PB1); //Taster PB1 auf Eingang
> PORTB = (1<<PB0);    //LED aus
> DDRD &= ~ (1<<PD2); //INT0 auf Eingang

Wo hängt denn nun dein Taster?
Auf PB1 oder auf PD2

Laut Code und Kommentar hängt dein Taster auf PB1
Die Interrupt Hardware lauscht aber auf PD2

von Karl H. (kbuchegg)


Lesenswert?

Alexander Bartler schrieb:

> Umformatiertet Code ;)

:-)
Das nennst du umformatiert?

von Alexander B. (Gast)


Lesenswert?

Der taster hängt an pb1 und pd2 aber die Zeile  mit pb1 ist hier 
überflüssig. Kann jemand vllt. Mal einen verbesserten Code von mir aus 
auch kurz Posten? Wäre eine echte Hilfe

von Marco F. (m8_killer)


Angehängte Dateien:

Lesenswert?

hier ist mein vorschlag, einfach und funzt

gruss

von Marco F. (m8_killer)


Lesenswert?

p.s.  ist für atmega32 geschrieben

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.