Σε αυτή την ενότητα θα μάθουμε για τον καταχωρητή OCR0A, ο οποίος συνοδεύει τον Timer0. Ο OCR0A καταχωρητής χρησιμοποιείται στην κατάσταση λειτουργίας CTC. Όπως στην κατάσταση λειτουργίας Normal έτσι και στην κατάσταση CTC o timer αυξάνει με τους κύκλους ρολογιού. Στη λειτουργία CTC ο timer απαριθμεί προς τα πάνω μέχρι η τιμή του TCNT0 να γίνει ίση με εκείνη του καταχωρητή OCR0A (compare match occurs). Στον επόμενο κύκλο ρολογιού η τιμή του timer θα μηδενιστεί ενώ ταυτόχρονα η σημαία OCF0A θα τεθεί σε 1. Η σημαία OCF0A βρίσκεται στον καταχωρητή TIFR0. Δες την ακόλουθη εικόνα και μελέτησε τα ακόλουθα παραδείγματα.

Παράδειγμα: Στο επόμενο πρόγραμμα, παράγουμε ένα τετραγωνικό σήμα με 50% duty cycle (με ίσα τμήματα high και low) στο PORTB.3 bit. Χρησιμοποιείται ο Timer0 για την παραγωγή της χρονικής καθυστέρησης. Μελετήστε το πρόγραμμα.
INITSTACK
LDI R16, (1<<3)
SBI DDRB, 3 ; PB3 as an output
LDI R17, 0
BEGIN: OUT PORTB, R17 ; PORTB = R17
RCALL DELAY
EOR R17, R16 ; toggle D3 of R17
RJMP BEGIN
;------------ Timer0 Delay
DELAY: LDI R20, 0
OUT TCNT0, R20
LDI R20, 9
OUT OCR0A, R20 ; load OCR0A
LDI R20, (1<<WGM01) ; CTC mode
OUT TCCR0A, R20
LDI R20, 1
OUT TCCR0B, R20 ; CTC mode, int clk
AGAIN: SBIS TIFR0, OCF0A ; if OCF0A is set skip next instruction
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20 ; stop Timer0
LDI R20, (1<<OCF0A)
OUT TIFR0, R20 ; clear OCF0A flag
RET
Απάντηση: Για το προηγούμενο πρόγραμμα σημειώστε τα ακόλουθα βήματα:
1] Η τιμή 9 φορτώνεται στον OCR0A
2] O TCCR0 φορτώνεται και ο Timer0 ξεκινά την απαρίθμηση
3] Ο Timer0 απαριθμεί προς τα πάνω σε κάθε κύκλο ρολογιού ο οποίος παράγεται από κρυσταλλικό ταλαντωτή. Καθώς ο Timer απαριθμεί προς τα πάνω, πηγαίνει από τις καταστάσεις 00, 01, 02, 03 κ.ο.κ. μέχρι να φτάσει στην τιμή 9. Με τον επόμενο κύκλο ρολογιού κυλίεται στο 0 ανεβάζοντας σε 1 την σημαία OCF0A. Σε αυτή την στιγμή εδώ η εντολή «SBIS TIFR0, OCF0A» παρακάμπτει την εντολή «RJMP AGAIN»
4] Σταματά η λειτουργία του Timer0
5] Η σημαία OCF0A μηδενίζεται

Παράδειγμα: Βρες την χρονική καθυστέρηση που παράγεται από τον Timer0 στο προηγούμενο παράδειγμα. Μη λάβετε υπόψη τις καθυστερήσεις που παράγονται με τις άλλες εντολές. Θεωρείστε XTAL=16MHz
Απάντηση: Ο καταχωρητής OCR0A φορτώνεται με την τιμή 9 και ο TCNT0 μηδενίζεται. Επομένως μετά από 9 κύκλους ρολογιού, ο TCNT0 γίνεται ίσος με τον OCR0A. Στον επόμενο κύκλο η σημαία OCF0A γίνεται 1 και μηδενίζεται ο TCNT0. Αυτό σημαίνει ότι ο TCNT0 μηδενίζεται έπειτα από 9+1 κύκλους ρολογιού. Επειδή XTAL=16MHz ο απαριθμητής μετρά κάθε 0,0625μs. Επομένως έχουμε 10 x 0,0625μs = 0,625μs
Παράδειγμα: Βρες την χρονική καθυστέρηση που παράγεται από τον Timer0 για το ακόλουθο πρόγραμμα. Μην συμπεριλάβετε τις καθυστερήσεις που παράγονται με τις εντολές. (XTAL=16MHz)
LDI R16, (1<<3)
SBI DDRB, 3 ; PB3 as an output
LDI R17, 0
OUT PORTB, R17
LDI R20, 89
OUT OCR0A, R20 ; load Timer0
BEGIN: LDI R20, (1<<WGM01)
OUT TCCR0A, R20 ; CTC mode
LDI R20, 0x03
OUT TCCR0B, R20 ; CTC mode, prescaler=64
AGAIN: SBIS TIFR0, OCF0A ; if OCF0 flag is set skip next instruction
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20 ; stop Timer0
LDI R20, 1<<OCF0A
OUT TIFR0, R20 ; clear OCF0 flag
EOR R17, R16 ; toggle D3 of R17
OUT PORTB, R17 ; toggle PB3
RJMP BEGIN

