externer Interrupt (PCINT1) atmega88 - Sprung nach 0x0000

Gast #1816302
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
1
//Interrupt Routine
2

3
ISR(PCINT1_vect)
4
{
5
  //cli();
6
  if(hallindi==1)
7
    hallindi=0;
8
  else
9
    hallindi=1;
10
  //sei();
11
}
12

13
//Biteinstellungen
14

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




Jemand eine Idee wo hier der Fehler liegt?

Gruß Felix
#1816635
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
Gast #1816639
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__avr__interrupts.html
Gast #1816821
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.
Gast #1819219
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
1
EIMSK |= ( 1<<INT1 ); 
2
EICRA |= ( 1<<ISC10 );

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

Felix schrieb:

>
1
> 
2
> //Interrupt Routine
3
> 
4
> ISR(PCINT1_vect)
5
> {
6
> ...
7
> }
8
> 
9
>     PCICR = (1<<PCIE0);
10
>

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...
Gast #1819684
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?
1
/*DDRB &= ~(1<<PB1);*/
2
EICRA = /*(1<<ISC01)|*/(1<<ISC00);
3
//EIMSK = (1<<INT0);
4
PCICR = (1<<PCIE0);
5
PCMSK0 = (1<<PCINT1);
6

7

8
/*ISR(INT0_vect)
9
{
10
  cli();
11
  //LED_PORT ^= (1<<LED1);       //LED1 anschalten
12
  sei();
13
}*/
14

15
ISR(PCINT1_vect)
16
{
17
  //cli();
18
  if(hallindi==1)
19
    hallindi=0;
20
  else
21
    hallindi=1;
22
  //sei();
23
}

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?
#1819690
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...
#1819712
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
Gast #1820597
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren