www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer Atmega8


Autor: hansmaulwurf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
 interrupt [TIM0_OVF] void timer0_int(void)
    {
    // hier dein Code
    }


Mit welcher Taktfrequenz arbeitest du?

Autor: hansmaulwurf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: hansmaulwurf (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht 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...

...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.