Hab mich mal etwas in das Thema Timer eingelesen, aber das scheint mir etwas zu komplex zu sein, um das auf die schnell verstehen zu können. Ich hätte gern nen Timer, der mir ca. jede Minute z.B. ne boolsche Variable auf 1 setzt. Diese frag ich dann in der Hauptprogrammschleife ab und reagier ggf. darauf. Nach was müsst ich da konkret suchen? Oder hat vielleicht jemand nen Code, bzw. nen Link dazu?
>Hab mich mal etwas in das Thema Timer eingelesen, aber das scheint mir >etwas zu komplex zu sein, um das auf die schnell verstehen zu können. Aufgeben zählt nicht! "Zur Not" gibt es noch das Tutorium hier auf der Seite, das man sich ansehen und dazu dann Fragen stellen darf. Sonst würde ich eine Eieruhr am INT-Eingang empfehlen...
Schau doch einfach im AVR-GCC-Tutorial unter Timer und interrupt. Ist ja nur ein wenig rechnen. Eine Echtzeituhr gibts z.B. auch schon fertig von Atmel (AVR134, http://atmel.com/dyn/products/app_notes.asp?family_id=607), dort musst du dann nur noch die Teiler und Interruptfunktion anpassen.
Hallo Jochen, für regelmäßige Zeitraster heist das Schlagwort CTC. Du kannst dem Zähler sagen bis zu welchem Wert er zählen soll und wenn der Wert errecht ist kann er den Zähler automatisch zurücksetzen, einen Interrupt auslösen oder beides. Damit kann man z.B. alle 25 ms in einem Interrupt eine Variable hoch (runter) zählen. Nach 2400 ist eine Minute erreicht, dein Flag kann gesetzt werden und die Variable startet erneut mit zählen. Da Takt unbekannt must du die Werte selber berechnen. Die Genauigkeit ist abhängig vom Takt, Vorteiler und Zählerauflösung. Es gibt Kombinationen die z.B. für genaue ms geeignet sind. gruß hans
Danke, aber mehr als Codeschnipsel kann ich nirgends finden. Daraus wird man nicht schlau und ie Tutorials sind schon bissl dürftig.
> Danke, aber mehr als Codeschnipsel kann ich nirgends finden.
Gewöhn dich daran.
Du wirst nie ein fertiges Programm finden, welches genau das macht was
du willst. Du wirst immer aus Codeschnipseln die für dich relevante
Information extrahieren müssen um diese dann für deinen konkreten Fall
anzuwenden.
Timer sind eigentlich ganz einfach!
So ein Timer ist eine Hardwareeinheit, die still und leise vor sich
hinzählt. Nicht mehr und nicht weniger. Das ist die Basisfunktionalität
auf der alles andere beruht.
Wie schnell macht sie das?
Dazu braucht es einen Taktgeber, der im Normalfall der gleiche Takt ist,
der auch deine restliche CPU antreibt. Also die Systemfrequenz. Da das
aber oftmals einfach zu schnell ist, gibt es den Vorteiler, der den
Systemtakt um einen bestimmten Faktor runterteilt. Ist dein Systemtakt
zb 1Mhz, dann bewirkt ein Vorteiler von 8, dass der Timer mit 125kHz
zählt (125kHz bedeutet in dem Fall: der Timer zählt in einer Sekunde
zumindest theoretisch von 0 bis 124999)
Wann legt so ein Timer los?
Ganz einfach: sobald ein Vorteiler zugewiesen wird (es gibt auch einen
Vorteiler von 1 und es gibt einen Vorteiler von 0, was 'kein Vorteiler'
bedeutet)
Welche Vorteiler es gibt und welche Bits in welchem Register gesetzt
werden müssen um einen auszuwählen, steht im Datenblatt des Prozessors.
Damit kannst du den Timer schon mal starten und stoppen. Vorteiler
ungleich 0 gesetzt -> der Timer zählt. Vorteiler auf 0 -> der Timer
zählt nicht.
Natürlich kann so ein Timer nicht endlos zählen. Als 8 oder 16 Bit
Einheit gibt es natürlich eine Obergrenze bis zu der er kommt. Eine 8
Bit Einheit kann physikalisch bedingt nun mal nicht höher zählen als bis
255. Was macht der Timer dann? Nichts spezielles, es gibt einen Überlauf
und er beginnt wieder bei 0.
Anstelle von 0 bis 124999 zu zählen, zählt der Timer also ständig nur
von 0 bis 255 und generiert dabei laufend Überläufe.
Wieviele denn?
Ganz einfach: Wie oft muss men denn von 0 bis 255 zählen, damit man in
Summe 125000 Zählvorgänge gemacht hat? 125000 / 256 = 488.28125 mal
Der Timer generiert also bei 1Mhz Systemtakt und einem Vorteiler von 8,
genau 488.2815 Überläufe in der Sekunde. Aber abgesehen davon, zählt er
immer noch munter vor sich hin. Immer von 0 bis 255
Jetzt wär das alles ein bischen witzlos, wenn der Timer einfach nur vor
sich hinzählt. Der soll ja auch was machen!
Na, zb. kann der Timer dir ein Signal geben (einen Interrupt), wenn er
bestimmte Zählerstände erreicht hat. Und da kommen jetzt die ganzen
Timer-Modi ins Spiel. Im Grunde ist jeder dieser Modi einfach nur eine
andere Anweisung für den Timer, dass er bei unterschiedlichen
Zählerstanden was machen soll.
Zb. wurden oben schon mal die Überläufe angesprochen. Es gibt einen
Interrupt, den man genau an dieses Überlauf-Ereignis anhängen kann. Wird
dieser Interrupt ausgelöst (weil der Timer einen Überlauf fabriziert
hat), so wird eine spezielle Funktion in deinem Programm aufgerufen, in
der du dann machen kannst was du willst. Und jetzt kommt der Clou! Wir
wissen ja, wie oft diese Funktion aufgerufen wird! Nämlich 488.28125 mal
in der Sekunde. Haben wir ja grade ausgerechnet, wie oft so ein Überlauf
in der Sekunde stattfindet.
Damit hast du aber in deinem Programm eine konstante Zeitbasis, die nur
vom Quarz abhängt und mit der du Dinge ausführen lassen kannst.
Es gibt noch andere Modi. Zb. den CTC Modus. In dem Modus kannst du dem
Timer sagen, er soll nicht bis 255 zählen, sondern gibst ihm eine
Obergrenze deiner Wahl vor. Wenn du ihm als Obergrenze zb. 124 vorgibst,
dann wird der CTC-Interrupt bei 1Mhz und einem Vorteiler von 8 genau
1000 mal in der Sekunde aufgerufen. 1Mhz und Vorteiler 8 bedeutet
wieder, dass in einer Sekunde 125000 Zählvorgänge ablaufen. Und mann
muss 1000 mal von 0 bis 124 zählen, damit man ebenfalls 125000
Zählvorgänge absolviert hat.
Danke schonmal, den Timer hab ich verstanden. Alles was ich bisher hab, ist die Initialisierung:
1 | void timer_init(void) { |
2 | |
3 | OCR1A = 7200; //Vergleichswert auf 1s setzen |
4 | |
5 | TCCR1A = 0x00; //PWM ausgeschaltet |
6 | TCCR1B = (1<<WGM12); //CTC-Modus auswählen |
7 | |
8 | //Compare match interrupt aktivieren
|
9 | // TIMSK = (1<<OCIE1A);
|
10 | |
11 | TCCR1B = (1<<CS12) | (1<<CS10); //Vorteiler auf 1024 stellen |
12 | }
|
Stimmt das so? Brauch ich den Interrupt? Ich müsst es jetz nur noch irgendwie machen, dass alle Sekunde ein Zähler hochgezählt wird? Könnt ich das in der ISR machen? Würde dabei das Hauptprogramm unterbrochen werden? Fragen über Fragen :)
Jochen wrote: > Stimmt das so? Nein. Schau Dir mal an, was Du mit TCCR1B machst. Das kann so nicht funktionieren. Ob die gesetzten Bits stimmen, hab ich jetzt nicht nachgesehen. > Brauch ich den Interrupt? Wenn Du was hochzählen willst, ja. > Ich müsst es jetz nur noch > irgendwie machen, dass alle Sekunde ein Zähler hochgezählt wird? Könnt > ich das in der ISR machen? Ja. > Würde dabei das Hauptprogramm unterbrochen werden? Nun, "Interrupt" heißt ins Deutsche übersetzt "Unterbrechung"... Dein Controller hat nur eine CPU und kann dementsprechend nur eine Sache gleichzeitig machen. Dementsprechend muss das Hauptprogramm wohl unterbrochen werden, wenn zwischendurch etwas anderes gemacht werden soll. Ich empfehle als Lektüre die entsprechenden Abschnitte im AVR-GCC-Tutorial, auch wenn Du es als "dürftig" bezeichnest...
Jetz funktionierts, danke. Das Problem ist auch, dass überall was anders steht. Hab mir jetz überall das beste zusammengesucht :)
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.