Hey Zusammen! Ich habe Probleme mit dem Timer 0 im Zusammenhang mit AVR Studio. Ich hab versucht ein früheres Programm das mal funktioniert hat (nicht auf AVR Studio programmiert) mittels AVR Studio zu programmieren, da das Alte nicht mehr vorhanden ist. Der Timer 0 zählt auch hoch, aber es wird nie ein Interrupt ausgelöst. Bin schon ziemlich am Verzweifeln! Besten Dank schon mal! Unten mal der Code: #include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> int main (void) { IO_Init (); //Hardware initialisieren wdt_disable() TCCR0A = 0; TCCR0B |= (0<<WGM02)|(1<<CS02) |(0<<CS01) | (0<<CS00); TIMSK0 |= (0<<OCIE0A)|(1<<TOIE0); sei(); while(1) { } return(0); } ISR (TIMER0_OVF_vect) { PORTD |= (1<<PD2); }
Per default geht ein freigegebener Interrupt aber fehlender Interrupthandler zum Resetvector. Peter
besser gesagt, verstehe ich nicht warum der Handler nicht freigegeben sein soll?
Jo schrieb: > besser gesagt, verstehe ich nicht warum der Handler nicht freigegeben > sein soll? Jo schrieb: > (0<<OCIE0A) Ohne ISR (Interrupthandler) keine Freigabe, da dann der Defaultvektor in der Interruptvektortabelle auf den Resetvektor weist.
> PORTD |= (1<<PD2); Du überwachst wahrscheinlich PD2, um festzustellen, ob der Interrupt kommt oder nicht? > IO_Init (); //Hardware initialisieren Wird da auch DDRD für PD2 auf Ausgang gesetzt? > TCCR0B |= (0<<WGM02)|(1<<CS02) |(0<<CS01) | (0<<CS00); Prescaler 256 Angenommen du arbeitest mit der Werkseinstellung (1 MHz interner Takt) 1000000/256/256 = 6,6 ms Hast du ein Messgerät, um das Pintoggeln alle 6,6 ms festzustellen?
Genau ich überwache den Interrupt jetzt vorläufit mal mit dem PD2, den ich auch als Ausgang konfiguriert habe. Ich habe auch ein Oszilloskop dran, aber mindestens einmal sollte die Lammpe ja angehen, dann weiß ich auch ob der Interrupt gekommen ist oder nicht. Bis jetzt geht sie nie an.
Dann setze den Ausgang mal im Hauptprogramm und warte, bis der Interrupt sie ausschaltet. Wenn das Setzen im hauptprogramm nicht funktioniert ist der Interrupt unschuldig. Dann ist vielleicht die Schaltung fehlerhaft!
Wenn der Watchdog mal per Fuse WDTON an war (Inhalt der Fuses?), dann die Fuse disablen (Schaltung stromlos machen nicht vergessen! http://www.mikrocontroller.net/articles/AVR-Tutorial:_Watchdog#WDTON_Fuse_zur.C3.BCcksetzen) Oder wenn der Watchdog per Software aktiv war das wdt_disable() noch früher machen (http://www.mikrocontroller.net/articles/AVR-Tutorial:_Watchdog#WDT_nach_einem_Reset). Was macht das Programm im Simulator?
Der Simulator springt nach dem Abarbeiten des sei() Befehls gleich wieder hoch zum Init()-Befehl. Also bringt er irgendwie RESET?
Geh im Simulator in den Disassembler, nicht in das C-Fenster und kontrolliere im Einzelschritt: Über welchen Vektor macht er den Sprung nach Init. Anhand der Vektornummer über den der Sprung passiert findest du raus, welche ISR fehlt. Die Zuordnung Vektornummer findest du im Datenblatt und in avr/include/avr/iomx8.h.
Kontrolliere in deiner Toolchain, ob es TIMER0_OVF_vect gibt oder ob es in deiner (älteren) Toolchain anders definiert ist. Die Toolchain wirft zwar ggf. eine Warnung bei unbekanntem Namen, aber gelegentlich überliest man die, weil sie in einem anderen Fenster in der IDE erscheint. Hier der "Universal"-Code für neue/alte Toolchain aus dem AVR-GCC-Tutorial:
1 | #ifndef TIMER0_OVF_vect
|
2 | // Für ältere WinAVR Versionen z.B. WinAVR-20071221
|
3 | #define TIMER0_OVF_vect TIMER0_OVF0_vect
|
4 | #endif
|
Kontrolliere auch, ob du unter Projektoptionen als Target auch den ATMEGA168A eingestellt hast. Bei falscher Einstellung liegen die Vektoren u.U. woanders und der Reset ist klar!
-Fuses: hab ich geschaut und auch die Stelle von wdt_disable geändert -Dissambler: hab ich auch versucht und gemerkt, dass er nach sei() in Assembler den Aufruf "RJMP PC-0x0000" bringt. Das heißt der springt ins Nirgendwo oder?
Da dein Programm Syntax Error enthält
1 | int main (void) |
2 | {
|
3 | IO_Init (); //Hardware initialisieren |
4 | wdt_disable() |
geh ich davon aus, dass das wieder mal nicht das richtige Programm ist, welches auf deinem µC läuft. Korrigiert man ihn und ersetzt IO_init() durch DDRD = (1<<PD2); funktioniert dein Programm im SImulator
Jo schrieb: > Assembler den Aufruf "RJMP PC-0x0000" bringt. Das heißt der springt > ins Nirgendwo oder? Nein. Das implementiert die Endlosschleife
1 | while( 1 ) { |
2 | }
|
Nach dem RJMP springt er dann zu 0000001C und dreht da seine Runden und geht dann irgendwann wieder zum Start. Weiß gar nicht ob das wirklich Reset ist Hab im Anhang mal das Programm als zip. Bin die nächste halbe Stunde mal kurz weg, aber dann wieder da. Vielen vielen Dank schon mal für die riesen Hilfe!
Jo schrieb: > Hab im Anhang mal das Programm als zip. Was wird das?
1 | ISR (TIMER0_OVF_vect) |
2 | {
|
3 | PORTD |= (0<<PD2); |
4 | }
|
---> PORTD &= ~(1<<PD2); wenn du das Bit löschen willst, dass du in main gesetzt hast. Und du bist sicher, dass du einen einzelnen Puls am PD2 Pin im Oszi siehst? Tausch das mal gegen
1 | ISR (TIMER0_OVF_vect) |
2 | {
|
3 | PORTD ^= (1<<PD2); |
4 | }
|
dann toggelt das Teil und du hast alle Zeit der Welt Messungen vorzunehmen. Und das
1 | PCMSK0 |= (1<<PCINT0); |
2 | |
3 | ....
|
4 | |
5 | ISR (PCINT2_vect) |
macht dich nicht irgendwie stutzig?
zu ISR (TIMER0_OVF_vect): Der PD2 soll ausgehen als Zeichen, dass der Interrupt ausgelöst wurde Kann genauso auch umgedreht werden. zu ISR (PCINT2_vect): den hätte ich rauslöschen sollen. Der war als Versuch ob überhaupt Interrupts ausgelöst werden können und das hat funktioniertl. Tut aber nicht zur Sache
Jo schrieb: > den hätte ich rauslöschen sollen. Du sollst in erster Linie das Programm posten, mit dem du auch tatsächlich testest! Sonst suchen wir Fehler, die nicht in deinem eigentlichen Programm enthalten sind. Wenn du abspeckst, dann teste das abgespeckte, ob es noch die gleichen Symptome zeigt. Mit dem Posten von extra für das Forum hergerichteten Code, der so nie getestet wurde, kann man sich hier ganz schnell unbeliebt machen.
PORTD |= (1<<PD2) mach, da dann die Lampe gesetzt bleibt. Sie wird ja erst ausgemacht, wenn der Controller neu initialisiert, solange ist sie an. Dann sehe ich ob sie durch den Interrupt mindenstens einmal an bzw. aus gemacht wurde
Es war nicht meine Absicht euch zu verwirren. Ich hab den Code auch vorher getestet, aber es übersehen. Hab einfach schon viel probiert. Habs jetzt nochmal bereinigt. Entschuldigt bitte!
Und mein Programm ist momentan einfach so klein, da ich es selbst aufs wesentliche reduziert hab, da ich den Fehler mit den Timerinterrupts nicht finde.
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.