Forum: Mikrocontroller und Digitale Elektronik Timer Atmega8


von hansmaulwurf (Gast)


Lesenswert?

Hallo und einen schönen guten Tag zusammen...

Ich möchte mit Hilfe eines Timers eine 10 sekündige Warteschleife
programmieren...
[Atmega8, benutzen möchte ich den 16bit Timer]

folgendes habe ich bis jetzt verstanden....bzw. nicht verstanden

//----------------------------------------------------------------------

TIMSK |= _BV(TOIE1); //aktivieren des Überlaufinterrupts von Timer1

--> wozu dient mir der Interrupt ?
irgendwo wird doch eine "1" reingeschrieben, wenn ich bei 2^16 bin ?
wie kann ich diese 1 dann benutzen, um z.b eine Led anzuschalten ?


TCCR1B = _BV(CS12) | _BV(CS10); //Prescaler definieren(aus Datenblatt:
101 cs12,cs11,cs10) = 1024 Prescaler

--> das ist soweit klar

TCNT1 = 55771; //Zählregister vorladen für 10sek.

--> zählt also noch bis 2^16...meiner rechnung nach müssten dann 10 sek.
vorvbei sein !


--> also ich möchte eigentlich jetzt nur nach 10 sekunden etwas
ausführen...um genauer zu sein möchte ich jetzt nicht unbedingt eine led
anschalten, sondern es soll sich ja um eine warteschleife handeln.
Deswegen möcht ich nach 10 sekunden wieder weitermachen mit meinem
programmcode....
wie kann ich das realisieren ?


Vielen dank für eure hilfe

mfg hans

von Karl H. (kbuchegg)


Lesenswert?

Ich geh da jetzt mit gemischten Gefühlen in die Beantwortung
deiner Frage. Der Grund ist der, dass man solche Warteschleifen
eigentlich vermeiden möchte. Der µC soll eigentlich überhaupt
nie auf etwas warten, sondern es entstehen Ereignisse und
diese Ereignisse lösen Aktionen aus.

Eine Systematik die sich in der Praxis gut bewährt, ist
folgende Vorgehensweise:

Es gibt in main() die sog. Hauptschleife. Diese Hauptschleife
überprüft ständig ob ein Ereignis eingetreten ist. Ob
ein Ereignis eingetreten ist, oder nicht, wird durch
globale Variablen angezeigt, die zb. den Wert 0 haben, wenn
das Ereignis nicht eingetreten ist und 1 wenn das Ereignis
eingetreten ist.

Konkret sieht das zb so aus:

uint8_t Abgelaufen10Sek;
uint8_t irgendeinAnderesEreignis;


