Timers/Counters - PWM στον ATmega16

 

Συγγραφέας: Πορλιδάς Δημήτριος

Βιογραφικό Σημείωμα

electronics@porlidas.gr

Facebook

Linkedin


 

 

Οι AVR διαθέτουν μετρητές (Timers/Counters) με δυνατότητα σύγκρισης και διακοπής. Ο χρονισμός τους μπορεί να είναι σύγχρονος ή ασύγχρονος, από το ρολόι συστήματος ή από εξωτερική πηγή και υπάρχει δυνατότητα διαίρεσης της συχνότητας χρονισμού με prescaler ώστε να επιτευχθεί ο επιθυμητός ρυθμός μέτρησης. Οι μετρητές χρησιμοποιούνται για ακριβή χρονισμό ή διακοπή μετά το πέρας κάποιου συγκεκριμένου χρονικού διαστήματος και για παραγωγή παλμών διαμόρφωσης πλάτους (PWM).

Ο ATmega16 διαθέτει τρεις μετρητές Timer/Counter0:2. Οι Timer/Counter0 και Timer/Counter2 είναι 8-bit, ενώ ο Timer/Counter1 είναι 16-bit και είναι διπλός Α και Β. Οι Timer/Counter0 και Timer/Counter1 έχουν σύγχρονη λειτουργία ενώ ο Timer/Counter2 ασύγχρονη. Οι μετρητές κάνουν μέτρηση και σύγκριση μεταξύ των καταχωρητών τους. Ο καταχωρητής μέτρησης είναι ο TCNTn (n: 0, 1A, 1B, 2) και μεταβάλλει το περιεχόμενό του προς τα πάνω ή προς τα κάτω, από το ελάχιστο όριο Bottom έως το μέγιστο Max ή Top, ανάλογα με τον τρόπο λειτουργίας του μετρητή. Το περιεχόμενό του συγκρίνεται με το περιεχόμενο του καταχωρητή σύγκρισης OCRn και όταν υπάρξει ισότητα ή κατά την υπερχείλιση του TCNTn, προκαλείται μια διακοπή. Η διακοπές που προκαλούνται και οι σημαίες που τοποθετούνται στα όρια διαμορφώνουν κάποιες λειτουργίες. Το όριο Bottom είναι σε όλους τους μετρητές 0 (0x0), το όριο Max εξαρτάται από τα bit του μετρητή και το Top από τον τρόπο λειτουργίας του και από τον OCRn.

Οι τρόποι λειτουργίας των μετρητών καθορίζονται από τα WGMnx bit του καταχωρητή TCCRn. Ο πιο απλός τρόπος λειτουργίας είναι ο Normal Mode όπου ο TCNTn μετράει προς τα πάνω μέχρι το μέγιστο και ξεκινάει πάλι από την αρχή. Όταν φτάσει στο μέγιστο τοποθετείται η σημαία υπερχείλισης TOVn και προκαλείται η αντίστοιχη διακοπή[1], η οποία μηδενίζει την TOVn.

Στη λειτουργία Clear Timer on Compare Match (CTC) Mode ο TCNTn μετράει προς τα πάνω και συγκρίνεται με το περιεχόμενο του καταχωρητή OCRn. Όταν υπάρξει ισότητα τοποθετείται η σημαία OCn και προκαλείται η αντίστοιχη διακοπή[2], ενώ ταυτόχρονα μηδενίζει ο TCNTn και ξεκινάει το μέτρημα ξανά. Την κατάσταση της OCn μπορούμε να πάρουμε ως κυματομορφή στο αντίστοιχο pin του PORT, εφόσον το ενεργοποιήσουμε ως έξοδο και ρυθμίσουμε την OCn από τα bit COMnx του καταχωρητή TCCRn να αλλάζει την λογική της κατάσταση στο σημείο σύγκρισης (Toggle). Η κυματομορφή εξόδου θα είναι συμμετρικοί παλμοί όπου η συχνότητα εξαρτάται από τη συχνότητα του ρολογιού του συστήματος, τον prescaler και από την τιμή του OCRn. Στη συνέχεια παρουσιάζεται ένα παράδειγμα χρήσης του Timer/Counter1A γραμμένο σε γλώσσα προγραμματισμού C (η ρουτίνα της διακοπής εκτελείται με συχνότητα 250Hz): 

