TIMER O
Ένας σχετικά απλός timer είναι ο timer0, αυτός είναι 8bit στην σειρά 16f ενώ στην 18f μπορεί να είναι 8 ή 16, επίσης δεν διαθέτει postscaler.
το block
Fosc/4 : instruction clock (συχνότητα κρυστάλλου δια 4)
TOCKI pin: είναι το τιμερ 0 clock input (εξωτερικό ρολόι)
TOSE : Source Edge Select bit (hi to low ή low to hi για το εξωτερικό ρολόι)
TOCS : Timer0 Clock Source Select bit (εξωτερικοί παλμοί ή κρύσταλλος)
T0PS2:T0PS0 : Prescaler Select bits (διαιρέτης)
PSA : Prescaler Assignment bit (βγάζει εκτός τον prescaler)
2 TCY Delay : κάνει καθυστέρηση 2 instruction clock για να συγχρονιστεί ο εξωτερικός παλμός (αν υπάρχει) με τα εσωτερικά συστήματα του.
TMR0 : ο καταχωρητής του τιμερ.
TMR0IF : interrupt flag (γίνεται 1 όταν υπάρξει υπερχείλιση του TMR0).
Πώς δουλεύει τώρα, πχ. έχουμε κρύσταλο 4Mhz που μας κάνει τον κάθε κύκλο μηχανής σε 1μS (Tcy=Fosc/4)
δηλαδή ο τιμερ θα αυξάνει κατά ένα κάθε ένα μS και έτσι θα έχουμε (με απενεργοποιημένο τον prescaler) interrupt κάθε 256μS.
Τώρα αν θέλουμε να μεγαλώσουμε τον χρόνο που θα πραγματοποιήτε η διακοπή μας μπορούμε να ενεργοποιήσουμε τον prescaler,
η δουλεία του prescaler είναι να διαιρεί τους παλμούς που θα φτάσουν στον TMR0 register ώστε να μεγαλώσει ο χρόνος.
Αυτό μπορεί να γίνει ρυθμίζοντας κατάλληλα τα 3 bit TOPS0, TOPS1, TOPS2 του T0CON (timer0 control register), αυτά τα τρια bit μπορούν να δώσουν 8 διαφορετικές τιμές διαίρεσης /2, /4, /8, /16, /32, /64, /128, /256
έτσι λοιπόν στο ποιο πάνω παράδειγμα αν ενεργοποιήσουμε και τον prescaler με τιμή /64 τότε θα μετράει ανά ένα κάθε
1μS(που είναι το instruction clock)*64(που είναι η τιμή του prescaler) και έτσι θα έχουμε interrupt κάθε 256*64= 16384μS.
Επίσης την τιμή του TMR0 μπορούμε να την διαβάσουμε ή και να την γράψουμε, το διάβασμα εξυπηρετεί αν θέλουμε να εκτελούμε κάτι σε τακτά χρονικά διαστήματα ή για έλεγχο ενώ το γράψιμο του μας εξυπηρετεί αν θέλουμε ένα μικρότερο χρόνο διακοπής (από το 256 που είναι στα 8bit).
Πχ. στο παραπάνω παράδειγμα κρυσταλο=4Mhz, Tcy=1μS, prescaler=/64
αν γράψουμε στο καταχωρητή του timer την τιμή 100, θα ξεκινάει να μετράει πάνω από αυτή και έτσι θα αυξάνει κατά ένα ανά 64μS αλλά η διακοπή θα έρθει όχι στα 16,384mS αλλά στα (256-100)*64=9984μS.
Και τέλος όταν δημιουργείτε overflow του timer τότε εκτελείτε η ρουτίνα της διακοπής που υπάρχει στην αρχή του προγράμματος,
και όταν αυτή τελειώση επιστρέφει στο σημείο που είχε μείνη και συνεχίζει κανονικά την ροή του προγράμματος.
Παράδειγμα 1:
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4000000)
#int_TIMER0
void TIMER0_isr(void)
{
output_toggle(PIN_A0);
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
}
Τον ορίζουμε σαν 8bit με το εσωτερικό ρολόι και διαίρεση /4,
που σε χρόνο μας βγαίνει 1uS*256=256uS overflow επί 4 (ο διαιρέτης) = 1024uS.
Δηλ. στο παραπάνω θα δημιουργηθεί στο πιν Α0 ένας παλμός 500hz (1mS hi και 1mS low).
Τώρα αν αφαιρέσουμε από τις παραμέτρους του setup_timer το rtcc_8_bit, τότε θα γίνει 16 bit.
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4000000)
#int_TIMER0
void TIMER0_isr(void)
{
output_toggle(PIN_A0);
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
}
Και έτσι θα κάνει overflow ανά 1*65536=65mS επί 4 (ο διαιρέτης)
θα δημιουργηθεί στο πιν Α0 ένας παλμός περίπου στα 2hz (262mS hi και 262mS low).
Ένα άλλο πράγμα που μπορούμε να κάνουμε με αυτό είναι να του δώσουμε εξωτερικούς παλμούς αντί του εσωτερικού βασικού ρολογιού δηλαδή σαν counter (τους εξωτερικούς παλμούς τους δίνουμε στο πιν TOCKI timer 0 clock input).
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4000000)
#int_TIMER0
void TIMER0_isr(void)
{
output_toggle(PIN_A0);
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_1|RTCC_8_bit);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
}
Τον timer τον όρισα σαν 8 bit counter με prescaler ίσο με ένα και έτσι ανά 256 παλμούς (low to hi) που θα λαμβάνει θα ενεργοποιείτε η ρουτίνα της διακοπής,
δηλ. με ένα clock 256hz θα μας δώσει στο πιν Α0 έναν παλμό 0,5Hz (1sec hi και 1sec low)
το block
Fosc/4 : instruction clock (συχνότητα κρυστάλλου δια 4)
TOCKI pin: είναι το τιμερ 0 clock input (εξωτερικό ρολόι)
TOSE : Source Edge Select bit (hi to low ή low to hi για το εξωτερικό ρολόι)
TOCS : Timer0 Clock Source Select bit (εξωτερικοί παλμοί ή κρύσταλλος)
T0PS2:T0PS0 : Prescaler Select bits (διαιρέτης)
PSA : Prescaler Assignment bit (βγάζει εκτός τον prescaler)
2 TCY Delay : κάνει καθυστέρηση 2 instruction clock για να συγχρονιστεί ο εξωτερικός παλμός (αν υπάρχει) με τα εσωτερικά συστήματα του.
TMR0 : ο καταχωρητής του τιμερ.
TMR0IF : interrupt flag (γίνεται 1 όταν υπάρξει υπερχείλιση του TMR0).
Πώς δουλεύει τώρα, πχ. έχουμε κρύσταλο 4Mhz που μας κάνει τον κάθε κύκλο μηχανής σε 1μS (Tcy=Fosc/4)
δηλαδή ο τιμερ θα αυξάνει κατά ένα κάθε ένα μS και έτσι θα έχουμε (με απενεργοποιημένο τον prescaler) interrupt κάθε 256μS.
Τώρα αν θέλουμε να μεγαλώσουμε τον χρόνο που θα πραγματοποιήτε η διακοπή μας μπορούμε να ενεργοποιήσουμε τον prescaler,
η δουλεία του prescaler είναι να διαιρεί τους παλμούς που θα φτάσουν στον TMR0 register ώστε να μεγαλώσει ο χρόνος.
Αυτό μπορεί να γίνει ρυθμίζοντας κατάλληλα τα 3 bit TOPS0, TOPS1, TOPS2 του T0CON (timer0 control register), αυτά τα τρια bit μπορούν να δώσουν 8 διαφορετικές τιμές διαίρεσης /2, /4, /8, /16, /32, /64, /128, /256
έτσι λοιπόν στο ποιο πάνω παράδειγμα αν ενεργοποιήσουμε και τον prescaler με τιμή /64 τότε θα μετράει ανά ένα κάθε
1μS(που είναι το instruction clock)*64(που είναι η τιμή του prescaler) και έτσι θα έχουμε interrupt κάθε 256*64= 16384μS.
Επίσης την τιμή του TMR0 μπορούμε να την διαβάσουμε ή και να την γράψουμε, το διάβασμα εξυπηρετεί αν θέλουμε να εκτελούμε κάτι σε τακτά χρονικά διαστήματα ή για έλεγχο ενώ το γράψιμο του μας εξυπηρετεί αν θέλουμε ένα μικρότερο χρόνο διακοπής (από το 256 που είναι στα 8bit).
Πχ. στο παραπάνω παράδειγμα κρυσταλο=4Mhz, Tcy=1μS, prescaler=/64
αν γράψουμε στο καταχωρητή του timer την τιμή 100, θα ξεκινάει να μετράει πάνω από αυτή και έτσι θα αυξάνει κατά ένα ανά 64μS αλλά η διακοπή θα έρθει όχι στα 16,384mS αλλά στα (256-100)*64=9984μS.
Και τέλος όταν δημιουργείτε overflow του timer τότε εκτελείτε η ρουτίνα της διακοπής που υπάρχει στην αρχή του προγράμματος,
και όταν αυτή τελειώση επιστρέφει στο σημείο που είχε μείνη και συνεχίζει κανονικά την ροή του προγράμματος.
Παράδειγμα 1:
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4000000)
#int_TIMER0
void TIMER0_isr(void)
{
output_toggle(PIN_A0);
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
}
Τον ορίζουμε σαν 8bit με το εσωτερικό ρολόι και διαίρεση /4,
που σε χρόνο μας βγαίνει 1uS*256=256uS overflow επί 4 (ο διαιρέτης) = 1024uS.
Δηλ. στο παραπάνω θα δημιουργηθεί στο πιν Α0 ένας παλμός 500hz (1mS hi και 1mS low).
Τώρα αν αφαιρέσουμε από τις παραμέτρους του setup_timer το rtcc_8_bit, τότε θα γίνει 16 bit.
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4000000)
#int_TIMER0
void TIMER0_isr(void)
{
output_toggle(PIN_A0);
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
}
Και έτσι θα κάνει overflow ανά 1*65536=65mS επί 4 (ο διαιρέτης)
θα δημιουργηθεί στο πιν Α0 ένας παλμός περίπου στα 2hz (262mS hi και 262mS low).
Ένα άλλο πράγμα που μπορούμε να κάνουμε με αυτό είναι να του δώσουμε εξωτερικούς παλμούς αντί του εσωτερικού βασικού ρολογιού δηλαδή σαν counter (τους εξωτερικούς παλμούς τους δίνουμε στο πιν TOCKI timer 0 clock input).
#include <18F2550.h>
#FUSES NOWDT, INTRC_IO, NOPUT, NOMCLR
#use delay(clock=4000000)
#int_TIMER0
void TIMER0_isr(void)
{
output_toggle(PIN_A0);
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_1|RTCC_8_bit);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while (1);
}
Τον timer τον όρισα σαν 8 bit counter με prescaler ίσο με ένα και έτσι ανά 256 παλμούς (low to hi) που θα λαμβάνει θα ενεργοποιείτε η ρουτίνα της διακοπής,
δηλ. με ένα clock 256hz θα μας δώσει στο πιν Α0 έναν παλμό 0,5Hz (1sec hi και 1sec low)