Timer verwenden als Wait Funktion
Hallo,
ich hab hier schon viele Threads die zum Thema Timer und Warteschleifen durchgelesen.
Ich blick aber eines nicht: Ich schreib irgendein Programm. Nun komm ich an einen Punkt, z. B. Tastendruck o.ä. und ab jetzt will ich eine gewisse Zeitspanne messen. Wie geht dass? Wenn ich den Timer am Anfang des Programms anstoße und bis zu einem gewissen Punkt laufen lasse, dann kommt der Interrupt. Wie lese ich den Interrupt jetzt aus? (ich hab in der ISR programmiert, dass immer ein PIN seinen Zustand ändert, aber dass will ich ja eigentlich nicht, ich will es von meiner main aus starten...) Und zweitens läuft der Timer ja immer weiter. Wenn ich in einer Endlosschleife bin, wird die Zeitspanne ja sehr ungenau, da der Timer ja dann nicht mehr bei 0 los läuft, sondern bei irgendwas........... Ich wollte mir eine Funktion (soe wie _delay_ms) bauen, die ich in meiner main quasi immer dann aufrufe wenn ich eine bestimmte Zeit brauche ](*,) . Und mein ganzes Programm so aufzubauen dass ich genaue Timestamps hab will ich auch nicht. Ich bin am verzweifeln.
Kann mir irgend jemand erklären wie der ganze Mist funktioniert? ](*,) ](*,) ](*,)
LG Anna
Re: Timer verwenden als Wait Funktion
Hei beginner 1101,
Zitat:
Zitat von beginner1101
... Thema Timer und Warteschleifen ... z. B. Tastendruck o.ä. und ab jetzt will ich eine gewisse Zeitspanne messen. Wie geht dass? ...
Es gibt wie immer mehrere Möglichkeiten. Ich weiß nicht welchen Controller Du verwendest, ich hab hier mal EINE Möglichkeit für ´nen mega168 (war grad zur Hand), so wie sie mir grad einfällt:
Ich schreib mir zwei Routinen. Eine Initialisierung des Timers (Interrupt bei Compare Match A - es wird KEIN Pin geschaltet). Dazu eine ISR (Interrupt Service Routine) - die mir einen Wert, hier genannt Izeit_1 (uint16 - geht also bis ungefähr 65000) hochzählt von 0 bis 60 000. Bei 60000 wird Izeit_1 wieder auf 0 gesetzt, damit ist kein Überlauf möglich. Die Routinen sind hier:
Code:
/* ============================================================================== */
/* === Initialisierung fuer Timer2 mega168 ===================================== */
void TC2TMR_init(void) // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs
{
TCCR2A |= (1<<WGM21); // Timer im CTC-Mode, Top=OCR2A doc S 157
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 158
OCR2A = 125; // Preset 125 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
}
/* ============================================================================== */
/* ============================================================================== */
/* === Nicht unterbrechbare ISR für timer2 ===================================== */
/* Routine zählt hoch im Takt 20 kHz = 50 µs. */
ISR(TIMER2_COMPA_vect) // Vektor 7
{
if (Izeit_1 < 60000) //Timer bis 60 000 - 3 sec Datenerfassung möglich
Izeit_1 ++; // war: alle drei Sekunden wird 60000 erreicht
// und Izeit_1 bleibt in der uint16-Grenze
else
{
Izeit_1 = 0; // ansonsten: Rückstellen auf Null
PORTC ^= (1<<PC5); // Zur Anzeige gLED am PC5/SCL toggeln
}
}
/* ============================================================================== */
Soweit meine Vorbereitungen.
Nun kommt (D)ein Tastendruck. Also setze ich im main erstmal cli(); - damit ich gefahrlos die Variable Izeit_1 manipulieren kann - und setze Izeit_1 im main auf 0. Danach natürlich wieder sei();.
Nun kannste jeden beliebigen Wert mit der Genauigkeit meines 50µs-Zeittaktes bis fast 60 000 - das wären 6 Sekunden - abfragen und danach weitergehen im Ablauf.
Dazu würde ich nach dem Tastendruck und nach dem Setzen von Izeit_1 ein Schleife schreiben : cli(); Abfrage ob Izeit_1 > als Wartezeit ist; sei(); und danach fortfahren mit dem Ablauf.
Meine Initialisierungsroutine ist auf Zeiteinheiten von 50 µs abgestimmt (bei m-einen 20 MHz-Quarzen). Du kannstmusstsollst die Initialisierung des Timers auf Deine Bedürfnisse abstimmen. Den Pin auf PC5 toggeln wäre eine Testmöglichkeit - im normalen Leben sollst Du so eine Zeile löschen oder auskommentieren.
Dies ist nur EINE Möglichkeit. Ist die verständlich?
Natürlich ist es auch möglich den Timer für eher kurze Zeiten direkt zu schalten und in der ISR ein Flag zu setzen, das im Main abgefragt wird. Wie gesagt - es führen viele Code-Wege nach Rom.
Viel Erfolg