mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega8 INT0 mit AVR Studio Simulation


Autor: wulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Hab gerade angefangen den INT0 des ATMega8 auszuprobieren.
Dazu verwende ich folgenden Code:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
 
ISR(_VECTOR(1)) { // INT0
cli(); // Interrupts abschalten
PORTB |= (1<<PB1); // PB.1 setzen

}

int main(void)
{

DDRB = 0b00000011; // 0-1: Ausgang
DDRD = 0x00; // Eingänge
GIMSK |= (1<<INT0); // INT0 aktivieren
MCUCR |= ((1<<ISC01) | (1<<ISC00)); // bei steigender Flanke

sei(); // Interrupts aktivieren
 
while (1) {
PORTB ^= (1<<PB0); // PB.0 toggeln
}

}

Den PB.0 toggle ich, um zu sehen dass das Programm rennt. Wenn ich dann 
denn Pin D.2 auf high setze, wird auch die richtige Funktion aufgerufen 
aber es passiert dort nichts. Den PB1 kann ich nicht auf high setzen und 
eigentlich sollten ja die Interrups dann golbal deaktiviert sein, oder?
Wenn ich dann aber den INT0 Pin wieder auf 0 und dann auf 1 setze, wird 
der Interrupt erneut aufgerufen und es passiert nichts.

Was mache ich falsch?

Danke schonmal,
wulf

Autor: wulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK. Warum ich an PB.1 nichts ändern kann, ist mir mittlerweile klar.
ABer warum hat cli() in der Interruptroutine keine Auswirkungen?

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuch' mal die ISR so aufzurufen:

SIGNAL (SIG_INTERRUPT0)
{

}

Das CLI kannst du dir sparen, da das beim Aufruf der ISR sowieso 
passiert. Der globale INT wird beim Verlassen der ISR 'SIGNAL' wieder 
gesetzt, wenn du 'INTERRUPT' statt dessen verwendest musst du das 
Globale 'I'-Flag von Hand wieder setzen. Siehe AVR-LibC.

Autor: wulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort!
Hab nun SIG_INTERRUPT0 probiert und es geht wieder nicht, wie ich will.

Das Programm soll keine besondere Funktion haben, nur Versuche.
Ich hätte gerne, dass der INT0 ein einziges mal aufgerufen wird; dort 
ALLE Interrupts deaktiviert werden und somit von selbst nie wieder 
auftreten.

Autor: wulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mittlerweile wieder selbst ein bisschen experimentiert:
wenn ich einfach den INT0 Interrupt abdrehe (in der INT0-Routine), dann 
wird beim nächsten Ansteigen des Signals nur das entsprechende Flag 
gesetzt, aber die Routine wird nicht mehr aufgerufen.

Aber wieso kann ich mit cli() nicht einfach alles abdrehen?

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du brauchst nur den INT0 deaktivieren, das Register heißt übrigens GICR, 
nicht GIMSK. Ist vermutlich auch der Fehler.

SIGNAL (SIG_INTERRUPT0)
{
    GICR &= ~(1<<INT0);
    PORTB |= (1<<PB1);    // PB.1 setzen
}

Autor: wulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie schon oben geschrieben; das hat funktioniert

GIMSK = General Interrupt Mask Register (aus dem AVRGCC Tutorial) zwar 
nicht für den Atmega 8, aber der Compiler übersetzt es richtig auf GICR

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Upps.. Zeitüberschneidung.
Wenn die ISR wieder verlassen wird wird der Globale INT ('I'-Flag) 
wieder gesetzt, hab' ich oben schon geschrieben. Mit INTERRUPT statt 
SIGNAL als ISR kannst du auch das 'I'-Flag löschen.

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so, um's mal mit Assembler zu vergleichen:

SIGNAL verlässt die ISR mit 'reti'
INTERRUPT verlässt sie mit 'ret'

alles klar?

Autor: wulf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mit INTERRUPT statt SIGNAL als ISR kannst du auch das 'I'-Flag löschen.
Also INTERRUPT(SIG_INTERRUPT0) {} ?
Da tut sich bei mir nichts.
ISR(SIG...) schaltet nichts aus und SIGNAL(SIG...) auch nicht.

Aber es geht eh mit GICR &= ~(1<<INT0);
Den PB.1 konnte ich nicht setzen, da ich ja in der main() als 
Endlosscheife mit diesem Port arbeite; jetzt wird in der main() die ISR 
aufgerufen und beim Rückkehren schreibt es halt den 
zwischengespeicherten Registerwert auf den Port, so dass meine 
Änderungen in der ISR verloren gehen. Das hab ich aber mittlerweile eh 
schon gelöst

Danke nochmal!

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.