#include <avr/io.h>

#include <avr/interrupt.h>

 

void Timer1_init()                       // Initialize Timer1A

{

TCCR1B |= (1 << WGM12);               // Configure timer 1 for CTC mode

TCCR1B |= (3 << CS10);                // clk/64

TIMSK |= (1 << OCIE1A);               // Enable CTC interrupt

OCR1A = 500;                          // Set CTC for 250Hz at 8MHz clock

sei();                                // Enable global interrupts

}

 

ISR(TIMER1_COMPA_vect)

{

              /* Your code here */

}

 

int main(void)                           // Main program

{

/* Your code here */

Timer1_init();

 

While (1)

{

/* Your code here */

}

}

Η ρουτίνα Timer1_init() είναι υπεύθυνη για το initialization του Timer, όπου ρυθμίζεται να λειτουργεί σε CTC κατάσταση, ο χρονισμός να είναι από το ρολόι συστήματος διαιρεμένος με το 64, ενεργοποιείται η διακοπή από CTC, ενεργοποιούνται οι διακοπές γενικά και ορίζεται τιμή σύγκρισης στον OCR1A 500 ώστε να προκαλούνται διακοπές με συχνότητα 250Hz. Ακολουθεί το διάνυσμα της διακοπής ISR(TIMER1_COMPA_vect) όπου ο κώδικας που είναι γραμμένος στο μπλοκ κάτω από τον τίτλο του εκτελείται κάθε φορά που προκαλείται διακοπή από τη σύγκριση. Στο κυρίως πρόγραμμα τέλος, καλείται η ρουτίνα για το initialization πριν τον κυκλικό βρόχο.   

Στη λειτουργία Fast PWM Mode ο TCNTn μετράει προς τα πάνω και συγκρίνεται με το περιεχόμενο του καταχωρητή OCRn. Όταν υπάρξει ισότητα τοποθετείται (ή μηδενίζει στην ανάστροφη λειτουργία) η σημαία OCn και προκαλείται η αντίστοιχη διακοπή[3] χωρίς να μηδενίζει ο TCNTn, ο οποίος συνεχίζει το μέτρημα μέχρι το Max. Όταν φτάσει στο Max μηδενίζει (ή τοποθετείται) η OCn, μηδενίζει ο TCNTn και ξεκινάει το μέτρημα ξανά, τοποθετείται η σημαία υπερχείλισης TOVn και προκαλείται η αντίστοιχη διακοπή[4] η οποία μηδενίζει την TOVn. Την κατάσταση της OCn μπορούμε να πάρουμε ως κυματομορφή στο αντίστοιχο pin του PORT, εφόσον το ενεργοποιήσουμε ως έξοδο και ρυθμίσουμε κατάλληλα την OCn από τα bit COMnx του καταχωρητή TCCRn σε κανονική, ανάστροφη ή Toggle λειτουργία. Η κυματομορφή εξόδου θα είναι παλμοί με σταθερή συχνότητα και διαμόρφωση εύρους (duty cycle) από 0-100% (PWM). Η συχνότητα εξαρτάται από τη συχνότητα του ρολογιού του συστήματος και τον prescaler ενώ το duty cycle από την τιμή του OCRn. Στη συνέχεια παρουσιάζεται ένα παράδειγμα παραγωγής παλμών PWM στο pin PB3 γραμμένο σε γλώσσα προγραμματισμού C: 

#include <avr/io.h>

unsigned char pwmout;

 

void PWM0_init()                         // Initialize PWM0

{

DDRB |= (1 << PB3);                   // PWM PB3 OC0

TCCR0 |= (3 << WGM00);                // FPWM

TCCR0 |= (3 << COM00);                // Set output to high on compere match

TCCR0 |= (1 << CS00);                 // clk/64

}

 

