4. Δημιουργώντας μεγάλες χρονικές καθυστερήσεις

Όπως έχουμε δει στα παραδείγματα των προηγούμενων ενοτήτων, το μέγεθος της χρονικής καθυστέρησης που παράγεται, εξαρτάται από δυο παράγοντες: την συχνότητα του εσωτερικού κρυσταλλικού ταλαντωτή και την τιμή του 8bit TCNT0 καταχωρητή. Μέγιστη χρονική καθυστέρηση έχουμε όταν ο καταχωρητής TCNT0 έχει τιμή μηδέν. Τι γίνεται όμως εάν αυτό δεν είναι αρκετό; Μπορούμε να κάνουμε την κατάλληλη επιλογή prescaler στον καταχωρητή TCCR0B για να αυξήσουμε την καθυστέρηση. Η επιλογή prescaler του TCCR0B μας επιτρέπει να διαιρούμε τη συχνότητα του σήματος ρολογιού που τροφοδοτεί τον timer με ένα παράγοντα από 0 έως 1024. Ο ορισμός prescaler του Timer/Counter0 φαίνεται στο ακόλουθο σχήμα:

Παράδειγμα: Στο πρόγραμμα της προηγούμενης ενότητας, όρισε το περιεχόμενο του TCNT0 ώστε να έχουμε την μέγιστη δυνατή καθυστέρηση.

          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:    RECALL DELAY
          EOR  R17, R16    ;   toggle D3 of R17
          OUT  PORTB, R17  ;   toggle PB3
          RJMP BEGIN
;------------- Timer0 Delay
DELAY:    LDI  R20, 0x00
          OUT  TCNT0, R20  ;   load Timer0 with zero
          LDI  R20, 0x00
          OUT  TCCR0A, R20  ;   Normal mode
          LDI  R20, 0x01
          OUT  TCCR0B, R20  ;  Nomal 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

Για να πάρουμε την μέγιστη δυνατή καθυστέρηση θέτουμε τον TCNT0 ίσο με μηδέν. Αυτό σημαίνει ότι ο timer απαριθμεί από το 00 έως το 0xFF και μετά κυλίεται στο 00 ανεβάζοντας σε 1 τη σημαία TOV0. Σαν αποτέλεσμα το σύστημα περνά συνολικά από 256 βήματα. Επομένως η χρονική καθυστέρηση είναι (256 – 0) x 0,0625μs = 16μs. Αυτό δίνει τη μικρότερη συχνότητα τετραγωνικού σήματος ίση με 1 / (2×16μs) = 1/(32μs) = 31,250KHz.

Όμως έχουμε δει μέχρι στιγμής ότι, με την επιλογή no prescaler, το σήμα του κρυσταλλικού ταλαντωτή τροφοδοτεί κατευθείαν τον Timer0. Ενεργοποιώντας τον prescaler με τα κατάλληλα bits του TCCR0B καταχωρητή, μπορούμε να διαιρέσουμε το σήμα ρολογιού προτού τροφοδοτηθεί στον Timer0. Τα χαμηλότερα 3 bits του TCCR0B, ορίζουν τον αριθμό με τον οποίο θα διαιρεθεί το σήμα ρολογιού. Όπως φαίνεται στο σχήμα, αυτός ο αριθμός μπορεί να είναι 8, 64, 256 ή 1024

Παράδειγμα: Βρες την συχνότητα και την περίοδο ρολογιού που τροφοδοτεί τον timer, για διάφορα συστήματα AVR, για τις ακόλουθες συχνότητες κρυσταλλικού ταλαντωτή. Υποθέστε ότι χρησιμοποιείται prescaler 1:64
(α) 8MHz  (β)16ΜΗz  (γ)10MHz

Απάντηση: (α) 1/64 x 8MHz = 125KHz λόγω prescaler και T=1/125KHz = 8μs
(β) 1/64 x 16MHz = 250KHz λόγω prescaler και T=1/250KHz = 4μs
(γ) 1/64 x 10MHz = 156,2KHz λόγω prescaler και T=1/156KHz =6,4μs

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