Απάντηση: Επειδή έχουμε prescaler=64 κάθε κύκλος ρολογιού διαρκεί 64 x 0,0625μs = 4μs . Ο καταχωρητής OCR0A φορτώνεται με την τιμή 89. Επομένως μετά από 90 κύκλους ρολογιού, η σημαία OCF0A τίθεται σε 1. Συνεπώς έχουμε 90 x 4μs = 360μs
Παράδειγμα: Θεωρήστε XTAL=16MHz. Γράψε ένα πρόγραμμα που να παράγει χρονική καθυστέρηση 12,8ms. Χρησιμοποίησε Timer0, CTC λειτουργία και prescaler=1024
Απάντηση: Επειδή έχουμε prescaler=1024 κάθε κύκλος του timer διαρκεί 1024 x 0,0625μs = 64μs. Επομένως για να παράγουμε καθυστέρηση 12,8ms θα πρέπει να έχουμε καθυστέρηση 12,8ms/64μs=200 κύκλους ρολογιού. Συνεπώς ο καταχωρητής OCR0A θα πρέπει να φορτωθεί με την τιμή 200-1=199
DELAY: LDI R20, 0
OUT TCNT0, R20
LDI R20, 199
OUT OCR0A, R20
LDI R20, (1<<WGM01)
OUT TCCR0A, R20
LDI R20, 0x05
OUT TCCR0B, R20
AGAIN: SBIS TIFR0, OCF0A
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20
LDI R20, (1<<OCF0A)
OUT TIFR0, R20
RET
Παράδειγμα: Υποθέτουμε XTAL=16MHz. Γράψτε ένα πρόγραμμα που να παράγει χρονική καθυστέρηση 1ms.
Απάντηση: Επειδή XTAL=16MHz οι διάφοροι έξοδοι από τον prescaler είναι οι εξής:
Prescaler Timer Clock Timer Period Timer Value
None 16MHz 1/16MHz=0,0625μs 1ms/0,0625μs=16000
8 16MHz/8=2MHz 1/2MHz=0,5μs 1ms/0,5μs=2000
64 16MHz/64=250kHz 1/250kHz=4μs 1ms/4μs=250
256 16MHz/256=62,5kHz 1/62,5kHz=16μs 1ms/16μs=62,5
1024 16MHz/1024=15,625kHz 1/15,625kHz=64μs 1ms/64μs=15,625
Από τους προηγούμενους υπολογισμούς, μπορούμε να επιλέξουμε ένα από prescaler=64, prescaler=256, prescaler=1024. Θα χρησιμοποιήσουμε την επιλογή prescaler=64 από την στιγμή που δεν μπορούμε να χρησιμοποιήσουμε δεκαδικά ψηφία. Για καθυστέρηση 250 κύκλων ρολογιού θα πρέπει να φορτώσουμε τον OCR0A με την τιμή 250-1=249.
DELAY: LDI R20, 0
OUT TCNT0, R20 ; TCNT0 = 0
LDI R20, 249
OUT OCR0A, R20 ; OCR0A = 249
LDI R20, (1<<WGM01)
OUT TCCR0A, R20 ; CTC mode
LDI R20, 0x03
OUT TCCR0B, R20 ; CTC mode, prescaler = 64
AGAIN: SBIS TIFR0, OCF0A ; if OCF0A is set skip next instruction
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20 ; stop Timer0
LDI R20, (1<<OCF0A)
OUT TIFR0, R20 ; clear OCF0A flag
RET
Σημείωση: Ο εσωτερικός συγκριτής ελέγχει για ισότητα, επομένως εάν φορτώσουμε τον καταχωρητή OCR0A με μια τιμή που να είναι μικρότερη από την τιμή του TCNT0, o counter θα ξεπεράσει την κατάσταση ισότητας και θα απαριθμήσει μέχρι την μέγιστη τιμή $FF και μετά θα κυλήσει στο 0. Αυτό θα προκαλέσει μια μεγάλη καθυστέρηση που δεν είναι επιθυμητή σε πολλές περιπτώσεις.
Παράδειγμα: Στο επόμενο πρόγραμμα, πόσο χρόνο παίρνει για το ΡΒ3 να γίνει 1; Μην λάβετε υπόψη τους χρόνους εκτέλεσης των εντολών.
SBI DDRB, 3 ; PB3 as an output
CBI PORTB, 3 ; PB3 = 0
LDI R20, 89
OUT OCR0A, R20 ; OCR0A = 89
LDI R20, 95
OUT TCNT0, R20 ; TCNT0=95
BEGIN: LDI R20, (1<<WGM01)
OUT TCCR0A, R20 ; CTC mode
LDI R20, 1
OUT TCCR0B, R20 ; CTC mode, prescaler = 1
AGAIN: SBIS TIFR0, OCF0A ; if OCF0A flag is set skip next instruction
RJMP AGAIN
LDI R20, 0x00
OUT TCCR0B, R20 ; stop Timer0
LDI R20, (1<<OCF0A)
OUT TIFR0, R20 ; clear OCF0A flag
EOR R17, R16 ; toggle D3 of R17
OUT PORTB, R17 ; toggle PB3
RJMP BEGIN

Απάντηση: Επειδή η τιμή του TCNT0 (95) είναι μεγαλύτερη από την τιμή του OCR0A (89) ο timer θα απαριθμήσει προς τα πάνω μέχρι την τιμή $FF και μετά θα κυλήσει στο 0. Η σημαία TOV0 θα γίνει 1 με την υπερχείλιση. Μετά ο timer θα απαριθμήσει από την τιμή 0 μέχρι την 89 όπου μια ισότητα με τον OCR0A θα συμβεί. Συνεπώς η πρώτη ισότητα θα συμβεί μετά από 161+90=251 κύκλους ρολογιού (όπου 161 = 256-95) που σημαίνει μετά από χρόνο 251 x 0,0625μs = 15,6875μs. Η επόμενη ισότητα θα συμβεί μετά από 90 κύκλους που σημαίνει μετά από 90 x 0,0625μs = 5,625μs