Problem mit externem Inerrupt

OP #1535615
Hallo Gemeinde,

ich kämpfe hier gerade mit dem externen Interrupt des Atmega 32.

Initialisiert ist er folgendermaßen:

void init_interrupt0()
{
  DDRD &= ~ (1 << PD2);       //als Eingang deklarieren
  PORTD |=(1<<PD2);        //Pullup aktivieren
  GICR |= (1<<INT0);        //externen Interrupt 0 freigeben
  MCUCSR |=(1<<ISC01);      //Interrupt auf fallende Flanke
}

in der Interruptroutine steht folgendes:

ISR(INT0_vect)
{
  weiter =1;            //Boolsche Variable auf 1 setzen = 
Bestätigungsbedingung
}

Die globale Interruptfreigabe ( sei () ) erflogt im Hauptprogramm.

Angeschlossen daran ist ein entprellter Taster. Entrellung siehe 
Anahang.

Ich möchte eigentlich, dass der Interrupt genau einmal bei der Fallenden 
Flanke ausgelöst wird. Sollte ja laut Datenblatt so initalisiert werden. 
Tut er aber nicht, stattdessen löst er permanent Inerrupts aus, solange 
ich den Taster gedrück halte.
Was mache ich falsch. Wäre cool, wenn mir jemand weiterhelfen könnte.
Angehängte Dateien:
OP #1535638
wt schrieb:
> wie lange prellt denn der Schalter?

gar nicht, da ja der Taster im moment des drückens den Kondensator 
schlagartig gegen Masse entlädt und somit auch dieses Potential an dem 
Interrupt eingang anliegt.
Diese Schaltung hat sich eigentlich bewährt die hab ich auf einem 
unserer experimentierboards in der Schule gesehen. Zwar an einem 8051 
aber das sollte ja keinen Unterschied machen.

Spera schrieb:
> Ist die weiter-Variable als volatile deklariert?

Ja, die "weiter- Variable" ist als volatile deklariert.
OP #1535658
Der komplette Code ist noch ziemlich lang und SEHR unübersichtlich.

Das ganze soll folgende Anwendung erfüllen:

Ich möchte über 2 Taster (1x Inerrupt / 1x Polling) und ein LCD Display 
die Ladeart und den Ladestrom eines Akkus einstellen.
Dazu ist die Taste die die Kapazität bzw. die Ladeart verändert im 
Pollingbetrieb geschalten und die OK Tast, die das ganze dann übernimmt 
im Interruptbetrieb, wofür die Variable weiter verantwortlich ist.

Hier mal die betreffenden Zeilen:
1
volatile bool weiter=0;          //OK Taste auswahlmenü
2

3
//*********************************************************************************************************************************
4
// Externen Interrupt 0 initialisieren
5
//**********************************************************************************************************************************
6

7
void init_interrupt0()
8
{
9
  DDRD &= ~ (1 << PD2);       //als Eingang deklarieren
10
  PORTD |=(1<<PD2);        //Pullup aktivieren
11
  GICR |= (1<<INT0);        //externen Interrupt 0 freigeben
12
  MCUCSR |=(1<<ISC01);      //Interrupt auf fallende Flanke
13
}
14

15
//************************************  END ****************************************************************************************
16

17

18
ISR(INT0_vect)
19
{
20
  weiter =1;            //Boolsche Variable auf 1 setzen = Bestätigungsbedingung
21
}
22

