Hauptseite Zu yanwittmann.de

Zur Hauptseite

<     6. Timer     >

Hardware >> Microcontroller


Timer sind integrierte Bauteile in den Mikrocontrollern, die in regelmäßigen Abständen hardwaregesteuert um 1 hoch- bzw. runterzählen können, und das unabhängig vom Programmablauf. Hierfür sind einige Register reserviert, so gut wie jeder Mikrocontroller (μC) besitzt solche Register, doch abhängig von der Größe des μC kann deren Anzahl jedoch variieren. Es gibt generell zwei Größen von Timern: 8 und 16 Bit.

Generell sieht der Ablauf eines Timers so aus:

Noch einige Anmerkungen zu den einzelnen Punkten:


Prescaler

Dadurch, dass der Prescaler den Standardwert 0, lässt er keinen Takt durch, was dazu führt, dass der Timer inaktiv ist. Zum Aktivieren muss also ein Vorteiler gesetzt werden. Dies kann man im Register TCCR0 mit den Bits CS00-CS02 (Clock Select) machen.

                                                                                                                                                                                                                                         
CS02CS01CS00Bedeutung
000keine (Timer ist angehalten)
001Vorteiler: 1
010Vorteiler: 8
011Vorteiler: 64
100Vorteiler: 256
101Vorteiler: 1024
110externer Takt von Pin T0, fallende Flanke
111externer Takt von Pin T0, steigende Flanke


Auslöser einstellen

Hierfür wird das Register TIMSK0 verwendet. Es beinhaltet zwei Bits, die für zwei Interrupt-Arten stehen:


Beispiele

Eine komplette Initialisierung eines Timers in Assembler als Beispiel:

ldi r16, (1 << CS00)  ; Prescaler auf 1          
out TCCR0, r16
ldi r16, (1 << TOIE0) ; Overflow
out TIMSK0, r16
Assembler

Ein vollständiges Beispiel mit einem Overflow-Interrupt:

rjmp reset          
.org OVF0addr ; Timer 0 Overflow Vektor-Adresse          
rjmp isrOVF0  ; Wenn ausgelöst, springe zur passenden ISR          
.org INT_VECTORS_SIZE

reset:
ldi r16, (1 << CS00) | (1 << CS01) ; Prescaler auf 64
out TCCR0B, r16
ldi r16, (1 << TOIE0) ; Bei Overflow
out TIMSK0, r16
loop:
rjmp loop

isrOVF0:
  ; ISR-Code
reti
Assembler

Hier noch ein Beispiel, wie ein Timer verwendet werden würde, der durch eine fallende Flanke eines externen Signals hoch zählt und das zudem immer den aktuellen Zählerstand auf PORTB ausgibt, ohne, dass dabei ein Interrupt ausgelöst wird:

rjmp reset          
.org INT_VECTORS_SIZE ; es werden keine Interrupts benutzt, direkt zum Code          

reset:
ldi r16, low(RAMEND)
out SPL, r16
ser r16        ; set register (alles auf 1, also 0xFF)
out DDRB, r16  ; und damit PORTB komplett als Output definieren
ldi r16, 0b110 ; auf fallende Flanke setzen
          ; ^ hierfür hätte man auch Bits CS02 & CS01 setzen können!
out TCCR0B, r16

loop:
in r16, TCNT0  ; laufender Zählerstand
out PORTB, r16 ; auf PORTB ausgeben
rjmp loop
Assembler