www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit externem Inerrupt


Autor: Wayne Interessierts (mustang)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Spera (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist die weiter-Variable als volatile deklariert?

Autor: wt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie lange prellt denn der Schalter?

Autor: Wayne Interessierts (mustang)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Spera (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und setzt du sie in der while Schleife auch wieder zurück?^^

Wäre besser, wenn du gleich den ganzen Source Code postest.

Grüße

Autor: Spera (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mir gerade die Schaltung angeschaut.
Wieso hast du einen externen Pull-up Widerstand, wenn du sowieso den 
internen nutzt?

Grüße

Autor: Wayne Interessierts (mustang)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
volatile bool weiter=0;          //OK Taste auswahlmenü

//*********************************************************************************************************************************
// Externen Interrupt 0 initialisieren
//**********************************************************************************************************************************

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
}

//************************************  END ****************************************************************************************


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

unsigned int AkkuSetting(char Akku)
{  
  weiter=0;
  char wahl =0;
  int Kapazitat=100;
  weiter=0;
  LcdClear();
  LcdGotoXY(3,1);
  LcdStr( FONT_1X," Akku ");
  LcdGotoXY(9,1);
  LcdStr( FONT_1X,dtostrf(Akku,1,0,string) );
  LcdUpdate();

  
  while (weiter <1)
  {
    if (wahl == 0)
    {
      LcdGotoXY(1,3);
      LcdStrINV( FONT_1X," Schnelladen ");
      LcdGotoXY(1,4);
      LcdStr( FONT_1X," 14h Laden ");
      LcdGotoXY(1,5);
      LcdStr( FONT_1X," Kapazitaet ");
      LcdUpdate();
    }

    if (wahl ==1)
    {
      LcdGotoXY(1,3);
      LcdStr( FONT_1X," Schnelladen ");
      LcdGotoXY(1,4);
      LcdStrINV( FONT_1X," 14h Laden ");
      LcdGotoXY(1,5);
      LcdStr( FONT_1X," Kapazitaet ");
      LcdUpdate();
  
    }

    if (wahl==2)
    {
      LcdGotoXY(1,3);
      LcdStr( FONT_1X," Schnelladen ");
      LcdGotoXY(1,4);
      LcdStr( FONT_1X," 14h Laden ");
      LcdGotoXY(1,5);
      LcdStrINV( FONT_1X," Kapazitaet ");
      LcdUpdate();
    }
  
    while (!(PIND& (1<<PD3))&&(weiter<0x01));    //Abwarten bis Taster gedrückt
    while ( PIND & (1 << PD3)&&(weiter<0x01));   //Abwarten bis Taster wieder gelöst oder Interrupt (OK Taste betätigt)
  
    wahl++;

    if (wahl==3)
    {
      wahl=0;
    }
  }
  wahl= wahl-1;
  LcdClear();
  LcdGotoXY(3,1);
  LcdStr( FONT_1X," Akku ");
  LcdGotoXY(9,1);
  LcdStr( FONT_1X,dtostrf(Akku,1,0,string) );
  LcdGotoXY(1,3);
  LcdStr( FONT_1X,"Kapazitaet?" );
  LcdUpdate();
  weiter =0;
  
  
  while (weiter<1)
  {
    LcdGotoXY(5,5);
    LcdStr( FONT_1X,dtostrf(Kapazitat,1,0,string));
    LcdGotoXY(10,5);
    LcdStr( FONT_1X,"mA/h" );
    LcdUpdate();

    while (!(PIND&(1<<PD3))&&(weiter0x01));
    while ( (PIND & (1 << PD3))&&(weiter<0x01)) ;
    
    Kapazitat = Kapazitat +100;

    if (Kapazitat ==3100)
    {
      Kapazitat =100;
      LcdGotoXY(8,5);
      LcdStr( FONT_1X," ");
    }

      
  }

  weiter=0;
  Kapazitat = Kapazitat -100;
         //Auswerten der Eingaben

  if (wahl==0)
  {
    Kapazitat = Kapazitat *2/3;
  }

  if (wahl==1)
  {
    Kapazitat = Kapazitat / 10;
  }

  if (wahl ==2)
  {
    Kapazitat = Kapazitat *2/3;
  }

  LcdClear();
  LcdGotoXY(3,1);
  LcdStr( FONT_1X," Akku ");
  LcdGotoXY(9,1);
  LcdStr( FONT_1X,dtostrf(Akku,1,0,string) );

  LcdGotoXY(1,3);
  LcdStr( FONT_1X,dtostrf(Kapazitat,1,0,string) );
  LcdUpdate();
        
  
  
  return Kapazitat;  
}

Autor: Wayne Interessierts (mustang)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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ß

Autor: Spera (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das der ganze Code?
Weil ich sehe keine main Funktion.

Grüße

Autor: Spera (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass die Schaltung so wie sie ist und lass den internen Pullup 
Widerstand weg, indem du PORTD |=(1<<PD2); rauslöscht.

Autor: Wayne Interessierts (mustang)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

...

Autor: Spera (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Spera (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt auch.
Du musst es im MCUCR Register setzen.
So wie du es jetzt hast, triggert der Interrupt solange, wie der INT0 
auf Low ist.

Autor: Wayne Interessierts (mustang)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Wayne Interessierts (mustang)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.