Allgemeines zu
Timern
Timer 0
Timer 1
Timer 2
Beispiel für
Timer0
Alle Flash-PICs besitzen mindestens
einen
Timer. Größere PICs haben derer sogar drei.
Ein Timer ist nichts anderes als eine
normale Zählschaltung. Sein Eingang kann mit einem I/O-Pin oder
mit
dem internen PIC-Takt verbunden werden. Dann zählt er mit dem
eingespeisten
Takt. Ist der Zähler mit dem PIC-Takt verbunden wird er im
Allgemeinen
als Timer bezeichnet. Ist er mit einem externen I/O-Pin verbunden,
bezeichnet
man ihn auch als Counter.
Jeder Zähler läuft einmal über. Ein 8-Bit Timer kann von 0 bis 255 zählen, ein 16-Bit-Timer kommt bis 65535. Hat der Timer seinen höchsten Zählwert erreicht, und bekommt dann einen weiteren Zählimpuls, dann springt er wieder auf 0 und kann von vorn beginnen. Bei diesem Überlauf gibt der Timer ein Signal aus, das ein bestimmtes Bit in einem Register des PIC setzt. Wenn man dieses Bit abfragt, weiß man also, ob der Timer übergelaufen ist. Das kann man in einem Programm als Zeitbasis nutzen. Außerdem kann beim Überlauf auch ein Interrupt ausgelöst werden. Das erspart das dauernde Abfragen (pollen) des Überlaufbits.
Der momentane Zählerstand des Timers ist nicht geheim, er liegt immer in einem speziellen Register, von wo man ihn auslesen kann. Man kann dieses Register auch beschreiben, und dadurch den Timer auf einen bestimmten Wert setzen, von dem er dann weiterzählt.
PICs besitzen bis zu 3 Timer: (PIC18Fxxx haben bis zu 5 Timer)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Der Timer 0 gehört zur Grundausstattung aller Flash-PICs. Er ist ein 8-Bit-Timer, kann also nur bis 255 zählen.
Seine Zählimpulse
erhält er
entweder über das Pin RA4, oder er wird mit 1/4 des
PIC-Taktes
gespeist. Der ausgewählte Takt kann direkt auf den Zähler
gegeben
werden, oder man verwendet einen Vorteiler, dessen Teilverhältnis
von 1:2 bis zu 1:256 in 8 Stufen eingestellt werden kann.
Der Zähler zählt
vorwärts
von 0 bis 255 und beginnt dann von vorn. Bei Überlauf wird das Bit T0IF im INTCON Register gesetzt. |
Die Programmierung des Timer0 erfolgt im Register OPTION_REG mit den Bits T0SE, T0CS, PSA sowie PS2..0.
OPTION_REG: OPTIONS REGISTER (ADDRESS 81h):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | RBPU | INTEDG | T0CS | T0SE | PSA | PS2 | PS1 | PS0 |
Wert: | x | x | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 |
T0CS (Timer0 clock source select)
Mit diese Bit wählt man die
Taktquelle
des Timer0 aus
Den Vorteiler muss sich der Timer0
mit dem WDT (Watch dog
timer)
teilen. Da ein richtiges Teilen dieser Hardware kaum möglich ist,
muss man sich also entscheiden, ob man den Vorteiler für den
Timer0 oder für den WDT verwenden will.
Wenn man den
Vorteiler für dem
Timer0 verwendet, dann führt jeder schreibende Zugriff auf TMR0
dazu, das der Vorteiler die bereits gezählten Pulse wieder
vergisst. Bei einem Vorteilerverhältnis von 256:1 gehen durch
einen schreibenden Zugriff auf TMR0 also durchschnittlich über 100
Impulse verloren. Das muss man immer dann bedenken, wenn man mit dem
Timer0 hochgenaue Zeitabläufe steurn will ( z.B. in einer Uhr).
Hinweis:
In PICs der Serien PIC18Fxxx
wird ein Timer0 verwendet, der sich auf 16-Bit Breite umschalten
lässt.
Die modernen PIC24, dsPIC...
haben keinen Timer0 mehr.
Der Timer 1 ist ein 16-Bit
Timer, der
seine Zählimpulse entweder vom PIC-Takt oder vom I/O-Pin RC1 bzw.
RC0 erhält.
Der ausgewählte Takt wird durch einen Vorteiler, einen Synchronisator (wenn ausgewählt) und eine Torstufe zum 16-Bit-Zähler geleitet. Der Zähler zählt von 0 (0000h) bis 65535 (FFFFh). Dann läuft er über und beginnt bei 0 von vorn. Beim Überlauf wird das Bit TMR1IF gesetzt, das auch einen Interrupt auslösen kann (wenn aktiviert). Der Zählerstand kann über die beiden Register TMR1L (low-Teil) und TMR1H (High-Teil) ausgelesen und verändert werden. Das CCP-Modul benötigt Timer1 für die Capture- sowie für die Compare-Funktion. Wird eine dieser Funktionen im CCP-Modul aktiviert, steht der Timer1 also nicht mehr frei zur Verfügung. |
Der Eingang RC0/RC1
Das Pins RC0 kann den Timer1 als Input-Pin
mit Pulsen versorgen. Es besteht aber auch die Möglichkeit, das
Pin
RC1 über einen Verstärker zum Pin RC0 zu schalten. dann wird
RC0 automatisch Output-Pin und RC1 dient nun als Takt-Eingang. Sinn des
ganzen ist es, mit RC0, RC1 und dem Verstärker einen Oszillator
aufzubauen
(entspricht dem Oszillator
für
den PIC-Takt im LP-Mode). Dazu werden RC0 und RC1 mit einem
Resonator
(z.B. einem Quarz) verbunden. Dieser wird durch den Verstärker zum
Schwingen angeregt. Diese Schwingung is dann das Timer1 Inputsignal.
Der
Oszillator ist für Frequenzen bis zu maximal 200 kHz ausgelegt.
Wenn an RC0&RC1 ein
32,768kHz-Uhrenquarz
angeschlossen wird, lässt sich mit dem Timer1 ein Zeitnormal
aufbauen.
(Oft benötigt man zur Ablaufsteuerung im Programm eine 'Uhr'.)
Bei einigen neueren Typen wie z.B. 16F87xA
ist der Oszillator für 32,768 kHz optimiert. Dadurch ist die
Funktion
bis hinauf zu 200 kHz nicht mehr garantiert.
Vorteiler
Der Vorteiler des Timer1 ist immer im
Signalpfad der Eingangspulse, beherrscht aber neben 8:1, 4:1 und 2:1
auch
das Teilverhältnis 1:1, wodurch er sich dann nicht störend
auswirkt.
Synchronisator
Der Synchronisator synchronisiert den
Vorteilerausgang mit dem internen Zyklustakt (1/4 des externen
PIC-Taktes).
Der Synchronisator kann, aber muss nicht ausgewählt werden.
Torstufe
Durch die Torstufe kann der Eingang des
Zählers für Impulse gesperrt werden.
Die Programmierung des Timer1 erfolgt im Register T1CON mit den Bits T1CKPS1&0, T1OSCEN, T1SYNC, TMR1CS sowie TMR1ON.
T1CON: TIMER1 CONTROL REGISTER (ADDRESS 10h):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | - | - | T1CKPS1 | T1CKPS0 | T1OSCEN | T1SYNC | TMR1CS | TMR1ON |
Wert: | x | x | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 |
TMR1CS (Timer1 clock source
select)
Mit diese Bit wählt man die
Taktquelle
des Timer1 aus
Beispiel:
; Auslesen eines 16-Bit-Wertes aus
dem laufenden
Timer1*************
TM1_read TM1_weiter |
Alternativ kann man den Timer1 natürlich auch mit TMR1ON=0 vorübergehend anhalten, aber das ist oft nicht gewünscht.
Ein ähnliches Problem ist das
Schreiben
in TMR1H und TMR1L:
; Einschreiben eines 16-Bit-Wertes
in den
laufenden Timer1*************
TM1_write |
Die
Zählgeschwindigkeit
des Timer1 ist im synchronen Mode begrenzt auf 1/4 des PIC-Taktes.
Ein mit 20 MHz getakteter PIC kann seinen Timer1 also maximal mit 5 MHz
zählen lassen. Dabei ist es egal, ob der interne Takt oder der
Takt
von RC0 genommen wird. Diese Begrenzung gilt aber nicht für den
Vorteiler.
Mit einem Vorteilerverhältnis von 8:1 lässt sich also
theoretisch
eine Frequenz von max 40 MHz an RC0 zählen. Der Hersteller
garantiert
in dieser Betriebsart 33 MHz.
Die Funktion des
Timer1 ist im asynchronen Mode nur bis 16 MHz (an RC0) garantiert.
Der 'Timer2 ist vielleicht schon
vom PWM-Modul her
bekannt, dort wird er nämlich zur PWM-Erzeugung benutzt.
Der Timer2 ist ein 8-Bit-Timer mit Vorteiler und Nachteiler. Mit seinen 8-Bit macht er eigentlich nicht viel her, er besitzt aber den Vorteil, dass man einstellen kann, wie weit er zählen soll, bevor er wieder bei Null anfängt. Man kann ihn also so programmieren, dass er z.B. immer von 0 bis 100 Zählt, und dann wieder bei 0 startet. (Bei den anderen Timern lässt sich so etwas nur per Software mit Hilfe eines Interrupts erreichen.) Der Timer2 kann ausschließlich durch den internen PIC-Takt getaktet werden. Dazu wird der PIC-Takt zunächst durch 4 geteilt, um den Zyklustakt zu erhalten. Dieser kann dann noch durch 4 oder durch 16 geteilt werden, bevor er in den 8-Bit Zähler eingespeist wird. Dieser Zähler zählt mit jedem Takt einen Schritt vorwärts. Der Zahlenwert im Zähler kann jederzeit durch das Programm ausgelesen oder verändert werden. Das erfolgt durch Lesen oder Schreiben auf das Register TMR2. |
Der Wert im Timer2 wird durch einen
Vergleicher
ständig mit dem Wert im Register PR2 verglichen. Erreicht
der
Timer2 den Wert in PR2, dann gibt der Vergleicher ein Signal
aus,
das den Timer2 beim nächsten Takt auf 0 setzt.
Dieses Signal setzt über den
Nachteiler
auch das Interrupt-Flag TMR2IF. Da der Nachteiler auf jedes
Teilverhältnis
von 1:1 bis 16:1 eingestellt werden kann, benötigt es 1 bis 16
Durchläufe
von Timer2, bis das Interrupt-Flag gesetzt wird.
Das im Blockschaltbild zu sehende 'TMR2-output'-Signal geht zum CCP-Modul, und kann dort für die PWM-Erzeugung benutzt werden.
Die Programmierung des Timer2 erfolgt im Register T2CON
T2CON: TIMER2 CONTROL REGISTER (ADDRESS 12h):
bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 | |
Name: | - | TOUTPS3 | TOUTPS2 | TOUTPS1 | TOUTPS0 | TMR2ON | T2CKPS1 | T2CKPS0 |
Wert: | x | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 | 0 oder 1 |
TOUTPS3 ... TOUTPS0
(Timer2
Output Postscale Select bits)
Hier stellt man das Teilverhältnis
des Nachteilers ein
Beispiel
für Timer0
Das folgende Beispiel entstammt dem Lernbeispiel
LED-Ziffernanzeige. Hier wird der Timer0 benutzt, um alle 4 ms
einen
Interrupt auszulösen
Der PIC-Takt beträgt 4 MHz. Der
Timer0
wird über den Vorteiler an den internen Takt (4 MHz / 4 = 1 MHz)
angeschlossen.
Der Vorteiler wird auf ein Teilverhältnis von 32:1 eingestellt.
Damit
gibt der Vorteiler alle 32 µs einen Impuls an den Timer0 ab. Nach
125 solchen Impulsen sind 4 ms vorbei. Deshalb wird der Timer0 am
Beginn
(und dann auch in jedem Interrupt) auf den Wert 131 eingestellt.. Nach
125 Impulsen läuft er dann jeweils über.
; Tektquelle: 4 MHz ;************************************************************** ; Includedatei für den 16F84 einbinden #include <P16f84.INC> ; Configuration festlegen
__CONFIG _PWRTE_ON & _WDT_OFF & _XT_OSC ;************************************************************** ; Variablennamen vergeben w_copy
Equ
0x20
; Backup für Akkuregister ;**************************************************************
org
0 ;**************************************************************
org
4
movwf
w_copy
;
w
retten
movlw
D'131'
;
256-125=131
((1MHz
: 32 ): 125 = 250 Hz) ; Intrrupt servic routine
;hier folgt die eigentliche
Interrupt-Routine, Int_end swapf s_copy,
w
; STATUS zurück
bcf
INTCON,
T0IF
;
Interrupt-Flag
löschen retfie ;************************************************************** ;Initialisierung am Anfang des Programms Init loop goto loop ; eine Endlosschleife ;**********************************************************
end |