Einführung
Ein Timer löst ein „internes Ereignis“ aus, welches zu einem Interrupt führt und dem Programmierer somit die Möglichkeit gibt, zu einem bestimmten Zeitpunkt das Hauptprogramm zu unterbrechen, um ein Unterprogramm, die Interrupt Service Routine, auszuführen.
Bitte ließ dir zuerst den Beitrag über die Interrupts durch, da dort wichtige grundlegende Informationen erläutert werden!
Unser Mikrocontroller besitzt 2 Timer:
- Timer
- Bezeichnung: T0
- Port: 3.4
- Einsprungadresse: 000Bh
- Timer
- Bezeichnung: T1
- Port: 3.5
- Einsprungadresse: 001Bh
Anwendung
Timerstartwert errechnen
Im Normalfall wird man dazu aufgefordert, den Timerstartwert selbst zu berechnen. Dazu benötigt man lediglich die Frequenz des Mikrocontrollers und die gewünschte Zeit, nach der ein Interrupt ausgelöst werden soll.
In diesem Fall hat der Mikrocontroller einen Systemtakt von 1 MHz (1*106 Hz) und es soll alle 50 ms ein Interrupt ausgelöst werden.
-
Zeit errechnen, die ein Takt benötigt
→ 1 Takt benötigt 1µs!
2. Wie viele Takte notwendig?
3. Startwert errechnen
Bei einem 16-Bit-Timer sind 216-1 (= 65.535) Takte notwendig bis zum Überlauf. Mit dem Überlauf sind es somit 216 (= 65.536) Takte. Da wir nur 50.000 Takte brauchen, ist kein Multiplikator notwendig.
→ 65.536 Takte – 50.000 Takte = 15.536 Takte
Stackpointer setzen
Dem Stackpointer wird die Adresse 0x80 zugewiesen:
mov SP,#0x80
Timerstartwert setzen
Nun muss man dem Timer den gerade errechneten Startwert zuweisen.
- Dazu wandelt man den Startwert zuerst einmal in eine Hexadezimal-Zahl um:
15.53610 = 3CB016
2. Nun teilt man die Werte und weißt dem Timer ein „Timer High-Byte“ und ein „Timer Low-Byte“ zu.
TH0 enthält das „Timer High-Byte“ und TL0 das „Timer Low-Byte“ des Timers 0.
Die 2 linken Hexadezimal-Zahlen unseres Wertes weisen wir TH0 zu:
mov TH0,#0x3C
Die 2 rechten Hexadezimal-Zahlen unseres Wertes weisen wir TL0 zu:
mov TL0,#0xB0
Timermodus setzen
Unser Mikrocontroller besitzt 4 verschiedene Modi:
M1 | M0 | ||
0 | 0 | Modus 0 | |
0 | 1 | Modus 1 | 16-Bit Timer ohne nachladen |
1 | 0 | Modus 2 | 8-Bit-Timer mit Auto-Reload |
1 | 1 | Modus 3 | 2 Stück 8-Bit-Timer |
Wir verwenden Modus 1, damit wir 50.000 Takte ohne nachladen realisieren können.
mov TMOD,#0x01
Timer freigeben
Als nächstes gibt man den Timer 0 frei:
setb ET0
Zuletzt gibt man „generell“ alle Interrupts frei:
setb EA
Timer starten
Zum starten des Timer 0, setzt man ein Bit bei TR0. Um ihn zu stoppen entfernt man es.
setb TR0 //Timer starten clr TR0 //Timer stoppen
ISR erstellen
Damit der Timer nun auch etwas bewirkt, benötigt man noch eine Interrupt Service Routine (ISR).
cseg at 0x000B //cseg auf die Einsprungsadresse setzen isr: //Label setzen //Irgendwelche Befehle reti //ISR beendet
Nun kann der Timer T0 verwendet werden!
Zusammenfassung
- Timerstartwert errechnen
- Stackpointer setzen
- Timerstartwert setzen
- Timermodus setzen
- Timer freigeben
- Timer starten
Quelltext-Beispiel
Das folgende (kommentierte) Quelltext-Beispiel löst alle 50 ms einen Interrupt durch Timer 0 aus und komplementiert das Bit bei P2.0:
$NOMOD51 //Vordefinitionen vergessen #include <at89c5131.h> //Neue Definitionen einbinden cseg at 0x0000 jmp main //zu Sprungmarke main springen cseg at 0x000B //vordefinierte Einsprungadresse (siehe Einfuehrung) jmp isr //zu Sprungmarke isr springen main: //Sprungmarke main mov SP,#0x80 //Stackpointer auf 0x80 setzen mov TH0,#0x3C //TH0-Startwert setzen mov TL0,#0xB0 //TL0-Startwert setzen mov TMOD,#0x01 //Modus setzen setb ET0 //T0 freischalten setb EA //Alle Interrupts generell freischalten setb TR0 //T0 starten loop: //Endlosschleife nop jmp loop isr: //Sprungmarke isr clr TR0 //Timer stoppen mov TH0,#0x3C //TH0 zuruecksetzen mov TL0,#0xB0 //TL0 zuruecksetzen setb TR0 //Timer starten cpl P2.0 //Bit bei P2.0 komplementieren reti //ISR beendet - zuruekspringen end