Μπορούμε να αναπτύξουμε μια μέθοδο για την δημιουργία και υπολογισμό χρονικών καθυστερήσεων με χρήση timer στην κατάσταση λειτουργίας Normal και χρησιμοποιώντας τον εσωτερικό κρυσταλλικό ταλαντωτή με συχνότητα XTAL=16MHz
Σύμφωνα με τη μέθοδο φορτώνουμε τον TCNT0 με αρχική τιμή την (0xFF – XX + 1) στο δεκαεξαδικό, έτσι ώστε να είναι (0xFF – XX + 1) x 0,0625μs η χρονική καθυστέρηση που επιδιώκουμε. Διαφορετικά μετατρέπουμε την τιμή XX (δεκαεξαδικός) στον αντίστοιχο δεκαδικό ΝΝΝ. Στη συνέχεια φορτώνουμε τον TCNT0 με την αρχική τιμή 256 – ΝΝΝ για να πάρουμε χρονική καθυστέρηση (256 – ΝΝΝ) x 0,0625μs. Μπορούμε να χρησιμοποιήσουμε το κομπιουτεράκι των Windows για να διευκολυνθούμε με τις απαραίτητες πράξεις.
Παράδειγμα: Βρείτε τη χρονική καθυστέρηση που προκαλείται από τον Timer0 στο ακόλουθο απόσπασμα κώδικα χρησιμοποιώντας και τις δυο μεθόδους της προηγούμενης παραγράφου. Μην λάβετε υπ’ όψη τις καθυστερήσεις από τις εντολές που ορίζουν τον timer.
INITSTACK
LDI R16, (1<<5)
SBI DDRB, 5 ; PB5 as an output
LDI R17, 0
OUT PORTB, R17
BEGIN: RCALL DELAY
EOR R17, R16 ; toggle D5 of R17
OUT PORTB, R17 ; toggle PB5
RJMP BEGIN
DELAY: LDI R20, 0x3E
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
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20 ; stop Timer0
LDI R20, (1<<TOV0) ; R20 = 0x01
OUT TIFR0, R20 ; clear TOV0 flag
RET
Απάντηση: (α) (FF – 3E + 1) = 0xC2 = 194 στο δεκαδικό και 194 x 0,0625μs = 12,125μs
(β) Επειδή TCNT0 = 0x3E = 62 (στο δεκαδικό), έχουμε: 256 – 62 = 194. Αυτό σημαίνει ότι ο timer απαριθμεί από 0x3E έως 0xFF. Με την κύλιση από 0xFF στο 00 έχουμε συνολικό αριθμό 194 κύκλων (μέχρι η σημαία υπερχείλισης γίνει HIGH) και επειδή κάθε κύκλος έχει 0,0625μs διάρκεια, το πλάτος του παλμού είναι 194 x 0,0625μs = 12,125μs
Υπολογίζοντας την τιμή που πρέπει να φορτωθεί στον timer
Υποθέτουμε ότι γνωρίζουμε το ποσό της καθυστέρησης που χρειαζόμαστε και η ερώτηση είναι πως μπορούμε να βρούμε την τιμή που πρέπει να φορτώσουμε στον TCNT0 καταχωρητή. Για να υπολογίσουμε την τιμή που πρέπει να φορτώσουμε στον καταχωρητή TCNT0 ακολουθούμε τα ακόλουθα βήματα:
1] Υπολογίζουμε την περίοδο των παλμών του εσωτερικού ταλαντωτή που τροφοδοτεί τον timer, χρησιμοποιώντας τη σχέση Τclock = 1 / Ftimer όπου Ftimer η συχνότητα του ρολογιού που τροφοδοτεί τον timer. Για παράδειγμα, στην επιλογή no prescaler έχουμε Ftimer = Foscillator To χρονικό διάστημα Tclock δίνει την περίοδο κατά την οποία ο timer αυξάνει κατά ένα.
2] Διαιρούμε την επιθυμητή χρονική καθυστέρηση δια Tclock από όπου προκύπτει ο αριθμός των παλμών ρολογιού που χρειαζόμαστε.
3] Εκτελούμε την αφαίρεση 256-n όπου n η ακέραια τιμή από το βήμα 2.
4] Μετατρέπουμε το αποτέλεσμα του βήματος 3 στο δεκαεξαδικό που δίνει την τιμή xx που είναι ο δεκαεξαδικός που πρέπει να φορτώσουμε στον καταχωρητή TCNT0
5] Θέτουμε TCNT0 = xx
Παράδειγμα: Θεωρούμε ότι XTAL = 16MHz. Γράψτε ένα πρόγραμμα που να παράγει ένα τετραγωνικό σήμα με περίοδο 6,25μs στο pin PORTB.3
Απάντηση: Για την τετραγωνική κυματομορφή έχουμε Τ=6,25μs και πρέπει να δημιουργήσουμε χρονική καθυστέρηση 3,125μs. Επειδή ΧΤΑL=16MHz o counter απαριθμεί κάθε 0,0625μs. Αυτό σημαίνει ότι χρειαζόμαστε 3,125μs/0,0625μs = 50 παλμούς ρολογιού. Έχουμε 256 – 50 = 206 = 0xCE. Επομένως θέτουμε TCNT0 = 0xCE.
INITSTACK ; add its definition from previous example
LDI R16, (1<<3)
SBI DDRB,3 ; PB3 as an output
LDI R17, 0
OUT PORTB, R17
BEGIN: RCALL DELAY
EOR R17, R16 ; toggle D3 of R17
OUT PORTB, R17
RJMP BEGIN
;---------------------Timer0 delay
DELAY: LDI R20, 0xCE
OUT TCNT0, R20 ; load Timer0
LDI R20, 0x00
OUT TCCR0A, R20 ; Normal mode
LDI R20, 0x01
OUT TCCR0B, R20 ; Normal mode, int clk, no prescaler
AGAIN: SBIS TIFR0, TOV0 ; if TOV0 is set skip next instruction
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20 ; stop Timer0
LDI R20, (1<<TOV0)
OUT TIFR0, R20 ; clear TOV0 flag
RET
Παράδειγμα: Θεωρούμε ότι XTAL = 16MHz. Τροποποιήστε το πρόγραμμα του προηγούμενου παραδείγματος για την παραγωγή ενός τετραγωνικού σήματος συχνότητας 32kHz στο pin PORTB.3
Απάντηση: Ακολουθούμε τα ακόλουθα βήματα
(α) T = 1 / F = 1 / 32kHz = 31,25μs η περίοδος του τετραγωνικού σήματος
(β) Το μισό από αυτό είναι ίσο με τα τμήματα high και low του σήματος
(γ) 15,625μs / 0,0625μs = 250 και 256 – 250 = 6
(δ) θέτουμε TCNT0 = 0x06