3. Δημιουργία χρονικών καθυστερήσεων με timer

Μπορούμε να αναπτύξουμε μια μέθοδο για την δημιουργία και υπολογισμό χρονικών καθυστερήσεων με χρήση 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