Απάντηση: Από το σχήμα ορισμού των bits του TCCR0B της προηγούμενης ενότητας προκύπτει ότι: TCCR0B = 0b0000 0011 με εσωτερικό σήμα ρολογιού και prescaler 1:64

Παράδειγμα: Εξετάστε το επόμενο πρόγραμμα και βρες το μέγεθος της χρονικής καθυστέρησης που παράγεται σε δευτερόλεπτα. Υποθέστε ότι XTAL=16MHz

          INITSTACK
          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    ;  toggle PB3
          RJMP BEGIN
;----------------- Timer0 Delay
DELAY:    LDI  R20, 0x10
          OUT  TCNT0, R20
          LDI  R20, 0x00
          OUT  TCCR0A, R20   ; Normal mode
          LDI  R20, 0x03
          OUT  TCCR0B, R20   ; Timer0, Normal mode, int clk, prescaler 64
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
          RET

Απάντηση: TCNT0=0x10 = 16 στο δεκαδικό και 256-16=240. Έχουμε 240 x 64 x 0,0625μs = 960μs

Παράδειγμα: Υποθέστε ότι XTAL = 16MHz (α) Βρες την περίοδο του σήματος ρολογιού που τροφοδοτεί τον Timer0 εάν έχουμε prescaler 1:1024  (β) Δείξτε ότι είναι το μεγαλύτερο δυνατό μέγεθος καθυστέρησης που παίρνουμε με αυτή την τιμή prescaler στον Timer0.

Απάντηση: (α) 16MHz x 1/1024 = 15625Hz λόγω  του λόγου prescaler 1:1024 και T = 1/15625Hz = 64μs = 0,064ms
(β) Για να πάρουμε την μεγαλύτερη δυνατή διάρκεια καθυστέρησης, φορτώνουμε τον TCNT0 με 0. Κάνοντας τον TCNT0 μηδέν σημαίνει ότι ο timer θα απαριθμεί από 00 έως 0xFF και με την κύλιση του στο 0, η σημαία TOV0 γίνεται 1. Συνεπώς η χρονική καθυστέρηση περνά από 256 βήματα. Επομένως έχουμε καθυστέρηση ίση με (256 – 0) x 64μs = 16,384μs = 0,016384 δευτερόλεπτα.

Παράδειγμα: Υποθέστε ότι έχουμε XTAL = 16MHz. Γράψτε ένα πρόγραμμα που να παράγει μια τετραγωνική κυματομορφή συχνότητας 250Ηz στο pin PORTB.3 Χρησιμοποιείστε Timer0, Normal mode, prescaler=256

Απάντηση: Ακολουθούμε τα ακόλουθα βήματα:
(α) Τ=1/250Ηz = 4ms είναι η περίοδος του τετραγωνικού σήματος
(β) ½ από αυτό δηλ. 2ms είναι η διάρκεια κάθε τμήματος high και low του σήματος
(γ) (2ms / 0,0625μs) / 256 = 125 και 256 – 125 = 131 στο δεκαδικό και 0x83 στο δεκαεξαδικό
(δ) TCNT0 = 0x83

.MACRO  INITSTACK         ;  set up stack
        LDI R20, HIGH(RAMEND)
        OUT SPH, R20
        LDI R20, LOW(RAMEND)
        OUT SPL, R20
.ENDMACRO
        INITSTACK
        LDI R16, (1<<3)
        SBI DDRB, 3     ;  PB3  as  an  output
        LDI R17, 0
BEGIN:  OUT PORTB, R17   ;  PORTB = R17
        CALL DELAY
        EOR R17, R16     ;  toggle D3 of  R17
        RJMP  BEGIN
;-------------------- Timer0 Delay
DELAY : LDI R20, 0x83
        OUT TCNT0, R20    ;  load Timer0
        LDI R20,  0x00
        OUT TCCR0A, R20   ;  Normal mode
        LDI R20, 0x04
        OUT TCCR0B, R20   ;  Normal mode, int clk, prescaler = 256
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

