Hallo,
ich möchte eine Stoppuhr mit Timer0 programmieren.
Könnte mir jemand sagen, wie oft die Methode "Stoppuhr" angesprungen
wird bzw wie ich das berechnen kann?
Danke!
Anfänger schrieb:
> Hallo,>> ich möchte eine Stoppuhr mit Timer0 programmieren.> Könnte mir jemand sagen, wie oft die Methode "Stoppuhr" angesprungen> wird bzw wie ich das berechnen kann?
Das ist eigentlich sehr einfach, wenn man verstanden hat, was ein Timer
macht und wie er arbeitet.
Der grundsätzliche Aufbau ist so:
CPU-Haupttakt -> Vorteiler -> Timer
Der Haupttakt des Systems (bei dir offenbar 16Mhz) wird durch den
Vorteiler gejagt. Ist der zb auf 16 eingestellt, dann kommt aus dem
Vorteiler ein Takt von 1Mhz raus. Steht der Vorteiler auf 8, dann eben
2Mhz. Bei 256 sind es 16/256 Mhz etc. etc.
Mit diesem Takt wird der Timer gespeist und der zählt mit jedem
Taktschlag vor sich hin
0, 1, 2, 3, 4, 5 ....
Ohne irgendwelche sonstige Beschränkungen würde ein Timer mit einem
Vorteiler von 8 bei 16Mhz Haupttakt also in 1 Sekunde bis 2Millionen
zählen. Ist ja auch logisch: Herz ist ja 1 Schwingung in 1 Sekunde. Hast
du 2 Millionen Schingungen in der Sekunde, dann wird eben bis 2
Millionen gezählt.
Jetzt kann aber ein Timer nicht so hoch zählen.
Timer0 ist ein 8 Bit Timer. Der kann nur bis 255 zählen. Danach geht es
bei 0 weiter. Es ist ein sog. Überlauf (Overflow) entstanden.
Jetzt kann man sich natürlich fragen: Wenn der Timer in 1 Sekunde bis 2
Millionen zählen würde, das aber nicht kann, weil bei 255 (also nach 256
Takten) ein Überlauf entstand; wieviele Überläufe gibt es dann
eigentlich in 1 Sekunde?
Einfach: 2000000 / 256 = 7812.5 Überläufe pro Sekunde.
Du hast dich mit
> On Timer0 Stoppuhr
an diese Überläufe gekoppelt. Bei jedem Überlauf wird die Funktion
Stoppuhr aufgerufen. Daher wird diese Funktion (bei den von mir
gewählten Zahlen) in 1 Sekunde 7812.5 mal aufgerufen.
Jetzt bist du drann: Wie oft wird die Funktion bei DIR aufgerufen?
Timer 0 ist 8 Bit breit. Prescale steht auf 1.
Das heißt: Du mußt die 16Mhz durch 256 teilen. Dann hast Du die
Frequenz,
mit der der Interrupt auftritt. Die Zeit ist dann: T=1/F
Zum Rechnen bin ich jetzt zu faul.
;-)
MfG Paul
@ Anfänger (Gast)
>Könnte mir jemand sagen, wie oft die Methode "Stoppuhr" angesprungen>wird bzw wie ich das berechnen kann?
Mit Hilfe des Datenblatts und der Kenntniss deines CPU-Taktes.
In deinem Fall 16 MHz, Timer 0 hat 8 Bit und läuft damit nach 256 Takten
über und löst den Interrupt aus. Macht 16MHz/256 = 62,5kHz bzw.
16us. Ziemlich schnell, zu schnell. Du musst den Prescaler höher setzen,
damit du auf ca. 1..10ms kommst.
MFG
Falk
Hallo,
vielen Dank, jetzt wird es klarer.
Karl Heinz: bei mir wird also die Methode 16.000.000 mal pro Sekunde
aufgerufen. Ich müsste also, wenn die Stoppuhr zb Millisekunden zählen
soll, den Takt mit dem Prescaler so anpassen, dass der Interrupt 1x pro
ms aufgerufen wird.
Allerdings klappt das nicht so recht. Wenn ich zb den Vorteiler auf 256
stelle, dann würde der Interrupt 62.500 mal pro Sekunde aufgerufen
werden, das entspricht 0,016 ms. Bekommt man da irgendwie einen geraden
Wert hin? Der Prescaler kann ja max auf 1024 eingestellt werden, oder?
Anfänger schrieb:
> Hallo,>> vielen Dank, jetzt wird es klarer.> Karl Heinz: bei mir wird also die Methode 16.000.000 mal pro Sekunde> aufgerufen.
Nein.
Denk nach einmal darüber nach.
Die Methode wird aufgerufen, wenn ein ÜBERLAUF entsteht. Der ensteht
aber nicht bei jedem Timer-Takt sondern genau dann, wenn ....
Anfänger schrieb:
> werden, das entspricht 0,016 ms. Bekommt man da irgendwie einen geraden> Wert hin?
Du kannst ja einfach mal alle vorhandenen Vorteiler durchrechnen :-)
-> Es geht sich mit keinem richtig aus.
Aber du musst ja auch nicht auf Millisekunden.
Wenn du weisst, dass die Funktion 354 mal in der Sekunde aufgerufen
wird, dann brauchst du doch nur in der Funktion eine Variable um 1
hochzählen und wenn diese 354 erreicht hat, dann ist 1 Sekunde vorbei
:-)
Ah ok, es sind 16.000.000 / 256 = 62.500 Aufrufe / Sek.
Wenn ich also den Prescaler auf 256 einstelle, sind es 16.000.000 / 256
/ 256 = 244.14 Aufrufe pro Sekunde. Das entspricht etwa einem Aufruf
jede 4.1ms
Aber wie kommt man nun auf einen geraden Wert? Zb alle 1ms oder 10ms?
Anfänger schrieb:
> Ah ok, es sind 16.000.000 / 256 = 62.500 Aufrufe / Sek.>> Wenn ich also den Prescaler auf 256 einstelle, sind es 16.000.000 / 256> / 256 = 244.14 Aufrufe pro Sekunde. Das entspricht etwa einem Aufruf> jede 4.1ms>> Aber wie kommt man nun auf einen geraden Wert? Zb alle 1ms oder 10ms?
Gar nicht!
Zumindest nicht mit dem einfachen Schema, sich an die Überläufe zu
hängen. (Jetzt weißt du auch, warum der Systemtakt bei reinen
Uhrenanwendungen gerne als eine Potenz von 2 gewählt wird. Dann geht es
sich nämlich aus)
Du brauchst einen Timer der den CTC Mode kann. Dort kannst DU dann
vorgeben, wann ein 'Überlauf' entstehen soll.
Aber eins nach dem anderen. Man kann auch mit geringen Fehlern leben,
solange die Uhr nicht zulange läuft :-)
Und eine gute Übung ist es allemal.
@Anfänger (Gast)
>Ist es so korrekt?
Sieht gut aus.
>Ich habe gelesen, dass man so wenige Berechnungen in die>Interrupt-Routinen packen soll. Ist bei in dem oberen Beispiel schon zu>viel?
Nein, das ist voll OK. Nur ist deine Millisekunde um 24us zu lang, sind
immerhin 2,4% Fehler. Anderen Quarz nutzen oder den CTC-Modus.
MfG
Falk
Hier ist ein Beispiel, wie man einen Sekundentakt erzeugen kann:
'Sekundenimpuls mit Timer 0 erzeugen (Paul Baumann)
$regfile = "m8def.dat" 'ATmega8-Deklarationen
$crystal = 16000000 'Quarz: 16 MHz
Dim Umlauf As Byte
Dim X As Bit
On Timer0 Ontimer0
Config Timer0 = Timer , Prescale = 256 '16Mhz/256 = 62500 Hz
'Timer auf 6 heißt 250
Schritte
'bis Überlauf
Enable Timer0 'Timer erzeugt 250 Hz
Enable Interrupts 'Interrupts global zulassen
Timer0 = 6
Umlauf = 250 'Umlauf zählt die
Interrupts
Config Portd.6 = Output 'LED an Port D6
Portd.6 = 0
X = 0
Do
If Umlauf = 0 Then
Umlauf = 250
If X = 0 Then
Portd.6 = 0
X = 1
Else
Portd.6 = 1
X = 0
End If
End If
Loop
'Interrupt-Routine
Ontimer0:
Timer0 = 6 'Timer sofort neu laden
Decr Umlauf
Return
MfG Paul
Danke Paul.
In dem Zusammenhang fällt mir noch was ein:
Es gibt ja in Bascom den waitms - Befehl.
Wie berechnet der die Dauer? Wird da auch ein Timer genutzt?
Nein. Das geht anders. Man nimmt zwar den Uebrlauf, zaehlt aber nicht
von Null weg. Dh, im Intterrupt setzt man den Wert des Zaehlers :
Interrupt Timer0Overflow;
{
Timer0Count:=155;
}
Ja, das müßte so hinhauen. Aber: Denk dran, -wir haben es mit Elektronik
zu tun. Da treten Effekte auf, die allen physikalischen Gesetzen
widersprechen...
Grins
Paul