Hallo Leute, ich hoffe ihr könnt mir weiter helfen. ich versuche im Moment vergeblich irgendwelche Interrupts bei einem Tiny26 zu erzeugen. Der nachfolgende C-Code sollte ein Interrupt INT0 beim ändern des INT0 Pins PB6 erzeugen und eine LED, die irgendwo an PORTA angeschlossen sein kann zum leuchten zu bringen. Sieht jemand von Euch, wo ich den Fehler drin habe? Danke Gruß ------------------Code--------------------------------------------- #include <avr/io.h> #include <avr/signal.h> #include <avr/interrupt.h> SIGNAL (SIG_INT0) { //LED will go an PORTA = 0x00; //waiting for sync asm volatile ("NOP"); } int main (void) { //Configure PortA as output DDRA = 0xff; //Configure PortB as Output DDRB = 0xff; //Clear PortB pin6 PORTB &= ~(1 << PINB6); //Configure POrt B Pin6 as Input DDRB &= ~(1 << DDB6); //Aktivate INT0 GIMSK = _BV(INT0); //Configure INT0 so that every level change will generate Interrupt MCUSR = _BV(ISC00); //Set all Pins of PortA LED will go off PORTA = 0xff; //Enable all Interrupts sei(); //So far do nothing util Interrupt occurs for (;;) { asm volatile ("nop"); } PORTA = 0xff; }
Hast du wirklich eine Spannung am Int0 angelegt, oder nur mit Draht nach Masse kurzgeschlossen? Weil Pullup hast du anscheinend für den Pin nicht eingeschaltet. Funkioniert die LED überhaupt? Zieh den Pin am Programmanfang mal nach 0 und mach ein delay, dass du siehst ob sie leuchtet. Sonst seh ich nix falsches (bin aber kein guter Falsches-Seher).
Hallo Fritz, ich habe sowohl einen externen 10k Pullup an Int0 angeschlossen, als auch den internen Pullup verwendet und anschließend nach Masse geschaltet. Die LED funktioniert. Danke für Deine Hilfe. Gruß
Hallo Leute, Problem SOLVED! Warum weiß ich jetzt nicht, aber ein SREG |= 1 << SREG_I; bringt den Tiny26 ins schwingen. Der Resultat ist ein teilweise unkoordiniertes herumhüpfen im Programmcode. Weiterhin heißt das bei dem nicht SIG_INT0 (wie bei den Megas) sondern SIG_INTERRUPT0. Na ja, Problem solved und ein wenig schlauer! #include <avr/io.h> #include <avr/signal.h> #include <avr/interrupt.h> #include <avr/sleep.h> INTERRUPT (SIG_INTERRUPT0) { //LED will go an if (PORTA == 0xff) PORTA = 0x0; else PORTA = 0xff; //waiting for sync asm volatile ("NOP"); } int main (void) { //Configure PortA as output DDRA = 0xff; //Configure PortB as Output DDRB = 0xff; //Set PortB pin6 PORTB |= (1 << PINB6); //Aktivate INT0 sbi (GIMSK,INT0); //Configure INT0 so that every level change will generate Interrupt sbi (MCUCR,ISC00); //Enable Sleep mode sbi (MCUCR,SE); //Enable all Interrupts sbi (SREG,SREG_I); //Set all Pins of PortA LED will go off PORTA = 0xff; //Activate Sleep Mode Idle set_sleep_mode (SLEEP_MODE_IDLE); //Now sleep until interrupt occurs sleep_mode(); }
Hab grad bei mir nachgesehen, ich hab stehen: SIGNAL (SIG_INTERRUPT0) { } Vielleicht macht das einen Unterschied? Dann hab ich in der IR Routine noch ein GICR &= ~_BV (INT0); Und im Hauptprogramm schalte ich mit GICR |= _BV (INT0) den Interrupt wieder ein. Grund ist, dass die Interruptroutine bei mir rekursiv oder ständig aufgerufen wurde. Allerdings hab ich Level und kein Flankeninterrupt verwendet, weil Flankeninterrupt im Powersleep nicht geht. Vielleicht hilft das weiter.
Exakt so gehe ich auch vor. Der Low-Level-Int wird solange wiederholt ausgeführt wie Low Pegel am Int0 ist. Zu diesem Verhalten konnte ich leider nichts in den Datenblättern finden. In diesem Sinne heist das aber das in der INT0-ISR unbedingt über das GICRegister der Low-Level INT deaktiviert werden muß. Bevor ich dann in der Main Loop in den Powerdown Sleepmode gehe aktiviere ich dann den INT0-ISR wieder. Gruß Hagen
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.