Assemblers και αρνητικές τιμές

Επειδή ο Timer0 λειτουργεί σε κατάσταση 8bit μπορούμε να αφήσουμε τον Assembler να υπολογίσει την τιμή για τον TCNT0. Για παράδειγμα με την εντολή «LDI R20, -100» ο Assembler θα υπολογίσει -100=9C και θα θέσει R20=9C στο δεκαεξαδικό. Με τον τρόπο αυτό έχουμε μεγάλη ευκολία.

Παράδειγμα: Βρες τις τιμές (στο δεκαεξαδικό) που πρέπει να φορτώσουμε στον TCNT0 σε κάθε μια από τις ακόλουθες περιπτώσεις:
(α) LDI R20, -200
      OUT  TCNT0, R20
(β) LDI R17, -60
       OUT  TCNT0, R17
(γ)  LDI R25, -12
      OUT  TCNT0, R25

Απάντηση: Μπορούμε να χρησιμοποιήσουμε το επιστημονικό κομπιουτεράκι των Windows για να επαληθεύσουμε τα αποτελέσματα που δίνει ο Assembler. Στο κομπιουτεράκι των Windows επιλέγουμε decimal  και πληκτρολογούμε 200. Μετά επιλέγουμε hex και μετά +/- για να πάρουμε την αρνητική τιμή. Παίρνουμε τα ακόλουθα αποτελέσματα:

Decimal             2's complement(TCNT0 value)
-200                   0x38
-60                    0xC4
-12                    0xF4

Παράδειγμα: Βρες (α) τη συχνότητα του τετραγωνικού σήματος που παράγεται από τον ακόλουθο κώδικα και (β) το duty cycle αυτού του τετραγωνικού σήματος. Υποθέστε: XTAL= 16MHz

        LDI  R16, HIGH(RAMEND)
        OUT  SPH, R16
        LDI  R16, LOW(RAMEND)
        OUT  SPL, R16
        SBI  DDRB, 5        ;   PB5 as  an  output
        LDI  R18, -150
BEGIN:  SBI  PORTB, 5       ;   PB5 = 1
        OUT  TCNT0, R18     ;   load  Timer0 byte
        CALL  DELAY
        OUT  TCNT0, R18     ;   reload Timer0 byte
        CALL DELAY
        CBI  PORTB, 5       ;   PB5=0
        OUT  TCNT0, R18     ;   reload Timer0 byte
        CALL DELAY
        RJMP BEGIN
;---------- Delay  using  Timer0
DELAY:  LDI  R20, 0x00
        OUT  TCCR0A, R20    ;  Normal mode
        LDI  R20, 0x01
        OUT  TCCR0B, R20    ;  start Timer0, Normal mode, int clk, no prescaler
AGAIN:  SBIS TIFR0, TOV0
        RJMP AGAIN
        LDI  R20, 0x00
        OUT  TCCR0B, R20    ;  stop Timer0
        LDI  R20,  1<<TOV0
        OUT  TIFR0, R20     ;  clear  TOV0  flag bit
        RET

Απάντηση: Για τον TCNT0 σε κατάσταση λειτουργίας 8bit, η μετατροπή γίνεται από τον Assembler, εφόσον έχουμε εισάγει στην εντολή αρνητικό αριθμό. Αυτό κάνει τον υπολογισμό εύκολο. Επειδή χρησιμοποιούμε 150 κύκλους ρολογιού έχουμε για την χρονική καθυστέρηση στην DELAY ρουτίνα: 150 x 0,0625μs = 9,375μs. Το high τμήμα του τετραγωνικού σήματος είναι διπλάσιο από το low τμήμα (66% duty cycle). Επομένως έχουμε Τ=high portion + low portion = 2 x 9,375μs + 9,375μs = 28,125μs και συχνότητα F = 1/28,125μs = 35,555kHz