6. Προγραμματίζοντας τον Timer2

Όπως φαίνεται στο ακόλουθο σχήμα ο Timer2 είναι ένας 8-bit timer. Επομένως δουλεύει όπως ο Timer0.

Υπάρχουν τρεις διαφορές μεταξύ των Timer0 και Timer2:

1] O Timer2 μπορεί να χρησιμοποιηθεί σαν απαριθμητής πραγματικού χρόνου. Για να γίνει αυτό θα πρέπει να συνδέσουμε ένα κρύσταλλο συχνότητας 32,768kHz στους ακροδέκτες TOSC1 και TOSC2 του μικροελεγκτή AVR και να θέσουμε σε 1 το bit AS2

2] Οι καταχωρητές TCNT2, TCCR2A και TCCR2B είναι τοποθετημένοι στην extended I/O memory. Επομένως μπορούν να προσπελαστούν με τις εντολές STS και LDS

3] Στον Timer0 όταν τα CS02-CS00 έχουν τιμές 110 ή 111 ο Timer0 απαριθμεί τα εξωτερικά γεγονότα. Στον Timer2 ο πολυπλέκτης επιλέγει μεταξύ διαφορετικών διαιρέσεων του σήματος ρολογιού. Με άλλα λόγια, για τις ίδιες τιμές των CS bits έχουμε διαφορετικές λειτουργίες των Timer0 και Timer2.

Παράδειγμα: Βρες την τιμή που πρέπει να έχει ο TCCR2B όταν θέλουμε να προγραμματίσουμε τον Timer2 σε λειτουργία Normal mode με prescaler=64 χρησιμοποιώντας το εσωτερικό ρολόι για πηγή σήματος χρονισμού.

Απάντηση: Από τα παραπάνω σχήματα για XTAL clock source και prescaler = 64
WGM22 = WGM21 = WGM20 = 0 και CS22 = 1, CS21 = 0, CS20 = 0
Επομένως TCCR2A = 0000 0000 και TCCR2B = 0000 0100

Παράδειγμα Χρησιμοποιώντας prescaler=64 γράψε ένα πρόγραμμα που να παράγει χρονική καθυστέρηση ίση με 960μs. Θεωρήστε XTAL=16MHz

Απάντηση: Ο Timer2 τροφοδοτείται με σήμα ρολογιού συχνότητας ίση με 16ΜHz/64=250kHz. Η περίοδος του σήματος αυτού είναι 1/250kHz=4μs. Επομένως η τιμή του Timer είναι 960μs/4μs=240.

;------------- Time2 Delay
DELAY:  LDI  R20, -240    ;  R20 = 0x10
        STS  TCNT2, R20   ;  load Timer2
        LDI  R20, 0x00
        STS  TCCR2A, R20
        LDI  R20, 0x04
        STS  TCCR2B, R20  ; Timer2, Normal mode, int clk, prescaler = 64
AGAIN:  SBIS TIFR2, TOV2  ; if TOV2 is set skip next instruction
        RJMP AGAIN
        LDI  R20, 0x00
        STS  TCCR2B, R20  ;  stop  Timer2
        LDI  R20, 1<<TOV2
        OUT  TIFR2, R20   ;  clear TOV2 flag
        RET

Παράδειγμα: Χρησιμοποιώντας την κατάσταση λειτουργίας CTC, γράψτε ένα πρόγραμμα που να παράγει μια χρονική καθυστέρηση 4ms. Θεωρήστε XTAL=16MHz.

Απάντηση: Για XTAL=16MHz έχουμε διάφορες εξόδους από τον prescaler ανάλογα με την τιμή του.

Prescaler TimerClock             TimerPeriod         TimerValue
None      16MHz                  1/16MHz=0,0625μs    4ms/0,0625μs=64k 
8         16MHz/8=2MHz           1/2MHz=0,5μs        4ms/0,5μs=8000
32        16MHz/32=500kHz        1/500kHz=2μs        4ms/2μs=2000
64        16MHz/64=250kHz        1/250kHz=4μs        4ms/4μs=1000  
128       16MHz/128=125kHz       1/125kHz=8μs        4ms/8μs=500 
256       16MHz/256=62,5kHz      1/62,5kHz=16μs      4ms/16μs=250
1024      16MHz/1024=15,625kHz   1/15,625kHz=64μs    4ms/64μs=62,5

Από τους παραπάνω υπολογισμούς μπορούμε να χρησιμοποιήσουμε την επιλογή Prescaler=256 ή Prescaler=1024. Θα πρέπει εδώ να χρησιμοποιήσουμε την επιλογή Prescaler=256 αφού δεν μπορούμε να χρησιμοποιήσουμε τιμές με δεκαδικά ψηφία. Για καθυστέρηση 250 κύκλων ρολογιού θα πρέπει να φορτώσουμε τον OCR2 με την τιμή 250-1=249

Για κατάσταση λειτουργίας CTC θα πρέπει: WGM22 = 0 , WGM21 = 1 , WGM20 = 0
Για prescaler = 256 θα πρέπει: CS22 = 1 , CS21 = 1 , CS20 = 0
Με αυτές τις παραμέτρους έχουμε για τους καταχωρητές: TCCR2A=0000 0010 και TCCR2B=0000 0110

;-----------------Timer2 Delay
DELAY:  LDI R20, 0
        STS TCNT2, R20     ; TCNT2 = 0
        LDI R20, 249
        STS OCR2A, R20
        LDI R20, (1<<WGM21)
        STS TCCR2A, R20
        LDI R20, 0x06
        STS TCCR2B, R20    ; CTC mode, prescaler = 256
AGAIN:  SBIS TIFR2, OCF2A  ; if OCF2A is set skip next inst.
        RJMP AGAIN
        LDI R20, 0x00
        STS TCCR2B, R20    ; stop Timer2
        LDI R20, 1<<OCF2A
        OUT TIFR2, R20
        RET