int main(void)                           // Main program

{

/* Your code here */

PWM0_init();

 

While (1)

{

/* Your code here */

OCR0 = pwmout;                      // Set PWM duty cycle

/* Your code here */

}

}

Η ρουτίνα PWM0_init() είναι υπεύθυνη για το initialization του Timer, όπου ρυθμίζεται το PB3  ως έξοδος για το PWM, ρυθμίζεται να λειτουργεί σε FPWM κατάσταση, κανονική λειτουργία (η έξοδος να γίνεται 1 κατά την ταύτιση) και ο χρονισμός να είναι από το ρολόι συστήματος διαιρεμένος με το 64.  Στο κυρίως πρόγραμμα τέλος, καλείται η ρουτίνα για το initialization πριν τον κυκλικό βρόχο. Μέσα στον κυκλικό βρόχο μπορούμε να δίνουμε τιμές στον  OCR0 ώστε να μεταβάλλεται το duty cycle των παλμών PWM.

Η λειτουργία Phase Correct PWM Mode είναι σχεδόν ίδια με την Fast PWM με τη διαφορά ότι όταν ο TCNTn φτάσει στην ανώτερη τιμή δε μηδενίζει, αλλά αρχίζει να μετράει αντίστροφα (ελαττώνεται) μέχρι να φτάσει στο μηδέν όπου ξεκινάει να αυξάνει ξανά. Όταν υπάρξει ισότητα τοποθετείται (ή μηδενίζει στην ανάστροφη λειτουργία) η OCn όταν ο TCNTn βρίσκεται στην ανοδική φάση και το αντίθετο στην καθοδική. Η TOVn τοποθετείται όταν κατά την ελάττωση φτάσει στο μηδέν.

Ο Timer/Counter1 διαθέτει περισσότερους τρόπους λειτουργίας από τους άλλους δύο Timers και για αυτό το λόγο ο έλεγχος γίνεται από 4 bit (WGM13:0). Επίσης, μολονότι είναι διπλός (Α και Β) διαθέτει έναν καταχωρητή μέτρησης TCNT1. Οι επιπλέον τρόπου λειτουργίας εντοπίζονται κυρίως στις PWM λειτουργίες όπου ο TCNT1 αυξάνει μέχρι το Top το οποίο μπορεί να είναι 8, 9 ή 10 bit ή να εξαρτάται από τον OCR1A/B ή ICR1[5]. Υπάρχει επίσης η λειτουργία Phase and Frequency Correct PWM Mode όπου η μοναδική διαφορά της με την Phase Correct PWM Mode είναι ότι στην πρώτη ο καταχωρητής OCR1A/B ενημερώνεται από τον αντίστοιχο buffer όταν ο TCNT1 βρίσκεται στο Top ενώ στη δεύτερη στο Bottom.

 

©2017 Πορλιδάς Δημήτριος

 


[1] Η διακοπή προκαλείται αν είναι ενεργοποιημένη από το bit TOIEn του καταχωρητή TIMSK.

[2] Η διακοπή προκαλείται αν είναι ενεργοποιημένη από το bit OCIEn του καταχωρητή TIMSK.

[3] Η διακοπή προκαλείται αν είναι ενεργοποιημένη από το bit OCIEn του καταχωρητή TIMSK.

[4] Η διακοπή προκαλείται αν είναι ενεργοποιημένη από το bit TOIEn του καταχωρητή TIMSK.

[5] Ο ICR1 είναι ένας καταχωρητής όπου μπορεί να πάρει την τιμή του TCNT1 όταν υπάρχει εξωτερική ενεργοποίηση στο pin ICP1 ή από την έξοδο του αναλογικού συγκριτή ώστε να αποδοθεί χρονικό αποτύπωμα σε ένα γεγονός.   

 

Σας ευχαριστώ για την υποστήριξή σας ώστε να γίνει η ιστοσελίδα μου καλύτερη.

© 2017 Πορλιδάς Δημήτριος