Ο Timer0 είναι ένας 8-bit χρονιστής στον ATmega328, επομένως και ο καταχωρητής TCNT0 είναι 8-bit όπως φαίνεται στο ακόλουθο σχήμα:
TCCR0A και TCCR0B (Timer / Counter Control Register)
Οι TCCR0A και TCCR0B είναι 8bit καταχωρητές που χρησιμοποιούνται για τον έλεγχο του Timer0. Τα bits για τους TCCR0A και TCCR0B φαίνονται στα ακόλουθα σχήματα.
CS02:CS00 (Timer0 clock source)
Τα bits CS02:CS00 στον καταχωρητή TCCR0 χρησιμοποιούνται για την επιλογή της πηγής παλμών ρολογιού. Εάν CS02:CS00 = 000 τότε ο counter σταματά την απαρίθμηση. Εάν οι CS02:CS00 έχουν τιμές μεταξύ 001 και 101 ο εσωτερικός ταλαντωτής χρησιμοποιείται για την παροχή παλμών και ο timer/counter λειτουργεί σαν timer. Σε αυτή την περίπτωση οι timers χρησιμοποιούνται κυρίως για την παραγωγή χρονικών καθυστερήσεων. Εάν οι CS02:CS00 είναι 110 ή 111 η εξωτερική πηγή παλμών ρολογιού χρησιμοποιείται και σε αυτή την περίπτωση έχουμε έναν counter.
WGM02:00
Ο Timer0 μπορεί να λειτουργήσει σε τέσσερις διαφορετικές καταστάσεις: Normal, phase correct, PWM, CTC και Fast PWM. Τα bits WGM00, WGM01 και WGM02 μπορούν να χρησιμοποιηθούν για την επιλογή μιας από αυτές τις καταστάσεις.
Παράδειγμα: Βρες τις τιμές που πρέπει να βάλουμε στους TCCR0A και TCCR0B εάν θέλουμε να προγραματίσουμε τον Timer0 στην κατάσταση Normal χωρίς prescaler. Χρησιμοποίησε τον κρυσταλλικό ταλαντωτή του AVR σαν πηγή παλμών ρολογιού.
Απάντηση: Για επιλογή χωρίς prescaler θέτουμε CS02-CS00 = 001 και για να επιλέγουμε την κατάσταση Normal θέτουμε WGM02-WGM00 = 000
TIFR0 (Timer/counter Interrupt Flag Register)
Κάθε timer έχει ένα καταχωρητή TIFRn ο οποίος περιέχει τις σημαίες του αντίστοιχου timer. Το παρακάτω σχήμα δείχνει τον καταχωρητή TIFR0 ο οποίος αντιστοιχεί στον Timer0
TOV0 (Timer0 Overflow)
Η σημαία TOV0 τίθεται σε 1 όταν ο counter υπερχειλίζει. Όπως θα δούμε παρακάτω, όταν ο timer κυλίεται από την τιμή $FF στην 00, η σημαία TOV0 τίθεται σε 1 και παραμένει σε αυτή την τιμή μέχρι να μηδενιστεί από το λογισμικό.
Το παράξενο με αυτή τη σημαία είναι ότι για τον μηδενισμό της χρειάζεται να γράψουμε την τιμή 1 σε αυτή. Πράγματι αυτός ο κανόνας εφαρμόζεται σε όλες τις σημαίες του μικροελεγκτή AVR. Στον AVR όταν θέλουμε να μηδενίσουμε μια συγκεκριμένη σημαία του καταχωρητή τότε γράφουμε την τιμή 1 σε αυτή και 0 στα άλλα bits. Για παράδειγμα, το ακόλουθο απόσπασμα κώδικα μηδενίζει τη σημαία TOV0
LDI R20, 0x01
OUT TIFR0, R20 ; TIFR0 = 0b00000001
Normal κατάσταση λειτουργίας
Σε αυτή την κατάσταση, τα περιεχόμενα του timer/counter αυξάνονται με κάθε παλμό ρολογιού. Απαριθμεί προς τα πάνω μέχρι να φτάσει στην μέγιστη τιμή της 0xFF. Όταν κυλίεται από την τιμή 0xFF στην 0x00 θέτει σε ένα το bit της σημαίας που ονομάζεται TOV0 (Timer Overflow).
Βήματα προγραμματισμού του Timer0 στην κατάσταση Normal
Για να παράγουμε χρονικές καθυστερήσεις χρησιμοποιούμε τον Timer0 στην κατάσταση λειτουργίας Normal. Τα ακόλουθα βήματα πρέπει να ακολουθηθούν:
1] Φόρτωσε τον καταχωρητή TCNT0 με την κατάλληλη αρχική τιμή.
2] Φόρτωσε τις τιμές στους καταχωρητές TCCR0A και TCCR0B τέτοιες ώστε να έχουμε Normal λειτουργία και τον κατάλληλο prescaler να οδηγεί τον counter. Όταν επιλέξεις την επιθυμητή πηγή ρολογιού ο timer/counter αρχίζει να απαριθμεί και κάθε παλμός προκαλεί την αύξηση των περιεχομένων του timer/counter κατά 1.
3] Συνέχιζε να παρακολουθείς της σημαία TOV0 για να δεις πότε θα τεθεί σε 1. Βγες έξω από τον βρόγχο μόλις η TOV0 γίνει 1.
4] Σταμάτησε την απαρίθμηση με αποσύνδεση της πηγής ρολογιού, χρησιμοποιώντας τις ακόλουθες εντολές:
LDI R20, 0x00
OUT TCCR0B, R20 ; timer stopped, mode = Normal
5] Μηδένισε τη σημαία TOV0 για την επόμενη επανάληψη
6] Πήγαινε πίσω στο βήμα 1 για να φορτώσεις τον TCNT0 ξανά
Παράδειγμα: Στο επόμενο πρόγραμμα, δημιουργούμε ένα τετραγωνικό σήμα με 50% duty cycle (με ίσα τμήματα high και low) στο PORTB.5 bit. Ο Timer0 χρησιμοποιείται για την παραγωγή της χρονικής καθυστέρησης. Ανάλυσε το πρόγραμμα.
.MACRO INITSTACK
LDI R20, HIGH(RAMEND)
OUT SPH, R20
LDI R20, LOW(RAMEND)
OUT SPL, R20
.ENDMACRO
INITSTACK
LDI R16, 1<<5 ; R16 = 0x20
SBI DDRB, 5 ; PB5 as an output
LDI R17, 0
OUT PORTB, R17 ; clear PORTB
BEGIN: RCALL DELAY ; call timer delay
EOR R17, R16 ; toggle D5 of R17 by Ex-Oring with 1
OUT PORTB, R17 ; toggle PB5
RJMP BEGIN
;---------- Time0 delay
DELAY: LDI R20, 0xF2 ; R20 = 0xF2
OUT TCNT0, R20 ; load timer0
LDI R20, 0x00
OUT TCCR0A, R20 ; Normal mode
LDI R20, 0x01
OUT TCCR0B, R20 ; Normal mode, internal clock, no prescaler
AGAIN: SBIS TIFR0, TOV0 ; if TOV0 is set skip next instruction
RJUMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20 ; stop Timer0
LDI R20, (1<<TOV0)
OUT TIFR0, R20 ; clear TOV0 flag by writing a 1 to TIFR0
RET
Το προηγούμενο πρόγραμμα αποτελείται από τα εξής βήματα:
1] Η τιμή 0xF2 φορτώνεται στον TCNT0
2] Οι καταχωρητές TCCR0A και TCCR0B φορτώνονται και ο Timer0 ξεκινά.
3] Ο Timer0 απαριθμεί προς τα πάνω με κάθε παλμό ρολογιού που παρέχεται από κρυσταλλικό ταλαντωτή. Καθώς ο timer μετρά πηγαίνει από τις καταστάσεις F3, F4, F5 κ.τ.λ. μέχρι να φτάσει στην τιμή 0xFF. Με ένα επιπλέον παλμό παίρνει την τιμή 0 θέτοντας τη σημαία TOV0 σε1. Σε αυτό το σημείο η εκτέλεση της εντολής “SBIS TIFR0, TOV0” παρακάμπτει την εντολή “RJMP AGAIN”
4] Ο Timer0 σταματά την απαρίθμηση
5] Η σημαία TOV0 μηδενίζεται.
Παράδειγμα: Για το προηγούμενο παράδειγμα υπολογίστε την χρονική καθυστέρηση που προκαλεί ο timer. Θεωρείστε ότι XTAL = 16MHz
Απάντηση: Έχουμε 16MHz σαν την συχνότητα ρολογιού του timer. Σαν αποτέλεσμα έχουμε ότι κάθε παλμος ρολογιού έχει περίοδο T = 1/16MHz = 0,0625μs. Με άλλα λόγια ο Timer0 απαριθμεί για κάθε 0,0625μs οπότε η χρονική καθυστέρηση = σύνολο παλμών Χ 0,0625μs.
Ο αριθμός των παλμών μέχρι την υπερχείλιση είναι 0xFF – 0xF2 = 0x0D (13 στο δεκαδικό). Ωστόσο προσθέτουμε 1 στο 13 διότι χρειαζόμαστε έξτρα παλμό για την υπερχείλιση από 0xFF στο 0x00 για την ύψωση της σημαίας. Αυτό δίνει 14Χ0,0625μs για το μισό της κυματομορφής.
Παράδειγμα: Για το προηγούμενο παράδειγμα υπολογίστε τη συχνότητα του τετραγωνικού σήματος που παράγεται στο pin PORTB.5 Θεωρείστε XTAL = 16MHz
Απάντηση: Για να πάρουμε μεγαλύτερη ακρίβεια πρέπει να λάβουμε υπόψη τους κύκλους ρολογιού που οφείλονται στις εντολές του προγράμματος.
Cycles
LDI R16, 1<<5
SBI DDRB,5
LDI R17, 0
OUT PORTB, R17
BEGIN: RCALL DELAY 3
EOR R17, R16 1
OUT PORTB, R17 1
RJMP BEGIN 2
DELAY: LDI R20, 0xF2 1
OUT TCNT0, R20 1
LDI R20, 0x00 1
OUT TCCR0A, R20 1
LDI R20, 0x01 1
OUT TCCR0B, R20 1
AGAIN: SBIS TIFR0, TOV0 1 / 2
RJMP AGAIN 2
LDI R20, 0x00 1
OUT TCCR0B, R20 1
LDI R20, (1<<TOV0) 1
OUT TIFR0, R20 1
RET 4
--------
25
Επομένως η περίοδος της τετραγωνικής κυματομορφής είναι T = 2 x (14 + 25) x 0,0625μs = 4,875μs και η συχνότητα της είναι F = 1/T = 205,128kHz