WCM Forum

WCM Forum (http://www.wcm.at/forum/index.php)
-   Home Cockpit - Das Forum für die "Bastler" (http://www.wcm.at/forum/forumdisplay.php?f=55)
-   -   AVR-Interrupts in C (http://www.wcm.at/forum/showthread.php?t=214427)

philharmony 23.04.2007 16:03

Kann mir jmd erklären, warum der Programmzeiger in der Simulation nach jedem Interrupt wieder oben in der 1.Zeile des Main-Prog einsteigt ohne den SIG_Befehl auszuführen?
Eigentlich sollte er doch in der Hauptschleife bleiben, dann das SIG_... ausführen und danach wieder in die Hauptschleife zurückspringen oder?

dirkan 23.04.2007 23:11

Hi,

der Effekt ist typisch für ATMELs, wenn du
den falschen Interruptnamen programmierst.
Der C-Compiler erstellt am Anfang des SRAM
ein Sprungbefehl nach main, gefolgt von einer
Vektortabelle, in der zu jedem Int
ein Interruptfunktionszeiger stehen.
Wenn du eine Interruptfunktion für den externen INT0
interrupt schreibst, belegt der C-Compiler den dafür
vorgesehenen Slot.
Der Interrupt wird ausgelöst, der Prozessor holt den Funktions
zeiger und jumped dahin.
Wenn jedoch da ne NULL steht, weil es keine Funktion dafür gibt,
jumped das Programm nach 0 und das ist der Start des Programms.

Du musst also deine Namen SIG_INT0 kontrollieren.
Gibt es die bei dem verwendeten Prozessor überhaupt ?
Sind in deinem Programm mehrere Interrupts enabled ?


Gruss
Dirk

philharmony 23.04.2007 23:24

Also die SIG_INT0 gibt es und hab ich weiter oben, ausserhalb vom Main definiert.
Ich habe INT0 und INT1 enabled.
Hier mal der Neue Text...

Zitat:

#include <AVR/io.h>
#include <avr/interrupt.h>

int run,i;
run=1;

SIGNAL(SIG_INT0)
{
run=0;
}

SIGNAL(SIG_INT1)
{
run=1;
}

int main (void)
{

DDRB=0xff;
GICR = ((1<<INT0) |(1<<INT1));
GIFR = ((1<<INTF0)|(1<<INTF1));
MCUCR = ((1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10));
sei();


for (;;)
{
if(run==1)
{while(i<5000) i++;
PORTB--;
i=0;
}

}

}






dirkan 24.04.2007 17:14

Setz den MCUCR vor GICR.
Im Manual steht ein Hinweis:
When changing the ISC2 bit, an interrupt can occur. Therefore, it is recommended to first disable INT2 by clearing its Interrupt Enable bit in the GICR Register. Then, the ISC2 bit can be changed.


MCUCR = ((1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10));
GICR = ((1<<INT0) |(1<<INT1));

// das brauchst du wahrscheinlich nicht: GIFR = ((1<<INTF0)|(1<<INTF1));

Viel Erfolg

Dirk

philharmony 24.04.2007 20:44

Hi Dirk, ich benutze doch aber INT2 gar nicht, sondern nur INT0 und INT1...

dirkan 24.04.2007 20:51

Hallo,

probier das doch mal. Vieeleicht gilt das ja auch für die anderen beiden INTs. Irgendwie wird das schon gehen. Haben andere ja auch schon hinbekommen.

Gruss
Dirk

philharmony 24.04.2007 23:13

Hm, keine �nderung.
Bei Wechsel von 0 nach 1 an PIND2 oder PIND3 Springt der Zeiger an die erste Stelle des Main-Blocks ohne jedoch sie SIG-Routine auszuf�hren, dh, die Variable "run" wird nicht ver�ndert...

EDIT: Ok, langsam dämmert es mit dem SIG_...
Aber wo finde ich den namen des entsprechenden Vektors, bzw wie setzt er sich zusammen?
Im Manual steht Vector No.2 bzw 3, 0x001/0x002, INT0/INT1, External Interrupt Request0/1.
Wie setzt sich das mit dem SIG zusammen?

EDIT2:
ISR(_VECTOR(1)){run=0;}
ISR(_VECTOR(2)){run=1;}
funzt, zufällig eben per Google gefunden.
Wie hätte ich jetzt darauf kommen können?

dirkan 25.04.2007 23:43

Hallo,

in den .h Dateien stehen die Deklarationen. Für deinen 8535 gilt:
#define SIG_INTERRUPT0 _VECTOR(1)
#define SIG_INTERRUPT1 _VECTOR(2)
#define SIG_OUTPUT_COMPARE2 _VECTOR(3)
#define SIG_OVERFLOW2 _VECTOR(4)
#define SIG_INPUT_CAPTURE1 _VECTOR(5)
#define SIG_OUTPUT_COMPARE1A _VECTOR(6)
#define SIG_OUTPUT_COMPARE1B _VECTOR(7)
#define SIG_OVERFLOW1 _VECTOR(8)
#define SIG_OVERFLOW0 _VECTOR(9)
#define SIG_SPI _VECTOR(10)
#define SIG_UART_RECV _VECTOR(11)
#define SIG_UART_DATA _VECTOR(12)
#define SIG_UART_TRANS _VECTOR(13)
#define SIG_ADC _VECTOR(14)
#define SIG_EEPROM_READY _VECTOR(15)
#define SIG_COMPARATOR _VECTOR(16)

Es handelt sich um direkte Adressen im RAM. _VECTOR(0) ist der Sprung
nach main() und die anderen zeigen auf die jeweilige Behandlungsroutine. Wenn du eine Behandlungsroutine schreibst, fügt der Compiler in den passenden Slot der Tabelle die Adresse zur Funktion.

Wenn du programmierst:
SIGNAL(SIG_INTERRUPT0) {}
steht nach compilieren im vector 1 ein Zeiger auf deine Funktion.

Definiere doch mal zu allen möglichen 15 Interrupts eine SIGNAL Funktion, dann wird das Programm irgendwo hinspringen, nur nicht auf 0.

Viel Erfolg

Dirk

philharmony 25.04.2007 23:55

Hi Dirk, ok, jetzt hats geklickt, und funktioniert.
Vllt noch ne etwas peinliche Frage: wo finde ich denn die *.h-files? finde im Atmel-Ordner keine und würde da ganz gerne mal reinschauen.
Könnte vllt noch ganz aufschlussreich sein...

dirkan 26.04.2007 22:32

Hallo,

bei mir liegt das unter c:\winavr\avr\include\avr
Aber verrate mir jetzt mal, was letztendlich der Grund war, der
das Programm auf Adresse Null geführt hat ?

Gruss Dirk


Alle Zeitangaben in WEZ +2. Es ist jetzt 04:06 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
© 2009 FSL Verlag