23
unsigned int AkkuSetting(char Akku)
24
{  
25
  weiter=0;
26
  char wahl =0;
27
  int Kapazitat=100;
28
  weiter=0;
29
  LcdClear();
30
  LcdGotoXY(3,1);
31
  LcdStr( FONT_1X," Akku ");
32
  LcdGotoXY(9,1);
33
  LcdStr( FONT_1X,dtostrf(Akku,1,0,string) );
34
  LcdUpdate();
35

36
  
37
  while (weiter <1)
38
  {
39
    if (wahl == 0)
40
    {
41
      LcdGotoXY(1,3);
42
      LcdStrINV( FONT_1X," Schnelladen ");
43
      LcdGotoXY(1,4);
44
      LcdStr( FONT_1X," 14h Laden ");
45
      LcdGotoXY(1,5);
46
      LcdStr( FONT_1X," Kapazitaet ");
47
      LcdUpdate();
48
    }
49

50
    if (wahl ==1)
51
    {
52
      LcdGotoXY(1,3);
53
      LcdStr( FONT_1X," Schnelladen ");
54
      LcdGotoXY(1,4);
55
      LcdStrINV( FONT_1X," 14h Laden ");
56
      LcdGotoXY(1,5);
57
      LcdStr( FONT_1X," Kapazitaet ");
58
      LcdUpdate();
59
  
60
    }
61

62
    if (wahl==2)
63
    {
64
      LcdGotoXY(1,3);
65
      LcdStr( FONT_1X," Schnelladen ");
66
      LcdGotoXY(1,4);
67
      LcdStr( FONT_1X," 14h Laden ");
68
      LcdGotoXY(1,5);
69
      LcdStrINV( FONT_1X," Kapazitaet ");
70
      LcdUpdate();
71
    }
72
  
73
    while (!(PIND& (1<<PD3))&&(weiter<0x01));    //Abwarten bis Taster gedrückt
74
    while ( PIND & (1 << PD3)&&(weiter<0x01));   //Abwarten bis Taster wieder gelöst oder Interrupt (OK Taste betätigt)
75
  
76
    wahl++;
77

78
    if (wahl==3)
79
    {
80
      wahl=0;
81
    }
82
  }
83
  wahl= wahl-1;
84
  LcdClear();
85
  LcdGotoXY(3,1);
86
  LcdStr( FONT_1X," Akku ");
87
  LcdGotoXY(9,1);
88
  LcdStr( FONT_1X,dtostrf(Akku,1,0,string) );
89
  LcdGotoXY(1,3);
90
  LcdStr( FONT_1X,"Kapazitaet?" );
91
  LcdUpdate();
92
  weiter =0;
93
  
94
  
95
  while (weiter<1)
96
  {
97
    LcdGotoXY(5,5);
98
    LcdStr( FONT_1X,dtostrf(Kapazitat,1,0,string));
99
    LcdGotoXY(10,5);
100
    LcdStr( FONT_1X,"mA/h" );
101
    LcdUpdate();
102

103
    while (!(PIND&(1<<PD3))&&(weiter0x01));
104
    while ( (PIND & (1 << PD3))&&(weiter<0x01)) ;
105
    
106
    Kapazitat = Kapazitat +100;
107

108
    if (Kapazitat ==3100)
109
    {
110
      Kapazitat =100;
111
      LcdGotoXY(8,5);
112
      LcdStr( FONT_1X," ");
113
    }
114

115
      
116
  }
117

118
  weiter=0;
119
  Kapazitat = Kapazitat -100;
120
         //Auswerten der Eingaben
121

122
  if (wahl==0)
123
  {
124
    Kapazitat = Kapazitat *2/3;
125
  }
126

127
  if (wahl==1)
128
  {
129
    Kapazitat = Kapazitat / 10;
130
  }
131

132
  if (wahl ==2)
133
  {
134
    Kapazitat = Kapazitat *2/3;
135
  }
136

137
  LcdClear();
138
  LcdGotoXY(3,1);
139
  LcdStr( FONT_1X," Akku ");
140
  LcdGotoXY(9,1);
141
  LcdStr( FONT_1X,dtostrf(Akku,1,0,string) );
142

143
  LcdGotoXY(1,3);
144
  LcdStr( FONT_1X,dtostrf(Kapazitat,1,0,string) );
145
  LcdUpdate();
146
        
147
  
148
  
149
  return Kapazitat;  
150
}
OP #1535661
Spera schrieb:
> Ich hab mir gerade die Schaltung angeschaut.
> Wieso hast du einen externen Pull-up Widerstand, wenn du sowieso den
> internen nutzt?

Berechtigte Frage!
Habe das ganze gerade so aus einem Schaltplan unseres Schulboards 
übernommen. Aber es ändert auch nichts, wenn ich den externen Pullup 
Widerstand ziehe und nur den internen verwende.

Ist der Interrupt überhaupt richtig initalisiert?
Gruß
OP #1535675
Nein das ist nicht der komplette Code, jedoch greift der Interrupt nur 
auf diese Funktion zu. Also "weiter" wird nur in Akku Settings 
verwendet.

Das Problem ist eben, sobald ich den Interrupt auslöse, springt es mir 
wie gewünscht aus der while schleife wo ich die Ladeart (schnelladen, 
14h Laden, Kapazität) einstelle raus.
"weiter" wird ja danach wieder auf 0 gesetzt. Jedoch muss zeitgleich ein 
Interrupt kommen der Weiter sofort wieder auf 1 setzt und in die nächste 
while schleife (Eingabe der Kapazität) gar nicht mehr hineingesprungen 
wird, da die Bedingung zum beenden der while schleife bereits erreicht 
ist.

Ich hab mir vorhin mal den Spaß gemacht und anstatt einer Bool Variable 
ein int genommen. und deren wert in der Interruptroutine hochzählen 
lassen. Nach 1 Tastendruck stand die irgendwo zwichen 20000 und 40000 
also Taktzyklen. und das bei einem 8MHz Quarz.
Für mich sieht das so aus also ob der permanent interrupts bringt so 
lange der Taster gedrückt bleibt. Ich kann jedoch mit dem Datenblatt 
kein Indiz finden was ich falsch initalisiert habe.

