Forum: Compiler & IDEs [Atmega32] Timer, der jede Minute ne Variable schaltet


von Jochen (Gast)


Lesenswert?

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?

von STK500-Besitzer (Gast)


Lesenswert?

>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...

von Timmo H. (masterfx)


Lesenswert?

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.

von hans (Gast)


Lesenswert?

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

von Jochen (Gast)


Lesenswert?

Danke, aber mehr als Codeschnipsel kann ich nirgends finden. Daraus wird 
man nicht schlau und ie Tutorials sind schon bissl dürftig.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Jochen (Gast)


Lesenswert?

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 :)

von Johannes M. (johnny-m)


Lesenswert?

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...

von Jochen (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.