Hallo, ich habe ein Problem mit der Nutzung von Interrupts. Ich habe schon länger daran rumprobiert und bin jetzt zur einfachsten Variante (siehe unten) übergegangen. Das ganze soll eigentlich nur nach kurzer Zeit den Ausgang von Aus auf An schalten. Der Interrupt wird auch ausgelöst und der Ausgang kurzzeitig auf An gesetzt - gleich danach wird das aber zurückgesetzt und der Ausgang wieder Low gelegt. Ich habe so die Vermutung, dass entweder nach dem Interrupt ein Reset ausgeführt wird oder aber der Rücksprung aus dem Interrupt nicht klappt - würde er vor die Funktion "einstellen" springen, würde der Ausgang ja wieder low gelegt. Ich wäre wirklich über jede Hilfe sehr dankbar. Code: #define _AVR_ATmega169_ #include <avr/io.h> #include <avr/signal.h> #include <avr/interrupt.h> void einstellen (void) { CLKPR = (1<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<<CLKPS0); CLKPR = (0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(0<<CLKPS0); //Clock geteilt durch 64 DDRB = (1<<DDB6); //Pin7 an B auf Output PORTB = (0<<PB6); // und inaktiv TIMSK0 = (0<<OCIE0A)|(1<<TOIE0); //overflow enabled TCCR0A = (0<<WGM00)|(0<<WGM01)|(1<<CS02)|(0<<CS01)|(1<<CS00); // prescaler 1024 sei(); //globaler Interrupt an } SIGNAL (SIG_OVERFLOW0) { PORTB = (1<<PB6); } int main (void) { einstellen (); for (;;) ; return 0; }
> #define __AVR_ATmega169__ Das darfst Du nicht tun, Macros, die mit einem Unterstrich beginnen, sind reserviert. Dieser Macro wird intern generiert in Abhängigkeit von Deiner -mmcu Anweisung. Vermutlich liegt genau hier auch der Pfeffer im Hasen: Du wirst kein -mmcu haben, so daß der Compiler/ Linker Dir die Runtime für irgendwas (AT90S8515 oder was auch immer der Default ist) zusammenbasteln, so daß weder Interruptvektortabelle noch Stack-Initialisierung auch nur ansatzweise passen.
Hi, danke für die Antwort - ich habe das jetzt rausgenommen und mit: avr-gcc -mmcu=atmega169 test.c compiliert - danach dann noch das HexFile erstellt: avr-objcopy -j .text -O ihex a.out test.hex Leider bleibt das Ergebnis das gleiche. Also wenn ich das auf den Controller spiele, schaltet er den Ausgang kurz an und gleich wieder aus. Ist es möglich, dass er irgendwie falsch zurückspringt ?
Ich müßte im Datenblatt nachgucken, aber meiner Erinnerung nach kann man bei ATmega169 den Watchdog per Fusebit einschalten. Hast Du das aus Versehen getan?
Hab mal im Datenblatt geschaut - es ist möglich per Fusebit den Watchdog zu aktivieren aber dazu hätte ich das WDCE bit setzen müssen und eigentlich habe ich damit gar nix gemacht. Der Code der oben steht ist alles, was ich nutze... wird das in einer der Includedateien vielleicht gemacht ?
Du wirfst hier ziemlich viel durcheinander. Das Fusebit für den Watchdog heißt WDTON (in den high fuses) und hat mit WDCE schlicht gar nichts zu tun. Ob Du Deine Fusebits angefaßt hast, hat nichts mit Deinem Code zu tun, sondern das tust Du vom Programmiergerät aus. Includedateien generieren durch bloßes Einfügen mit #include keinen Code, können Dir also hier nichts geändert haben.
Guten Morgen, hm das stimmt, dass mit WDTON und WDCE hab ich jetzt durcheinander gebracht, weil ich noch geschaut habe, ob ich den Watchdog vielleicht selbst eingeschaltet habe. Mir ist noch ein anderes Phänomen eingefallen. Ich hatte auch mal versucht die Interruptroutine länger zu machen - also einfach mit einer Schleife, die nur immer wieder den Assemblerbefehl nop ausgeführt hat. Trotzdem hat sich aber die Zeit, die der Port an war nicht verändert. Ich schreibe den Code auf den AVR mit AVRProg - also aus dem AVR Studio 4 heraus. Bisher hatte ich aber nie ein Problem und es hat eigentlich immer alles so funktioniert, wie ich das wollte - dieses Problem habe ich erst, seitdem ich Interrupts nutzen will. Übrigens: wenn ich die Zeitspanne nach der der Interrupt kommen soll, ändere, verhält es sich alles genauso (was doch eigentlich heisst, dass es nur schwerlich am Watchdog liegen kann, weil ich doch nicht gleichzeitig diese Zeitspanne verändere - jedenfalls nicht bewusst :) ) Danke nochmal für die Hilfe.
Vielleicht rufst Du ja testhalber einfach mal in der Hauptschleife wdt_reset() auf?
Guten Morgen, ich habe jetzt mal in der Hauptschleife wdt_reset() aufgerufen - da hat sich nichts verändert. Dann habe ich noch versucht bei der Initialisierung den WDT auszuschalten über: wdt_reset(); WDTCR = (1<<WDTCE) | (1<<WDE); /* Turn off WDT */ WDTCR = 0x00; Geändert hat sich aber auch nichts - er schaltet den Pin immer kurz auf high und dann gleich wieder low. Hast du noch irgend'ne andere Idee ?
Hallo Niels, Du schreibst: | avr-gcc -mmcu=atmega169 test.c compiliert - danach dann noch das | HexFile erstellt: | avr-objcopy -j .text -O ihex a.out test.hex Ich habe die Infos nicht hier, aber irgendwie vermisse ich den Linker. Kann es sein, daß es daran liegt? Volkmar
Nö, der Linker wird vom Compiler-Treiber (avr-gcc) aufgerufen, das ist schon OK. Ohne Debugger finde ich da jetzt auch kein Problem.
Hallo Volkmar, also so wie es bisher gemacht habe, dachte ich, dass er es von selbst link und ich habe immer eine datei a.out bekommen. Ich habe aber jetzt nochmal folgendes gemacht: avr-gcc -g -Os -mmcu=atmega169 -c test2.c dann avr-gcc -g -mmcu=atmega169 -o test2.out test2.o und avr-objcopy -j .text -O ihex test2.out test2.hex Wie ich das sehe ist meine .out Datei in der anderen Methode kleiner gewesen dafür aber der Hex File grösser. Trotz diesem Unterschied hat sich aber daran, was der Controller macht, nichts geändert.
Hi ich hab dein Programm mal mit dem AVRStudio simuliert. Da funktioniert er. Matthias
Hallo Mathias, das habe ich auch gerade gemacht und es sieht wohl so aus, wie es soll - aber was kann denn dann falsch sein ? So richtig ist mir die Sache dann nicht klar. Bei anderen Programmen hatte ich noch nie so ein Problem - nur seit ich Interrupts nutzen will. Logisch ist das nicht, oder ?
Hmpf, was mir jetzt erst auffällt:
> TIMSK0 = (0<<OCIE0A)|(1<<TOIE0);
Du schaltest zwei Interrupts ein (output compare und overflow), aber
ich sehe nur einen Handler (overflow). Damit schießt Dein output
compare ,,in die Luft'' und landet auf einem nichtzugewiesenen
Vektor.
Alle nichtzugewiesenen ISRs machen einen jmp 0.
Ich schreibe doch in das Output Compare eine 0 - also disable. Im Datenblatt steht, dass es mit einer 1 eingeschaltet wird - also so wie ich es gemacht habe, sollte eigentlich der Overflow an sein und der Output Compare aus - oder nicht ? Ich schreib mal schnell nen Handler dazu... ich hoffe, dass ist es :).
Hm,
also ich habe einmal den "OUTPUT_COMPARE0" Handler dazu gemacht, da
hat sich nichts geändert.
Dann habe ich noch den Aufruf
> TIMSK0 = (0<<OCIE0A)|(1<<TOIE0);
zu
TIMSK0 = (1<<TOIEO);
geändert... also fasse ich das Output Compare nicht an.
Leider bleibt alles das gleiche.
Ach was, ich hatte sowieso nur Deine etwas umständlich ausgedrückte Null-Anweisung übersehen (0 << irgendwas). Klar, daß das dann nichts ändert. Nö, ohne Debugger keine Idee mehr. Leider ist der ATmega169 in meinem STK502 (oder wie das Teil heißt) nicht mehr gewillt, mit mir zu reden, so daß ich das auch nicht mal schnell mit einem JTAG-ICE durchspielen kann. (Ich muß mal gucken, ob ich den ATmega noch parallel programmieren kann, seriell reagiert er weder im STK500 noch in einem 08/15 Parallelport-Dongle.)
Hallo (jetzt war die Seite aber lange down...), ich wollte nur kurz sagen, dass ich es gefunden habe und einen Tipp loswerden. Nachdem Jörg das mit dem zusätzlichen InterruptHandler geschrieben hat, dachte ich mir: egal, schreibste einfach für jeden Interrupt mal 'nen Handler. Dann ging es und also habe ich nach und nach die Handler wieder rausgenommen. Zum Schluss hat sich rausgestellt, dass der PIN_CHANGE0 Interrupt geworfen wurde... und natürlich nicht in meinem Code abgefangen. Ich danke für jede Hilfe und vielleicht hilft meine Dummheit ja mal einem anderen :) Niels
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.