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
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
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
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.
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.
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...
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?
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...
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
> 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
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
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!!!