Teil 2: jetzt mit Reload für kurze Zeiten
=========================================
Die Timer zählen nach dem Überlauf sofort ab 0x0000 weiter. Also muss
man wieder einen Startwert (Reload) einstellen, so dass der Timer nach
einer kürzeren Zeit überläuft. Die Formeln im Quelltext kann man
problemlos mit Konstanten füllen, die Division und Modulo wird dabei
nicht wirklich berechnet, sondern der Compiler fügt die Ergebniswerte in
den Code ein. (anders sieht es für variable Zeiten aus, dazu später
mehr)
1 | TH0 = (65536 - Benoetigte_Zeit)/256; // für Startwert oder Reload
|
2 | TL0 = (65536 - Benoetigte_Zeit)%256; // für Startwert oder Reload
|
Die Benoetigte_Zeit ist ein Wert in Maschinenzyklen (je nach System, oft
aber 1µs). Für eine gewünschte Timer-Zeit von 1ms schreibt man dann also
einfach
1 | TH0 = (65536 - 1000)/256; // 1ms = 1000MZ, davon das High-Byte in TH0
|
2 | TL0 = (65536 - 1000)%256; // das Low-Byte in TL0
|
Da der 8051 bei den Timern 0 und 1 keine getrennten Zähl- und
Reload-Register hat, muss man diesen Wert nach jedem Überlauf möglichst
schnell wieder in die Register schreiben (daher nimmt man da dann meist
Interrupts).
1 | while(1) // Endlosschleife
|
2 | {
|
3 | if (TF0 == 1) // Timer 0 ist überglaufen
|
4 | { TH0 = (65536 - 1000)/256; // 1ms = 1000MZ, Hih-Byte
|
5 | TL0 = (65536 - 1000)%256; // Low-Byte in TL0
|
6 | TF0 = 0; // Flag löschen
|
7 | Ticks++; // sonst braucht man erstmal nix.
|
8 | }
|
9 | // Rest des Programms
|
Bei einer Millisekunde läuft die Variable Ticks bereits nach 65536ms,
also etwa einer Minute über. Wenn man längere Zeiten benötigt, dann
entweder die Ticks alle 10, 20 oder 50ms einstellen oder (in C ja kein
echtes Problem) unsigned long Ticks; verwenden. Damit kannst Du in
ms-Auflösung Zeiten bis 1193 Stunden erzeugen, bevor der Zähler
überläuft... Braucht aber mehr Speicher (auch für die Schaltzeiten!).
Ohne Interrupts kann es aber passieren, dass die Bearbeitung des
restlichen Programms länger als die Timer-Zeit dauert. Dann werden die
Zeiten sehr ungenau. Also erstmal nicht wundern...
Teil 3: Reload mit variablen Zeiten
===================================
Für variable Zeiten (z.B. PWM für Modellbau-Servo mit 1-2ms Impuls und
20ms Periodendauer) darf man die (16Bit) Variablen nicht einfach in die
obige Zeile einsetzen. Dabei wird sonst die Division und die
Modulo-Operation wirklich ausgeführt (die sich ergebenden Zeiten sind
dann für die Tonne...). Hier muss man (am besten eine Phase vorher, wenn
der Timer gerade übergelaufen war) die Variable berechnen.
1 | while(1) // Endlosschleife
|
2 | {
|
3 | if (TF0 == 1) // Timer 0 ist überglaufen
|
4 | { TH0 = (65536 - Pulszeit)/256; // Hih-Byte
|
5 | TL0 = (65536 - Pulszeit)%256; // Low-Byte in TL0
|
6 | TF0 = 0; // Flag löschen
|
7 | Ticks++; // sonst braucht man erstmal nix.
|
8 | Pulszeit = 1000 + 4 * Dip_Schalter; // ergibt 1-2ms
|
9 | }
|
10 | // Rest des Programms
|
tschuessle
Bernhard