Forum: Mikrocontroller und Digitale Elektronik Timer und Idle-Mode


von Matthias (Gast)


Lesenswert?

Hallo,

also ich verwende einen ATmega8 mit 4MHz und will das er jede Minute 
aufwacht, die Temperatur misst, am LCD ausgibt und wieder in den Idle 
Mode geht. Ich wollte den Idle Mode verwenden, weil bei diesem die Timer 
noch verfügbar sind und der µC auch durch den Timer (Interrupt) wieder 
aufwacht.

So jetzt weiß ich aber nicht wie ich das am besten machen soll, das der 
Timer nur einen (wegen Idle Mode) Interrupt erzeugt (alle 60s).

Mit dem Prescaler (1024) komm ich auf 3906,25 Takte pro Sekunde und 
234375 Takte bei 60s. Das dieser Wert zu groß für ein 8 / 16 Bit 
Register ist ist mir schon klar, nur hab ich im "AVR-GCC-Tutorial/Die 
Timer und Zähler des AVR" das gelesen:
"Im CTC Modus des Timers ist es möglich, anstelle der durch die Hardware 
bedingten Obergrenze des Timers, eine andere Zahl zu benutzen, an der 
der Timer einen Interrupt auslöst".

Dann wollte ich gleich den Timer2 verwenden, aber es erscheint immer 
eine Fehlermeldung beim Simulieren:
stray '\226' in program
expected ';' before numeric constant


Hier der Timer Code dazu:

TCCR2 |= (1<<WGM21);                         // Timer2 --> CTC Modus
TCCR2 |= (1<<CS20) | (1<< CS21) | (1<<CS22);       // Prescaler 1024
OCR2 = 234375–1;            // Timer vorladen (60s)
TIMSK |= (1<< OCIE2);      // Compare Interrupt erlauben


also denke ich das der Wert für das Register doch zu groß ist??
oder kann ich eine Variable hochzählen lassen, ohne Interrupt??

von Oliver (Gast)


Lesenswert?

Matthias schrieb:
> "Im CTC Modus des Timers ist es möglich, anstelle der durch die Hardware
> bedingten Obergrenze des Timers, eine andere Zahl zu benutzen, an der
> der Timer einen Interrupt auslöst".

Dadurch werden die Register aber auch nicht größer. Bei 0xff bzw. 0xffff 
ist Schluß, mehr geht nicht.

Die einzige Lösung ist, einen Softwarezähler zu nutzen. Da wird der AVR 
halt dann innerhalb der Minute ein paar mal aufwachen und addieren 
müssen, aber das macht im Vergleich zu der langen LCD-Ausgabe (fast) 
nichts aus.

Matthias schrieb:
> stray '\226' in program
> expected ';' before numeric constant

Die Fehlermeldung hat aber nichts mit der zu großen Konstante zu tun.
> OCR2 = 234375–1;            // Timer vorladen (60s)
Das - Zeichen ist komisch, das gefällt dem Compiler nicht.

Oliver

von Thomas E. (thomase)


Lesenswert?

Matthias schrieb:
> Ich wollte den Idle Mode verwenden, weil bei diesem die Timer
> noch verfügbar sind

Sind sie nicht. Timer2 ist noch verfügbar. Allerdings wird die CPU-Clock 
abgeschaltet. Sodaß der Timer eine eigene Taktquelle braucht.
Dazu benutzt man einen Uhrenquarz.

Matthias schrieb:
> also denke ich das der Wert für das Register doch zu groß ist??

Das ist ein 8-Bit Register. Das geht von 0 - 255.

Matthias schrieb:
> oder kann ich eine Variable hochzählen lassen, ohne Interrupt??

Nein.

Du kannst aber auch einen Atmega 48/88/168/328 nehmen und den 
Watchdogtimer zum regelmässigen Aufwecken benutzen.

mfg.

von Matthias (Gast)


Lesenswert?

ich benutze noch einen externen Quarz (4MHz). Dieser müsste doch im Idle 
Mode noch funktionieren??


