mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik externer Interrupt (PCINT1) atmega88 - Sprung nach 0x0000


Autor: Felix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich möchte per externen Interupt eine LED testweise an und ausschalten.

Wenn ich am PCINT1 den pin change Interrupt auslöse, startet der uC
wieder bei 0x0000 ,d.h. die main funktion wird erneut aufgerufen.

Zum einsatz kommt ein ATmega88

Hier mal die Initialisierung und die ISR

//Interrupt Routine

ISR(PCINT1_vect)
{
  //cli();
  if(hallindi==1)
    hallindi=0;
  else
    hallindi=1;
  //sei();
}

//Biteinstellungen

    EICRA = /*(1<<ISC01)|*/(1<<ISC00);
    //EIMSK = (1<<INT0);
    PCICR = (1<<PCIE0);
    PCMSK0 = (1<<PCINT1);





Jemand eine Idee wo hier der Fehler liegt?

Gruß Felix

Autor: the cat (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein. Hast Du denn eine Ahnung was das Problem ist?

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau nochmal ins Datenblatt, ich vermute, Du verwechselst externen 
Interrupt und Pin-Change-Interrupt. Das sind nämlich unterschiedliche 
Dinge und daher haben sie auch separate Vektoren. Und wenn der falsche 
Vektor aufgerufen wird, wird dies als Fehler behandelt und kann durchaus 
an Adresse 0 (Neustart) enden (so genau kenne ich den GCC nicht, ich 
mach' nix in C).

MfG

Autor: hab noch was (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kluchscheißender Consulter schrieb:
> Und wenn der falsche
> Vektor aufgerufen wird, wird dies als Fehler behandelt und kann durchaus
> an Adresse 0 (Neustart) enden
"If an unexpected interrupt occurs (interrupt is enabled and no handler 
is installed, which usually indicates a bug), then the default action is 
to reset the device by jumping to the reset vector."
Quelle: 
http://www.nongnu.org/avr-libc/user-manual/group__...

Autor: Frederik Krämer (n0ll4k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Felix schrieb:
> EICRA = /*(1<<ISC01)|*/(1<<ISC00);
  EIMSK |= ( 1<<INT1 ); 
  EICRA |= ( 1<<ISC10 ); 

Das sollte funktionieren, den Rest kannst du weglassen, das wie schon 
erwähnt für Pin Change

Autor: Felix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
erstmal danke für die Antworten und nein ich habe keine Ahnung was es 
sein könnte, aber das was

Kluchscheißender Consulter schrieb:
> Du verwechselst externen
> Interrupt und Pin-Change-Interrupt.

Ist en super Tipp, hab mir das mal im Datenblatt angesehn, davon wusste 
ich garnicht. Hab es schon im Programm geändert. Allerdings kann ich es 
erst Montag wieder testen.

Erfolg oder Misserfolg, ich meld mich nochmal.

Autor: Felix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Problem besteht weiterhin. Um das Problem genauer zu beschreiben, sei 
gesagt das ich über zwei Eingänge einen Interrupt auslösen möchte, das 
hatte ich am Anfang nicht geschrieben. Zum einen über den INT0 auf der 
anderen Seite den PCINT1.

Dieser Teil funktioniert nur für den INT0/INT1
EIMSK |= ( 1<<INT1 ); 
EICRA |= ( 1<<ISC10 ); 

was mir fehlt ist ein Lösungsansatz um auch den PCINT1 "Interruptfähig" 
zu machen.

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Felix schrieb:

>
> 
> //Interrupt Routine
> 
> ISR(PCINT1_vect)
> {
> ...
> }
> 
>     PCICR = (1<<PCIE0);
> 

das passt ja wohl nicht zusammen...mit PCIE0 setzt du 'Pin Change 
Interrupt Enable 0', hast aber nur eine ISR für 'Pin Change Interrupt 
Enable 1'. Vielleicht schaust du nochmal ins Datenblatt, wie die 
PC-Interrupts im Gegensatz zu den 'normalen' ext. Interrupts 
funktionieren...

Autor: Felix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werd aus dem letzten Kommentar nicht ganz schlau, weil mir glaub ich der 
Unterschied immer noch nicht klar ist.
Ich hab im Programm zwei ISR's eine für den INT0 und eine für den PCINT1 
hab jetzt die entsprechenden Stellen im Datenblatt die ich gefunden hab 
durchgelesen.

Hab die zugehörige Routine mit richtigem Vektor und hab soweit alle 
zugehörigen Bit's gesetzt, oder ist da grundlegend was falsch?
/*DDRB &= ~(1<<PB1);*/
EICRA = /*(1<<ISC01)|*/(1<<ISC00);
//EIMSK = (1<<INT0);
PCICR = (1<<PCIE0);
PCMSK0 = (1<<PCINT1);


/*ISR(INT0_vect)
{
  cli();
  //LED_PORT ^= (1<<LED1);       //LED1 anschalten
  sei();
}*/

ISR(PCINT1_vect)
{
  //cli();
  if(hallindi==1)
    hallindi=0;
  else
    hallindi=1;
  //sei();
}

Wie gesagt es geht mir darum das der Interrupt vom PCINT1 nicht das 
gesamte Program neu startet. Was löst den Fehler für diesen Reset aus?

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Felix schrieb:
> Hab die zugehörige Routine mit richtigem Vektor und hab soweit alle
> zugehörigen Bit's gesetzt, oder ist da grundlegend was falsch?

ja. Es gibt zwei PCINT1: Zum einen den Pin PCINT1, der eine Bezeichnung 
für PB1 ist. Daneben gibt es noch den Interruptvektor PCINT1_vect, der 
aber für die PinChange-Interrupts PCINT8..15 zuständig ist.

Es gibt drei PinChange-'Blöcke':
PortB mit PCINT0..7
PortC mit PCINT8..15
PortD mit PCINT16..23
PortB ist Block 0, PortC ist 1 und PortD ist 2. Und dementsprechend ist 
auch die Bezeichnung der Register.
Alles mit 0 gehört zu PortB. Und der Pin mit PCINT1 liegt nunmal auf 
PortB und damit gehört dazu die ISR PCINT0_vect.

Und bevor die Frage kommt: Man kann keine verschiedenen ISRs für die 
verschiedenen Pins eines 'Blocks' definieren...

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Werd aus dem letzten Kommentar nicht ganz schlau, weil mir glaub ich der
>Unterschied immer noch nicht klar ist.

>Was löst den Fehler für diesen Reset aus?

ISR(PCINT1_vect) ist für PCINT8...PCINT14, nicht für PCINT1, zuständig.

MfG Spess

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und bevor die Frage kommt: Man kann keine verschiedenen ISRs für die
> verschiedenen Pins eines 'Blocks' definieren...

Noch ein Tipp: Es gibt Register, mit denen man die 'Blocks' maskieren 
kann, also festlegen kann, welche Pins (Bits) des Blocks (Bytes) den 
Interrupt auslösen dürfen und welche nicht.

Es lohnt sich also, das entsprechende Kapitel des Datenblatts zu lesen 
(und zu verstehen) anstatt einfach nur per Suchfunktion nach 
Schlagworten zu suchen.

MfG

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kluchscheißender Consulter schrieb:
> Noch ein Tipp: Es gibt Register, mit denen man die 'Blocks' maskieren
> kann, also festlegen kann, welche Pins (Bits) des Blocks (Bytes) den
> Interrupt auslösen dürfen und welche nicht.

das hatte er an sich ja gemacht
PCMSK0 = (1<<PCINT1);

Autor: Kluchscheißernder Nixwisser (kluchscheisser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, dann nehme ich alles zurück und behaupte das Gegenteil. ^^

MfG

Autor: Felix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super!!! Klappt alles.

Die Register hab ich gefunden

Kluchscheißender Consulter schrieb:
> Noch ein Tipp: Es gibt Register, mit denen man die 'Blocks' maskieren
>
> kann, also festlegen kann, welche Pins (Bits) des Blocks (Bytes) den
>
> Interrupt auslösen dürfen und welche nicht.


Was ich allerdings nicht wusste, war diese Aufteilung in drei Blöcke.

Justus Skorps schrieb:
> Es gibt drei PinChange-'Blöcke':
>
> PortB mit PCINT0..7
>
> PortC mit PCINT8..15
>
> PortD mit PCINT16..23



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.