Timer

(in Arbeit)

zurück zu PIC-Prozessoren , Elektronik , Homepage

Allgemeines zu Timern
Timer 0
Timer 1
Timer 2
Beispiel für Timer0


Allgemeines zu Timern

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)

PIC-Typ
12F629/675
16F84(A)
16F628/627
16F7x
16F87x(A)
Timer0
X
X
X
X
X
Timer1
X
 
X
X
X
Timer2
 
 
X
X
X
nach oben

Timer 0

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.
Der momentane Zählerstand ist im Register TMR0 zugänglich. 

Bei Überlauf wird das Bit T0IF im INTCON Register gesetzt.

Timer0 Blockschaltbild

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

T0SE (Timer0 clock source edge select)
Falls man sich für RA4 als Taktquelle entschieden hat, kann man wählen, bei welcher Flanke an RA4 der Timer einen Schritt weiter zählt. PSA (pre scaler assignment)
Mit diesem Bit kann man bei Bedarf den Vorteiler zuschalten PS2, PS1, PS0 (pre scaler rate select)
Falls man den Vorteiler verwendet, kann man hier sein  Teilverhältnis einstellen Die Zählgeschwindigkeit des Timer0 ist begrenzt auf 1/4 des PIC-Taktes. Ein mit 10 MHz getakteter PIC kann seinen Timer0 also maximal mit 2,5 MHz zählen lassen. Dabei ist es egal, ob der interne Takt oder der Takt von RA4 genommen wird. Diese Begrenzung gilt aber nicht für den Vorteiler. Dieser verträgt 50 MHz (bei symmetrischem Takt). Sein Teilverhältnis muss dann natürlich so hoch gewählt werden, dass am Vorteiler-Ausgang nicht mehr als 1/4 des PIC-Taktes anliegt. Eine praktische Anwendung dafür findet sich im 50-MHz-Frequenzzähler.

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.

nach oben

Timer1
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.

Timer1 Blockschaltbild

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

T1OSCEN (Timer1 oscillator enable control bit)
ist nur von Interesse, wenn TMR1CS = 1
Mit diese Bit aktiviert man den Verstärker zwischen RC1 und RC0 T1CKPS1, T1CKPS0 (input clock prescaler select select)
Hier stellt man das Teilverhältnis des Vorteilers ein T1SYNC (Timer1 external clock input syncronisation control bit)
Mit diese Bit wählt man, ob der Takt  vor dem Zähler mit dem Zyklustakt des PIC (1/4 PIC-Frequenz) syncronisiert wird.
Eine solche Synchronisation ist z.B. nötig, wenn der Timer1 für Capture oder Compare-Funktionen des CCP verwendet werden soll.
Der Syncronisator funktioniert nicht im Sleep-Mode. Wenn der Timer1 auch während Sleep laufen soll (als Uhr oder zum Wecken des PIC via Interrupt), dann muss der Syncronisator abgeschaltet werden. TMR1ON (Timer1 on bit)
Mit diese Bit öffnet und schließt man das Tor vor dem Zähler. TMR1L und TMR1H
Der momentane 16-bittige Zählerstand des Timer1 steht in den beiden 8-Bit-Registern TMR1L (untere 8 Bit) und TMR1H (obere 8 Bit). Da diese beiden Register nur nacheinander ausgelesen werden können, kann es passieren, dass zwischen den beiden Leseoperationen ein Übertrag von den unteren 8-Bit zu den oberen 8-Bit erfolgt. In diesem Fall liest man ein falsches Ergebnis aus.

Beispiel:

auch ein Ändern der Lesereihenfolge bringt keine Verbesserung Folgende Routine bringt immer das korrekte Ergebnis. Falls Interrupts benutzt werden, sollten diese während der Abfrage abgeschaltet werden  (GIE = 0).
 
; Auslesen eines 16-Bit-Wertes aus dem laufenden Timer1*************

TM1_read
        movf    TMR1H, w        ; High Byte auslesen
        movwf   Time_H2         ; High Byte speichern
        movf    TMR1L, w        ; Low  Byte auslesen
        movwf   Time_L2         ; Low  Byte speichern
        movf    TMR1H, w        ; High Byte noch einmal auslesen
        subwf   Time_H2, w      ; 1. uind 2. High-Byte vergleichen
        btfsc   STATUS, Z       ; sind die gleich (kein Überlauf) ?
        goto    TM1_weiter      ; ja: wir sind fertig
        movf    TMR1H, w        ; High Byte noch mal auslesen
        movwf   Time_H2         ;
        movf    TMR1L, w        ; Low  Byte noch mal auslesen
        movwf   Time_L2         ;

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
        clrf    TMR1L           ; Low Byte löschen = demnächst kommt kein Überlauf
        movlw   Time_H2         ; High Byte laden
        movwf   TMR1H, f        ; High Byte schreiben
        movlw   Time_L2         ; Low  Byte laden
        movwf   TMR1L, f        ; Low  Byte schreiben
 

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.

nach oben

Timer2
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.

Timer2 Blockschaltbild

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

TMR2ON (Timer2 on bit)
Mit diese Bit schaltet man den Timer2 ein oder aus T2CKPS1, T2CKPS0 (input clock prescaler select select)
Hier stellt man das Teilverhältnis des Vorteilers ein
nach oben

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
; bis 4 MHz: Power on Timer, kein Watchdog, XT-Oscillator

        __CONFIG        _PWRTE_ON & _WDT_OFF & _XT_OSC

;**************************************************************

; Variablennamen vergeben

w_copy  Equ     0x20            ; Backup für Akkuregister
s_copy  Equ     0x21            ; Backup für Statusregister

;**************************************************************
; los gehts mit dem Programm

        org     0
        goto    Init 

;**************************************************************
; die Interruptserviceroutine

        org     4 
intvec  bcf     INTCON, GIE     ; disable Interrupt

        movwf   w_copy          ; w retten
        swapf   STATUS, w       ; STATUS retten
        movwf   s_copy          ;

        movlw   D'131'          ; 256-125=131 ((1MHz : 32 ): 125 = 250 Hz)
        movwf   TMR0

; Intrrupt servic routine
Int_serv 

;hier folgt die eigentliche Interrupt-Routine, 
;die 250 mal pro Sekunde aufgerufen wird
 

Int_end swapf   s_copy, w       ; STATUS zurück
        movwf   STATUS 
        swapf   w_copy, f       ; w zurück mit flags
        swapf   w_copy, w

        bcf     INTCON, T0IF    ; Interrupt-Flag löschen
        bsf     INTCON, GIE     ; enable Interrupt (macht RETFIE aber auch allein)

        retfie

;**************************************************************

;Initialisierung am Anfang des Programms

Init
; 250 Hz-Timer-Interrupt einstellen
        bsf     STATUS, RP0     ; auf Bank 1 umschalten
        movlw   B'10000100'     ; internen Takt zählen, Vorteiler zum Timer0, 32:1
        movwf   OPTION_REG
        movlw   D'131'          ; 256-125=131 ((1MHz : 32 ): 125 = 250 Hz)
        bcf     STATUS, RP0     ; auf Bank 0 zurückschalten
        movwf   TMR0
        bsf     INTCON, T0IE    ; Timer0 interrupt erlauben
        bsf     INTCON, GIE     ; Interrupt erlauben

loop    goto    loop            ; eine Endlosschleife

;**********************************************************
 

        end

nach oben

zurück zu PIC-Prozessoren , Elektronik , Homepage
Autor: sprut
erstellt: 30.10.2002
letzte Änderung: 14.11.2007