Hallo, ich möchte bei meinem XMEGA128A1 (AVR Studio 4, GNU C, STK600) einen externen Interrupt über PORTB Pin0 auslösen. Hier mein Code uint8_t temp; int main(void) { // internen Oszillator auf 32MHZ einstellen OSC.CTRL = 3; while(OSC.STATUS != 3) { } CCP = 0xD8; CLK.CTRL = 1; temp = 255; // Interrupts aktivieren und alle Level freigeben sei(); PMIC.CTRL=0x07; //LEDS initialisieren PORTA.DIR = 0xFF; PORTA.OUT = 0xFF; //TASTER initialisieren PORTB.DIR = 0x00; //Interrupt Level an PORTB festlegen PORTB.INTCTRL = 0x03; //Interrupt an PORTB PIN0 freigeben PORTB.INT0MASK = 0x01; while(1) { } } ISR (PORTB_INTFLAGS_INT0IF) { if (temp > 0) { temp--; PORTA.OUT = temp; } else { temp = 255; } } Das Interrupt Flag INT0IF wird auch gesetzt, aber die ISR wird nicht gestartet.
Jo, ist mir auch gerade aufgefallen und hab ich geändert ISR (PORTB_INT0_vect) { if (temp > 0) { temp--; PORTA.OUT = temp; } else { temp = 255; } } Läuft aber leider trotzdem noch nicht
Ich gehe mal davon aus, dass die Initialisierung des Port-Interrupts noch nicht ganz stimmt. Für Tips wäre ich sehr dankbar.
Muss ich PORTB als Eingang konfigurieren, damit ich an ihm einen externen Interrupt empfangen kann?
Du hast noch vergessen, bei welcher Flanke der Interrupt triggern soll. Register: PORTB_PIN0CTRL
>Muss ich PORTB als Eingang konfigurieren, damit ich an ihm einen >externen Interrupt empfangen kann? Ja. Sonst kannst Du nur Interrupts detektieren, die die Firmware selbst auf den Pin schreibt.
OK, jetzt sieht die Initialisierung folgendermaßen aus: //TASTER initialisieren PORTB.DIR = 0x00; //Interrupt Level an PORTB festlegen PORTB.INTCTRL = 0x03; //Interrupt an PORTB PIN0 freigeben PORTB.INT0MASK = 0x01; //Interrupt auf fallende Flanke einstellen PORTB.PIN0CTRL = 0x02; Aber leider gehts immer noch nicht und ich glaub auch nicht, dass das der Grund gewesen sein könnte, da das Register ja standardmäßig auf 0x00 steht und damit sowohl auf fallende als auch auf steigende Flanke reagiert werden sollte.
hatte gerade ähnliches Problem ... hatte nur die
1 | #include<avr\interrupt.h> |
vergessen ... der compiler hat weiter nicht gemeckert ... aber die Sprungadresse hat nicht gepasst. also mal überprüfen ob du die zeile drinne hast
Müssen die Initialisierungen vielleicht in einer bestimmten Reihenfolge vorgenommen werden?
Ok, danke, das ist gut zu wissen. Da kommt dann wohl auch mal wieder durch, dass ich blutiger Anfänger bin. Jetzt hab ich aber noch in meinem Programm nen Timer am laufen. Und eigenartigerweise funktioniert der externe Interrupt nur, wenn ich den Timer rauslasse. Sobald ich den Timer initialisiere funktioniert der externe Interrupt nicht mehr.
Aber auch die ISR die durch den Timer-Interrupt aktiviert werden soll läuft nicht. Scheinbar scheinen sich die beiden Interrupts irgendwie gegenseitig zu stören.
guck doch mal im avr simulator (disassembler) deines Programms nach wo die sprünge von der IRQ-Tabelle aus hingehen ... ob das ungefähr was er an der sprungadresse tut - mit deinem dort auszuführenden aufgaben in der ISR zusammenhängen kann ... oder ob er sonstwo hinspringt.
Fehler gefunden: Ich hatte in der ISR des Timers das _vect bei ISR (TCC0_OVF_vect) vergessen. Daher konnte natürlich die Timer ISR nicht laufen. Warum dadurch aber auch die ISR des externen Interrupts nicht lief ist mir trotzdem ein Rätsel. Aber jetzt läufts.
Bis auf die wenigen dokumentierten Errata macht der Controller alles richtig ;-). Zum Glück helfen Datenblatt und Manual. Man muß aber recht viel hin- und herblättern.
Das viele hin- und herblättern ist auch das, was einem Anfänger wie mir zu schaffen macht. Es ist halt gar nicht so einfach, zu selektieren welche Infos gerade wichtig sind und welche nicht. Und an was man alles gerade denken muss.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.