PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pause einfügen mit Timer1



ceekay
25.09.2005, 21:13
hallo,

und zwar komme ich mal wieder nicht weiter.
Ich möchte für eine bestimmte Zeit warten bevor etwas ausgeführt wird.
Ich möchte aber auch keine fertigen Funktionen nutzen.
Also mit Timer0 sieht das ja recht einfach aus. Nur das er nur 8 bit breit ist und selbst bei einem Vorteiler von 1/1024 würde er nach 16,38 ms bei 255 angekommen sein.

und ich möchte so ca. 2-3 sek. warten.

Wäre jemand so nett mal einen Beispielcode zu posten wie das mit timer1 aussehen könnte? wenn möglich auch ein wenig kommentiert.

oder gibts es eine bessere Lösung?

achja: ich benutze den mega32

gruß ceekay

Zentauro
26.09.2005, 02:17
also ich würde da eine schleife in einer schleife programmieren...

kann leider nur c-code für den computer...

for(int a=0;a<100;++a)
{
for(int b=0;b<100;++b)
{
//hier 1ms warten
}
}

ich hoffe du verstehst, was ich meine...


mfg

ceekay
26.09.2005, 17:45
nein nicht wirklich. Ich suche auch einen Code für einen AVR wo timer 1 genutzt wird.

Wäre schön wenn der Code auch gut dokumentiert ist.

gruß ceekay

Zentauro
27.09.2005, 14:10
das was ich damit sagen wollte ist, dass der timer alleine diese wartezeiten nie zusammenbringen wird (bei dem takt!). darum musst du einfach n-mal die zeit des timers vergehen lassen(schleife). kann dir leider wie gesagt nicht mit code helfen, aber vielleicht kann ich dir helfen die sache zu verstehen...

mfg

ceekay
27.09.2005, 14:51
ja ok das ist klar. und für genau sowas suche ich ein gut beschriebenes Beispiel.
Vielen Dank trotzdem.

gruß ceekay

SprinterSB
27.09.2005, 15:44
So was in der Richtung?


#include <avr/io.h>

// CPU-Frequenz
#define F_CPU 4000000
// Anzahl Millisekunden zum warten
#define MSEK 2500

#define OCR1A_VAL F_CPU / 1024 * MSEK / 1000
#if (OCR1A_VAL > 0xffff) || (OCR1A_VAL <= 0)
#error Schlechte Werte für F_CPU / MSEK / PRESCALE
#endif

void wait()
{
// Timer1 anhalten
TCCR1B = 0;

// Setzt TOP für Mode=4
OCR1A = (unsigned short) ((unsigned long) OCR1A_VAL);
TCNT1 = 0;

// OCF1A-Flag löschen
TIFR = _BV(OCF1A);
// Timer1 starten, Mode=4
// TOP=OCR1A, Prescale=1024
TCCR1A = 0;
TCCR1B = _BV(WGM12) |_BV(CS12) | _BV(CS10);

// Warten auf OCF1A-Flag
while (!(TIFR & _BV (OCF1A)))
;
}

Bei 4MHz gehen ca 16 Sekunden.
Die Wartezeit wird nur dann exakt eingehalten, wenn
X = F_CPU / 1024 * MSEK / 1000
eine ganze Zahle ist.
Ansonsten gibt es eine Abweichung von
([X]-X)/X vom gewünschten Wert, bei obigen Werten von -0.0064% bzw -160µs.

ceekay
27.09.2005, 21:44
Vielen Dank SprinterSB!
Funktioniert Prima.
Nur ich würde das jetzt auch gerne verstehen und nachvollziehen können.
Bis zum Begin der funktion wait(); verstehe ich alles. Nur danach leider nicht. wärst du so nett und würdest mir die Funktion Zeile für Zeile erklären?

Vielen Dank im Voraus

SprinterSB
28.09.2005, 16:17
Freut mich, daß der Code geht. Ist nähmlich ungetesteter ad-hoc-Code \:D/

Viel zu erklären gibt's da nicht, da müsste ich das Handbuch abtippen -- was ich mir und dir ersparen will...

Timer1 kann in verschiedenen Modi betrieben werden.

In Mode 4 zählt er hoch und wird bei TOP wieder auf 0 zurückgesetzt (CTC: Clear Timer on Compare match).
Den TOP-Wert bezieht der Timer1 in Mode 4 aus dem OCR1A-Register (OutputCompare Register A).

Timer1 kann mit verschiedenen Taktquellen (Clock Sources) betrieben werden, die über die CS1x (Clock Select) eingestellt werden. Oben sind sie so eingestellt, daß der Takteingang von Timer1 der Prescaler-Ausgang f_CPU/1024 ist. Sind alle CS1x auf 0, dann hält Timer1 an.

Die Fehlerrechnung ist übrigens inkorrekt, weil sie davon ausgeht, daß der Prescaler auf 0 steht beim Timerstart. Für die Praxis hat der zusätzliche Fehler kaum ne Bedeutung. Falls doch, kann man den Prescaler auch resetten.

Darüber hinaus ist es empfehlenswert so vorzugehen, wie es Zentauro gesagt hat. Dadurch muss man nicht ständig an den Timer-Routinen rumfummeln und Prescaler etc anpassen wenn die Wartezeit sich ändert.
Statt dessen macht man eine Wartefunktion für 1ms oder 10ms oder so und läuft solange in einer Schleife, bis die Zeit um ist.