Οι AVR διαθέτουν
αναλογικές εισόδους για σύγκριση ή μετατροπή σε ψηφιακή τιμή. Ο ATmega16 διαθέτει δύο εισόδους σύγκρισης, ΑΙΝ0 – ΑΙΝ1
(PB2 – PB3) και
οκτώ εισόδους για μετατροπή ADC0 – ADC7 (PA0 – PA7). Η σύγκριση μπορεί να γίνει είτε μεταξύ των ΑΙΝ0
– ΑΙΝ1 είτε μεταξύ της ΑΙΝ0 και μιας από τις οκτώ αναλογικές
εισόδους ADC0 – ADC7. Η θετική είσοδος του συγκριτή είναι είτε η ΑΙΝ0
είτε η τάση αναφοράς του μικροελεγκτή. Η αρνητική είσοδος μπορεί να είναι η ΑΙΝ1
ή μια από τις οκτώ αναλογικές. Για όσο η θετική είσοδος είναι μεγαλύτερη από
την αρνητική, η έξοδος του συγκριτή είναι τοποθετημένη ενώ καθαρίζει όταν η
αρνητική γίνει μεγαλύτερη. Κατά την αλλαγή η έξοδος μπορεί να προκαλέσει
διακοπή[1]
ή να ενεργοποιήσει τη λειτουργία Timer/Counter1 Input Capture. Οι
ρυθμίσεις του συγκριτή γίνονται από τους καταχωρητές SFIOR και ACSR.
Οι οκτώ αναλογικές είσοδοι μπορούν λειτουργήσουν ως μονές είσοδοι, μόνο
για θετικές τάσεις ως προς τη γείωση (αρνητική τροφοδοσία του συστήματος) ή ανά
δύο ως διαφορικοί είσοδοι,[2]
όπου θετική – αρνητική καθορίζονται από τον αντίστοιχο καταχωρητή ADMUX
και είναι ανεξάρτητες από την τροφοδοσία του συστήματος. Η ψηφιακή έξοδος του
μετατροπέα είναι 10bit και μετά
τη μετατροπή το αποτέλεσμα αποθηκεύεται στους καταχωρητές ADCL και ADCH. Όταν γίνεται χρήση
μονών εισόδων το αποτέλεσμα των 10bit είναι
μη προσημασμένος αριθμός[3]
και συνεπώς μπορεί να πάρει τιμές 0 – 1023. Όταν γίνεται χρήση διαφορικών εισόδων
είναι δυνατό να υπάρξουν αρνητικές τιμές και για αυτό το αποτέλεσμα των 10bit είναι προσημασμένος αριθμός[4] και μπορεί να
πάρει τιμές -512 – 511. Η μετατροπή γίνεται ως προς την τάση αναφοράς,[5] η οποία μπορεί
να είναι η AVCC (τάση τροφοδοσίας του αναλογικού
τμήματος του μικροελεγκτή) ή η εσωτερική τάση αναφοράς VREF[6]
ή μια εξωτερική τάση αναφοράς συνδεδεμένη στο pin AREF.[7]
Ο τρόπος που γίνεται η αποθήκευση των 10bit εξαρτάται από την αντίστοιχη σημαία ADLAR του καταχωρητή ADMUX και
μπορεί να είναι με δεξιά στοίχιση ή αριστερή. Κατά τη δεξιά στοίχιση τα 8 LSB του αποτελέσματος καταχωρούνται
στον ADCL και τα δύο MSB στα bit0
και bit1 του ADCH
(με το MSB στο bit1) ενώ όλα τα υπόλοιπα bit του ADCH είναι
0. Κατά την αριστερή στοίχιση
τα 8 MSB του αποτελέσματος
καταχωρούνται στον ADCH και
τα δύο LSB στα bit7 και bit6 του ADCL (με το LSB στο bit6) ενώ όλα τα υπόλοιπα
bit του ADCL είναι 0. Στον
Πίνακα Ι παρουσιάζεται ένα παράδειγμα με το περιεχόμενο των καταχωρητών για
προσημασμένους και μη αριθμούς στους δύο τρόπους στοίχισης.
Πίνακας Ι.
Παράδειγμα καταχωρητών ADCL και
ADCH.
ADCH
|
ADCL
|
|
0000 0011
|
0100 1011
|
Δεξιά στοίχιση, μη
προσημασμένος δεκ. αρ. 843
|
1101 0010
|
1100
0000
|
Αριστερή στοίχιση, μη
προσημασμένος δεκ. αρ. 843
|
0000 0011
|
0100 1011
|
Δεξιά στοίχιση, προσημασμένος
δεκ. αρ. -181
|
1101 0010
|
1100
0000
|
Αριστερή στοίχιση,
προσημασμένος δεκ. αρ. -181
|
Η δυνατότητα των δύο τρόπων στοίχισης μας επιτρέπει να απορρίπτουμε τα
δύο bit από τα δέκα και να
κάνουμε χρήση των υπόλοιπων οκτώ, έτσι ώστε να γίνεται πιο εύκολα η διαχείριση
του αποτελέσματος. Αν για παράδειγμα δε μας ενδιαφέρει τόσο η ακρίβεια μπορούμε
να επιλέξουμε αριστερή στοίχιση και να αγνοήσουμε τα 2 LSB διαβάζοντας μόνο τον ADCH.
Πρέπει όμως να λάβουμε υπόψη ότι η μέγιστη τιμή[8]
των 8bit αντιστοιχεί στην VREF. Στη συνέχεια παρουσιάζεται ένα παράδειγμα προετοιμασίας
του ADC και μετατροπής,
γραμμένο σε γλώσσα C.
uint8_t AdcOut1;
void InitADC (void)
{
ADCSRA = ((1 << ADEN) | (7 << ADPS0)); // ADC Enable, single conversion, 62.5kHz sample
ADMUX = ((1 << REFS0) | (1 << ADLAR)); // AVcc(REFS0:1 = 0->AREF, 1->AVCC, 3->IntRef
2.54V),
// left adjust result, PA0 (MUX0=0 by default)
}
void GetADC (void)
{
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // Wait for conversion to
complete
ADCSRA |= (1 << ADIF); // Set complete flag
AdcOut1 = ADCH; // Write data to variable
}
Η πρώτη ρουτίνα είναι για την προετοιμασία του ADC.
Mε την πρώτη εντολή γίνεται η ενεργοποίηση των
κυκλωμάτων του μαζί με την επιλογή εκκίνησης μετατροπής[9] (επιλέγεται
απλή μετατροπή) και συχνότητας λειτουργίας του κυκλώματος διαδοχικής
προσέγγισης[10]
(επιλέγεται 62.5kHz). Με τη δεύτερη εντολή γίνεται η
επιλογή της τάσης αναφοράς και αριστερής στοίχισης.
Η δεύτερη ρουτίνα είναι για τη μετατροπή. Με την πρώτη εντολή
τοποθετείται η σημαία ADSC και
αυτό σηματοδοτεί την εκκίνηση της μετατροπής. Η δεύτερη εντολή είναι για
αναμονή του επεξεργαστή ώσπου να ολοκληρωθεί η μετατροπή, με την επόμενη, στη
συνέχεια, τοποθετείται η σημαία ολοκλήρωσης και με την τελευταία εντολή γίνεται
η ανάγνωση του αποτελέσματος από τον ADCH.
Αν θέλουμε να χρησιμοποιήσουμε και τα 10bit του αποτελέσματος της μετατροπής θα πρέπει να γίνει ανάγνωση
και του ADCL και μάλιστα η ανάγνωση του ADCL πρέπει να γίνεται πάντα πρώτα γιατί ο επεξεργαστής θεωρεί
ότι μετά την ανάγνωση του ADCH ολοκληρώνονται οι διαδικασίες ανάγνωσης και απαγορεύει την
πρόσβαση στους καταχωρητές. Στη συνέχεια παρουσιάζεται το παραπάνω παράδειγμα
τροποποιημένο ώστε να γίνεται ανάγνωση και καταχώρηση του αποτελέσματος των 10bit σε μεταβλητή 16bit.
uint8_t AdcOut1;
uint8_t AdcOut0;
int16_t AdcOut10;
//int16_t AdcOut10n;
void InitADC (void)
{
ADCSRA = ((1 << ADEN) | (7 << ADPS0)); // ADC Enable, single conversion, 62.5kHz sample
ADMUX = ((1 << REFS0) | (1 << MUX4)); // AVcc(REFS0:1 = 0->AREF, 1->AVCC,
3->IntRef 2.54V),
// right adjust result,
PA0-PA1
}
void GetADC (void)
{
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // Wait for conversion to
complete
ADCSRA |= (1 << ADIF); // Set complete flag
AdcOut0 = ADCL; // Write data to variable
AdcOut1 = ADCH; // Write data to variable
AdcOut10 = 0;
AdcOut10 = AdcOut1<<8; //
Write high byte to 16bit variable
AdcOut10 |= AdcOut0; // Write
low byte to 16bit variable
if (bit_is_set(AdcOut1,1)) // Check
10bit result sign
AdcOut10 |= 0b1111110000000000; // if negative do sign extension
// AdcOut10n = AdcOut10 + 3; //
Reject CMV if necessary
}
©2017 Πορλιδάς Δημήτριος
|