Hallo Ihr Wissenden... Ich brauche alle 30 Minuten einen Interrupt auf meinem Attiny2313. Kann mir mal kur jemand sagen, ob ich das mit dem Timer richtig verstehe? Maximale Teilung für den Timer ist 1024. Ergibt bei 4MHz 25,6µs ? Wie bekomme ich jetzt eine halbe Stunde hin ? Das wären decimal 703125 Impulse. Muss ich die jetzt mit verschachtelten schleifen zählen?
Der Timer macht mit dem angegebenen Prescaler alle 25,6us einen Zählschritt. Interrupts gibt es erst beim Überlauf! siehe avrgcc-Tutorial
Das heisst bei Timer 1 kann ich maximal 65535 Impulse zählen und kann dann auf den Interrupt reagieren ? Das würde bedeuten ich müsste Interrupt ca. 107 mal mitzählen und hätte dann meine halbe Stund voll. Stimmt das so ?
Ja, HanneS... hab mich etwas komisch ausgedrückt. Stimmt das , dass ich für T1 dann OCIE1A in TIMSK setzen muss, wenn ich einen Zählwert von 65104 vorgeben möchte ? Wie bekomme ich den Vorgabewert in das Register ?
Wie bitte ??? Könnte das funktionieren ? ;Timer 0 initialisieren ldi Temp1, (1<<CS02)|(1<<CS00);Systemtakt /1024 out TCCR0B, Temp1 ;Timer 1 initialisieren ldi temp1, (1<<CS12)|(1<<CS10) ;Systemtakt /1024 =(0,00256s) out TCCR1B, Temp1 ldi temp1,0b11111110 ;High-byte von 65104 out TCNT1H,temp1 ldi temp1,0b01010000 ;Low-byte von 65104 out TCNT1L,temp1 ;Timer-Interrupt aktivieren ldi Temp1, (1<<TOIE0)|(1<<OCIE1A);Für T0 Overflow- und T1 Vergleichs-Interrupt setzen out TIMSK,Temp1
Tja, nun wissen wir schon mal, dass du in ASM werkelst... Warum du nun beide Timer initialisierst, kann ich nicht nachvollziehen. Wenn du den Überlauf-Int des Timers1 benutzt, solltest du beachten, dass der Timer aufwärts zählt (beim AT90S2313, beim Tiny2313 habe ich jetzt nicht nachgesehen), wenn du also 65104 einstellst, der Timer bei 65536 (=0) den Int auslöst, dann dauert das keine 65104 Zählschritte. Ansonsten solltest du dir mal die Output-Compare-Funktion des Timer1 ansehen. Alternativ: Einen Timer mit einem 1s-Takt klappern lassen und in diesem INT ein paar Register runterzählen, die bei Null auf Startwert gesetzt werden und die von dir gewünschte Aktion auslösen. Achja, RTFM = read The Fine/Fucking Manual Ein Blick ins Datenblatt schadet sicher auch nicht... :) ...
Jo, das mit dem Datenblatt hatte ich vorher schon getan. Ich hatte das so verstanden, dass der Kamerad anfängt bei 0 und dann hochzählt. Dann kommt dieses Vergleichregister / Flag zum Zuge (siehe OCIE1A). Den Timer 0 brauche ich für eine Tastenentprellung.
Ein Timer kann mehrere Dinge erledigen. Timer0 läuft mit einer festen Frequenz (100...250 Hz) durch. In seiner ISR werden die Tasten entprellt. Was hindert dich daran, in dieser ISR eine weitere Variable (16...32 Bit) herunterzuzählen, deren Erreichen von 0 dein Vorhaben aktiviert und die Variable wieder auf Startwert setzt. Damit kannst du alles mit nur einem Timer realisieren. ...
Ok, könnte ich tun. Damit ändert sich aber nichts an dem Problem, dass ich es auch verstehen möchte. Außerdem ist dann die Zeit extrem von der Schleife abhängig. So muss ich "nur" 108 mal eine Schleife durchlaufen, während ich sonst einige mehr brauche. Ausserdem muss ich auch gestehen, dass ich noch nie 32Bit gezählt habe. Da man aber nicht alles auf einmal lernen kann, haqb ich nu mit dem Timer angefangen. :-)
Mein Timer scheint nicht zu zählen. Ich sehe zumindest nichts im AVR Studio an TCNT1 So hab ich den initialisiert: ;Timer 1 initialisieren ldi temp1, (1<<CS12)|(1<<CS10)|(1<<CTC1);Systemtakt /1024 =(0,00256s) & Counter löschen wenn vergleich passt out TCCR1B, Temp1 ldi temp1,0b11111110 ;High-byte von 65104 out OCR1BH,temp1 ldi temp1,0b01010000 ;Low-byte von 65104 out OCR1BL,temp1 ;Timer-Interrupt aktivieren ldi Temp1, (1<<TOIE0)|(1<<OCIE1A);Für T0 Overflow- und T1 Vergleichs-Interrupt setzen out TIMSK,Temp1 Hab ich hier was vergessen ?
Na prima... just in dem Moment wo der Zähler zum Vorgabewert passt, ist das Programm grade in einer Schleife, wo die Interrupts ausgeschaltet sind. Also vergleichen kann man pauschal vergessen, wenn man nicht explizit und ausschließlich auf Interrupts wartet ? Wie soll es dann möglich sein, auf eine Zeitspanne zu warten ? HanneS schrieb dass ich zählen soll aber auch dieser Interrupt kommt dann ja wohl eher unregelmässig.
Warum schaltest du in einer Schleife die Interrupts aus? Der Interrupt kommt mit der Regelmäßigkeit eines Uhrwerks. Wenn deine Schleife natürlich so lange die Interrupts sperrt, dass in der Zeit mehrere auftreten, dann kommt es natürlich zum "Vergessen" von Interrupts. Ein einzelner Interrupt wird sofort nach dem Reaktivieren der Interrupts abgearbeitet. Was Hannes geschrieben hat ist voll i.O., so löst man dein Problem.
Schleifen sind unregelmäßig, Timer-Interrupts nicht! Abgesehen von der leicht variablen Int-response-time, aber das kann man stabilisieren indem man den AVR schlafen schickt. Int deaktivieren macht man eigentlich nur, wenn es absolut erforderlich ist, z.B. beim Schreiben auf EEPROM. Jedenfalls nicht für irgendwelche Schleifen. ...
Nundenn... ich habe mit einem Timer meine Tasten entprell. Um das Ergebnis auszuwerten, ohne wieder andere Tastenwerte dazwischen zu bekommen, muss ich zwischenzeitlich den Timer deaktivieren. Hier ist meine Hauptschleife: Loop: cli mov temp1,key_press andi temp1,0b00000100 ;nur PD2 auswerten cpi temp1,0b00000100 ;wenn's passt, springen brne PC+2 rcall start1 mov temp1,key_press ;nur PD3 auswerten andi temp1,0b00001000 cpi temp1,0b00001000 brne PC+2 rcall start2 sei clr key_press ;Tasten löschen nach Aktion sleep rjmp Loop
Nein, manche müssen nur nebenbei noch Geld verdienen und werden im Gegensatz zum Forum dort auch noch fürs Denken bezahlt!
ich dachte ja nur weil eben noch alles so sonnenklar war... ...by the way... Die Entprellroutine ist von Peter Dannegger, das cli und sei auch :-)
Und wieso muss man dazu den Timer deaktivieren?? Schau dir mal das Programm im Anhang an, das läuft z.B. ausschließlich in der ISR. Und zwar deshalb, weil bis zum nächsten Aufruf der Timer-ISR genügend Takte vergehen, also genügend Rechenzeit bleibt. Aber das ist nicht der Grund, warum ich dir das Beispiel zeige. Das Beispiel zeigt, wie man in der ISR neben der Tastenabfrage noch andere Dinge erledigen kann. Es zeigt weiter, dass man einzelne Bits in Registern auswerten und manipulieren kann, man muss also nicht das Register nach temp kopieren und dann das gewünschte Bit maskieren. Es zeigt aber auch, wie man ein ASM-Programm einigermaßen lesbar gestalten kann. ...
"das cli und sei auch :-)" Das muß auch so sein. Allerdings sollte dazwischen eben kein Interrupt verloren gehen. Ich weiß jetzt nicht, wie lange Deine Funktionen start1 und start2 dauern. Wenn sie länger dauern, mach es doch so: Loop: cli mov temp1,key_press clr key_press ;Tasten löschen nach Aktion sei push temp1 andi temp1,0b00000100 ;nur PD2 auswerten cpi temp1,0b00000100 ;wenn's passt, springen brne PC+2 rcall start1 pop temp1 ;nur PD3 auswerten andi temp1,0b00001000 cpi temp1,0b00001000 brne PC+2 rcall start2 sleep rjmp Loop Peter
Also den Timer nicht zu deaktivieren hat zur Folge, dass die Tasten nicht mehr zuverlässig erkannt werden. ...klingt komisch - ist aber so... Wenn ich Dein Programm richtig gelesen habe, hast Du den gesamten Programmablauf im Timer-Interrupt. Jetzt ist aber doch ein zu langes Programm verantwortlich dafür, dass die Interruptzeit nicht mehr maßgeblich ist (es gibt Warteschleifen). Wenn ich in dieser Timer-Routine dann das Zählen anfange, wird mein Zähler respektive die Vergangene Zeit vom Programmablauf bestimmt. Nicht vom Timer. Innerhalb der Interruptroutine wird der Timer ja wohl kaum die Routine neu starten. Dauert der Programmablauf 40µs ist's vorbei mit Taktzeiten von 25µs. Das soll heissen, wenn ich eine feste Zeitspanne brauche muss ich die Interruptzeit und den Programmablauf zusammenzählen, bevor ich den Zähler meiner Variablen erhöhe. Dann habe ich einen Teiler mit dem man eine Zeitspanne kalkulieren kann. Habe ich das so richtig verstanden? Ok, zur Lesbarkeit sieht Deins schick aus aber ich bin ja noch Anfänger und arbeite daran.
In meinem Beispiel wird die ISR alle 10000 Takte aufgerufen (100Hz). Da keinerlei Warteschleifen vorhanden sind, wird der Durchlauf einer ISR mit Sicherheit beendet sein, ehe der Timer erneut "zuschlägt". In der Mainloop schickt man den AVR besser schlafen, das habe ich aber in dieser Vorab-Version noch nicht gemacht, ist aber inzwischen drin. Auch ich habe die Tastenentprellung von Peter Dannegger benutzt und bedanke mich bei Peter für diesen cleveren Algorithmus. Meine Register haben zwar andere Namen, aber ich verweise grundsätzlich auf den Urheber der Routine. :) ...
Ich glaube ich muss mich mit dem Timer nochmal von Neuem auseinandersetzen. Im Moment versuche ich erneut die Entprellroutine zu verstehen. Wenn der Timerzyklus ausreicht für meine LCD und RS232-Routinen, werde ich den Programmaufbau wohl umbauen. So hat man im Grunde den gleichen Ablauf nur zu festen Zeiten. Wie ist das denn dann mit anderen Interrupts ? Funktionieren die dann noch ? Ich denke da so ans UART.
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.