Okay ich hab jetz mal die Zeile:

OCR2 = 234375–1;

in

OCR2 = 234374;

geändert und es kommt kein Fehler mehr?!
Müsste denn nicht ein Fehler wegen der Register Größe kommen??

Naja gut dann werd ichs wohl so programmieren müssen, dass er ein paar 
mal mit Timer2 aufwachen muss...

von (prx) A. K. (prx)


Lesenswert?

Matthias schrieb:

> ich benutze noch einen externen Quarz (4MHz). Dieser müsste doch im Idle
> Mode noch funktionieren??

Aber nicht in den echten Powerdown/save-Modi, die den Hauptoszillator 
abschalten. Für einen zweiten Quarz hat der Mega8 keine Pins. Dazu 
müsstest du auf internen Hauptoszillator gehen und für den Timer2 einen 
32KHz Quarz anschliessen.

Wenn es darum geht, wirklich Strom zu sparen, dann geht es mit dem 
pinkompatiblen ATmega88 einfacher: Watchdog-Interrupt alle 8 Sekunden 
freigeben (der ATmega8 kann nur Watchdog-Reset). Kannst dann voll in den 
Powerdown-Modus gehen.

von Thomas E. (thomase)


Lesenswert?

Matthias schrieb:
> OCR2 = 234374;

Auch wenn es keine Fehlermeldung gibt, passt es da nicht rein.
Die untersten 8 Bit werden da reingeschrieben, der Rest wird 
abgeschnitten.

Matthias schrieb:
> Dieser müsste doch im Idle Mode noch funktionieren??

Nein. Der wird abgeschaltet.

Siehe den Post von A. K. (prx). Der hat es genau auf den Punkt gebracht.

mfg.

von Matthias (Gast)


Lesenswert?

Im Datenblatt steht aber das beim Idle Mode die "Main Clock
Source Enabled" und die "Timer Osc. Enabled (If AS2 bit in ASSR is 
set.)" ist, also auch das Quarz??

von Matthias (Gast)


Lesenswert?

Sry, hab den letzten Post noch nicht gesehen...

von (prx) A. K. (prx)


Lesenswert?

Matthias schrieb:

> Im Datenblatt steht aber das beim Idle Mode die "Main Clock
> Source Enabled" und die "Timer Osc. Enabled (If AS2 bit in ASSR is
> set.)" ist, also auch das Quarz??

Im noch relativ viel Strom fressenden "Idle" Mode, der ausschliesslich 
CPU und Flash abschaltet, kannst du jeden Timer verwenden. Das AS2 Bit 
darf auf dem Mega8 bei einem Hauptoszillator mit Quarz nicht aktiviert 
werden, weil die Pins schon vom Hauptsozillator verbraten sind.

von (prx) A. K. (prx)


Lesenswert?

Apropos Watchdog: Wenn es nur darum geht, einmal die Minute einen 
Messwert anzuzeigen, dann geht das natürlich auch mit dem Mega8. Indem 
der Watchdog-Reset ihn frisch starten lässt. Müsst dann nur dafür 
sorgen, dass die Variable, die aus den 8 Sekunden die Minuten macht, vom 
Watchdog-Reset verschont wird und nur bei Powerup/Brownout-Reset 
initialisiert wird (MCUSR abfragen).

von Oliver (Gast)


Lesenswert?

Matthias schrieb:
> in
> OCR2 = 234374;
> geändert und es kommt kein Fehler mehr?!
>
> Müsste denn nicht ein Fehler wegen der Register Größe kommen??

Nein, man darf ja durchaus Integer unterschiedlicher Größe einander 
zuweisen. Da das aber gerne mal (wie jetzt bei dir) zu ungewollten 
Ergebnissen führt, kommt da eine Warnung.

Oliver

von Matthias (Gast)


Lesenswert?

Okay vielen dank für die antworten...

Ich werd dann einfach in der timer overflow ISR eine variable 
inkrementiern lassen und nach 60s die werte auslesen.

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.