Das deaktiviern von PORTD |=(1<<PD2); ändert auch nichts.
#1535688
> Ich hab mir vorhin mal den Spaß gemacht und anstatt einer Bool Variable
> ein int genommen. und deren wert in der Interruptroutine hochzählen
> lassen. Nach 1 Tastendruck stand die irgendwo zwichen 20000 und 40000
> also Taktzyklen. und das bei einem 8MHz Quarz.
> Für mich sieht das so aus also ob der permanent interrupts bringt so
> lange der Taster gedrückt bleibt. Ich kann jedoch mit dem Datenblatt
> kein Indiz finden was ich falsch initalisiert habe.

Schau Die mal PeDas Entprellung in Software (im Timer-Interrupt) an, 
sie enthält auch eine Flankenerkennung. Duch die Vierfachabfrage ist sie 
auch sehr störfest und kommt mit den labrigsten Tastern zurecht. Taster 
am ext.-Interrupt macht man eigentlich nur, wenn man damit den AVR aus 
dem Power-Down-Sleep holen will. Das eigentliche Tastenauslesen macht 
nach dem Wecken dann wieder der Timer-Int.

...
Gast #1535702
Genau. Für die Tastenabfrage würde ich auch einen Timer und keinen 
Interrupt verwenden.
Trotzdem würde ich dir raten, an deiner Stelle ein neues kleines Projekt 
zu machen, wo du versuchst, jeweils mit Interrupt und dannach mit Timer 
eine Taste abzufragen.
Wenn es dort funktioniert, kannst du es auch bei deinem großen Projekt 
verwenden.

Grüße
#1535762
Dirk K. schrieb:

> Ich hab mir vorhin mal den Spaß gemacht und anstatt einer Bool Variable
> ein int genommen. und deren wert in der Interruptroutine hochzählen
> lassen. Nach 1 Tastendruck stand die irgendwo zwichen 20000 und 40000

Weil du den Interrupt nicht auf Flanke konfiguriert hast.
Du setzt ISC01 im falschen Register.
OP #1535853
Danke euch, das war es...
Wenn ich den ISC01 im MCUCR setze, dann geht es auch wie es soll. Weiß 
auch nicht woher ich noch ein S im MCUCR hatte. Komisch nur, dass der 
Kompiler nicht gemeckert hat.

Aber jetzt noch mal was grundlegendes. Tasterabfrage über Timer. Wie ist 
dabei die generelle Vorgehensweiße und welchen Vorteil bringt es mir im 
gegensatz zu dem externen Interrupt?
#1535865
Dirk K. schrieb:

> auch nicht woher ich noch ein S im MCUCR hatte. Komisch nur, dass der
> Kompiler nicht gemeckert hat.

Warum sollte er. MCUSR gibt es ja auch.

> Aber jetzt noch mal was grundlegendes. Tasterabfrage über Timer. Wie ist
> dabei die generelle Vorgehensweiße und welchen Vorteil bringt es mir im
> gegensatz zu dem externen Interrupt?

Och nö, das wurde hier doch schon mehrfach bis zum Erbrechen und bis in 
das letzte Detail "ausdiskutiert". Wiki und Suche liefern massenhaft 
Infos.
OP #1535914
Stefan Ernst schrieb:
> Och nö, das wurde hier doch schon mehrfach bis zum Erbrechen und bis in
>
> das letzte Detail "ausdiskutiert". Wiki und Suche liefern massenhaft
>
> Infos.

alles klar, dann les ich mich da mal schlau. Danke mal dafür

Stefan Ernst schrieb:
> Warum sollte er. MCUSR gibt es ja auch.

klingt logisch!

Vielen Dank nochmals für euere Hilfe.
#1535961
Dirk K. schrieb u.A.:

> Aber jetzt noch mal was grundlegendes. Tasterabfrage über Timer. Wie ist
> dabei die generelle Vorgehensweiße und welchen Vorteil bringt es mir im
> gegensatz zu dem externen Interrupt?

Ich habe nicht umsonst in meinem Beitrag weiter oben
Beitrag "Re: Problem mit externem Inerrupt"
das Wort Entprellung als Link eingesetzt... ;-)
Da ist das nämlich alles beschrieben bzw. da gibt es weiterführende 
Links. Brauchste nur zu lesen und zu verstehen. In der Codesammlung 
unter dem Suchbegriff "bulletproof" findest Du auch eine umfangreiche 
Diskussion, in der alle Fragen, die Dir einfallen könnten bereits 
gestellt und erschöpfend beantwortet wurden.

...

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.