int main()
{

   .....


   while( 1 ) {

     if( Abgelaufen10Sek == 1) {
       // mache was immer nach der 10 Sekunden Wartezeit
       // passieren soll
       Abgelaufen10Sek = 0;
     }

     if( irgendeinAnderesEreignis ) {

       // Start einen Vorgang. Teil dieses Vorgangs
       // ist es zwischendurch mal 10 Sekunden zu warten
       // also wird hier der erste Teil (vor der Wartezeit)
       // erledigt
       // danach wird ein Timer aktiviert, der die Zeit
       // runterzählt. Hat der Timer die 10 Sekunden
       // überbrückt, so löst er einen Interrupt aus
       // und in der Interruptfunktion wird dann die Variable
       // Abgelaufen10Sek auf 1 gesetzt.
       // Dies sorgt dann dafür, dass der 2-te Teil der
       // Berechnung beim nächsten Durchlauf der while Schleife
       // hier in Angriff genommen wird.

       irgendeinAnderedEreignis = 0;
     }

     if( ( PINC & 0x01 ) = 0x01 ) {
       // löse die Berechnung aus indem irgendeinAnderes
       // auf 1 gesetzt wird. Beim nächsten Durchlauf durch
       // die while Schleife beginnt dann die Kette der
       // Berechnungen
   }
}

Mittels setzen von irgendeinAnderesEreignis auf 1 (zb. durch
das Drücken eines Tasters, unterbrechen einer Lichtschranke,
was auch immer), beginnt der erste Teil der Berechnung. Ist
diese soweit erledigt, dass gewartet werden müsste, so wird
der Timer gestartet. In der Zwischenzeit läuft das Programm
weiterhin brav durch seine while Schleife und erledigt was es
sonst noch so alles zu erledigen gibt.
Wenn der Timer abgelaufen ist, so löst der Timer einen Interrupt
aus, welcher in seiner ISR wiederrum die globale Variable so
setzt, dass beim nächsten Durchlauf durch die while Schleife
der 2te Teil der Berechnung durchgeführt wird.

Auf diese Weise, wartet das Programm nirgends auf irgendetwas
sondern es steht immer Rechenzeit zur Verfügung um in der
'Wartezeit' auch andere Dinge zu tun (zb. Messwerte auslesen,
Anzeigen auf den neuesten Stand bringen, etc ...)


Der springende Punkt um den es eigentlich geht, ist der,
dass man Warteschleifen von vorneherein vermeiden möchte.
Mit obiger grundsätzlicher Struktur ist sowas möglich.

von Max (Gast)


Lesenswert?

Hi Hans,


Wenn der Timer0 deines µC "überläuft" wird
das Programm unterbrochen und eine Interrupt Routine aufgerufen.

in C kann man das folgendermaßen schreiben:
1
 interrupt [TIM0_OVF] void timer0_int(void)
2
    {
3
    // hier dein Code
4
    }


Mit welcher Taktfrequenz arbeitest du?

von hansmaulwurf (Gast)


Lesenswert?

ok..erstmal danke für eure antworten...

Ich arbeite mit dem 16 bit Timer des atmega8 und einer taktfrequenz von 
1MHz.

Ich habe einen Fehler in meiner Beschreibung gemacht...sorry...

1) warum kann ich für ne einfache wartezeit nicht einfach...

#include <util/delay.h>

...

_delay_ms(100);

...

benutzen ?

2) Ich möchte das es folgendermaßen funktioniert:

ES soll ein 10 sek timer laufen.
Wenn ich innerhalb !!dieser 10 sek. keine aktion ausführe, soll das 
Programm irgendwas machen. Wenn ich jedoch innerhalb der 10 sek. eine 
aktion ausführe, soll dann das Programm auch wieder irgenwas anderes 
machen....
hört sich irgendwie dämlich an...soll aber so laufen...



@ Karl heinz Buchegger (kbuchegg)

- Ich fange gerade an mit der Micro-programmierung....
-also ich möchte tatsächlich einfach nur warten....das hat den 
hintergrund dass es sich um eine art Sperre handelt, wenn man etwas 
falsches eingibt...
was ist so schlecht an der routine _delay_ms() ? könnte ich doch 
benutzen oder?
Ja ich gebe dir recht, für umfangreiche Programme wäre dein Vorschlag 
natürlich sehr sinnvoll....

@max

die routine wird also automatisch aufgerufen, wenn deruc überläuft ?



danke für eure hilfe

von hansmaulwurf (Gast)


Lesenswert?

...also nicht, dass ihr verwirrt seit.

Ich brauche einmal eine Routine für das Warten, (evtl mit _delay_ms()) 
und einmal eine Routine, dass ich innerhalb der 10 sek. noch eingaben 
tätigen kann.(siehe punkt2)

danke

von Hannes L. (hannes)


Lesenswert?

Dann programmiere Dir doch einen Timeout-Zähler, den Du bei jeder Aktion 
wieder auf Startwert setzt und der (durch einen Timer-Interrupt 
synchronisiert) heruntergezählt wird, solange er nicht schon (oder noch) 
0 ist. Erreicht er 0, geht es mit der Abarbeitung weiter (über ein 
Job-Flag).

In ASM eine ganz einfache Sache, in C kann ich es nicht formulieren...

...

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.