Acesta este al nouălea tutorial despre învățarea microcontrolerelor PIC folosind MPLAB și XC8. Până acum, am acoperit multe tutoriale de bază, cum ar fi pornirea cu MPLABX, LED-ul care clipeste cu PIC, cronometrele în PIC, interfața LCD, interfața cu 7 segmente etc. Dacă sunteți un începător absolut, vă rugăm să vizitați lista completă a tutorialelor PIC aici și începe să înveți.
În acest tutorial, vom învăța cum să utilizați ADC cu microcontrolerul nostru PIC PICF877A. Majoritatea proiectelor de microcontroler vor implica un convertor ADC (analogic la digital), deoarece este una dintre cele mai utilizate modalități de citire a datelor din lumea reală. Aproape toți senzorii precum senzorul de temperatură, senzorul de flux, senzorul de presiune, senzorii de curent, senzorii de tensiune, giroscopii, accelerometrele, senzorul de distanță și aproape fiecare senzor sau traductor cunoscut produce o tensiune analogică de la 0V la 5V pe baza citirii senzorilor. Un senzor de temperatură, de exemplu, poate emite 2,1 V când temperatura este de 25 ° C și poate crește până la 4,7 când temperatura este de 60 ° C. Pentru a cunoaște temperatura lumii reale, MCU trebuie doar să citească tensiunea de ieșire a acestui senzor de temperatură și să o raporteze la temperatura lumii reale. Prin urmare, ADC este un instrument de lucru important pentru proiectele MCU și permite să aflăm cum îl putem folosi pe PIC16F877A.
Verificați și articolele noastre anterioare despre utilizarea ADC în alte microcontrolere:
- Cum se utilizează ADC în Arduino Uno?
- Tutorial ADC Raspberry Pi
- Interfațarea ADC0808 cu microcontrolerul 8051
ADC în microcontroler PIC PIC16F877A:
Există multe tipuri de ADC disponibile și fiecare are propria viteză și rezoluție. Cele mai frecvente tipuri de ADC sunt flash, aproximare succesivă și sigma-delta. Tipul de ADC utilizat în PIC16F877A este numit ca ADC aproximări succesive sau SAR pe scurt. Deci, să învățăm puțin despre SAR ADC înainte de a începe să îl folosim.
Aproximare succesivă ADC: SAR ADC funcționează cu ajutorul unui comparator și a unor conversații logice. Acest tip de ADC utilizează o tensiune de referință (care este variabilă) și compară tensiunea de intrare cu tensiunea de referință folosind un comparator și diferența, care va fi o ieșire digitală, este salvată de pe bitul cel mai semnificativ (MSB). Viteza comparației depinde de frecvența ceasului (Fosc) pe care funcționează PIC.
Acum, că știm câteva elemente de bază despre ADC, permiteți-ne să deschidem foaia noastră de date și să învățăm cum să utilizați ADC pe MCU-ul nostru PIC16F877A. PIC pe care îl folosim are ADC pe 10 biți pe 8 canale. Aceasta înseamnă că valoarea de ieșire a ADC-ului nostru va fi 0-1024 (2 ^ 10) și există 8 pini (canale) pe MCU care pot citi tensiunea analogică. Valoarea 1024 este obținută cu 2 ^ 10 deoarece ADC-ul nostru este de 10 biți. Cei opt pini care pot citi tensiunea analogică sunt menționați în foaia tehnică. Să ne uităm la imaginea de mai jos.
Canalele analogice AN0 la AN7 sunt evidențiate pentru dvs. Doar acești pini vor putea citi tensiunea analogică. Deci, înainte de a citi o tensiune de intrare, trebuie să specificăm în codul nostru ce canal trebuie utilizat pentru a citi tensiunea de intrare. În acest tutorial vom folosi canalul 4 cu un potențiometru pentru a citi tensiunea analogică la acest canal.
Modulul A / D are patru registre care trebuie configurate pentru a citi datele de la pinii de intrare. Aceste registre sunt:
• Registrul înalt al rezultatelor A / D (ADRESH)
• A / D Result Low Register (ADRESL)
• Registrul de control A / D 0 (ADCON0)
• Registrul de control A / D 1 (ADCON1)
Programare pentru ADC:
Programul pentru utilizarea ADC cu microcontroller PIC este foarte simplu, trebuie doar să înțelegem aceste patru registre și apoi citirea orice tensiune analogic va fi simplu. Ca de obicei, inițializați biții de configurare și să începem cu void main ().
În interiorul void main () trebuie să ne inițializăm ADC utilizând registrul ADCON1 și registrul ADCON0. Registrul ADCON0 are următorii biți:
În acest registru trebuie să pornim modulul ADC făcând ADON = 1 și să pornim ceasul de conversie A / D folosind biții ADCS1 și ADCS0 biți, restul nu va fi setat pentru moment. În programul nostru, ceasul de conversie A / D este selectat ca Fosc / 16, puteți încerca propriile frecvențe și puteți vedea cum se modifică rezultatul. Detalii complete disponibile pe pagina 127 a fișei tehnice. Prin urmare, ADCON0 va fi inițializat după cum urmează.
ADCON0 = 0b01000001;
Acum registrul ADCON1 are următorii biți:
În acest registru trebuie să facem A / D Result Format Select bit mare cu ADFM = 1 și să facem ADCS2 = 1 pentru a selecta din nou Fosc / 16. Ceilalți biți rămân zero, deoarece am planificat să folosim tensiunea de referință internă. Detalii complete disponibile pe foaia tehnică pagina 128. Prin urmare, ADCON1 îl vom seta după cum urmează.
ADCON1 = 0x11000000;
Acum, după inițializarea modulului ADC în funcția noastră principală, permiteți accesul în bucla while și începeți citirea valorilor ADC. Pentru a citi o valoare ADC trebuie parcurși următorii pași.
- Inițializați modulul ADC
- Selectați canalul analogic
- Porniți ADC făcând Go / Done puțin ridicat
- Așteptați ca bitul Go / DONE să scadă
- Obțineți rezultatul ADC din registrul ADRESH și ADRESL
1. Inițializați modulul ADC: Am învățat deja cum să inițializați un ADC, așa că numim doar funcția de mai jos pentru a inițializa ADC
Funcția nulă ADC_Initialize () este următoarea.
void ADC_Initialize () {ADCON0 = 0b01000001; // ADC ON și Fosc / 16 este selectat ADCON1 = 0b11000000; // Tensiunea de referință internă este selectată}
2. Selectați canalul analogic: Acum trebuie să selectăm ce canal vom folosi pentru a citi valoarea ADC. Să facem o funcție pentru aceasta, astfel încât să ne fie ușor să ne deplasăm între fiecare canal din bucla while .
unsigned int ADC_Read (canal de caractere nesemnat) {// **** Selectarea canalului ** /// ADCON0 & = 0x11000101; // Ștergerea biților de selecție a canalului ADCON0 - = canal << 3; // Setarea biților necesari // ** Selecția canalului finalizată *** ///}
Apoi, canalul de selectat este primit în interiorul canalului variabil. In linie
ADCON0 & = 0x1100101;
Selectarea canalului anterior (dacă există) este ștearsă. Acest lucru se face folosind bit și operatorul „&”. Biții 3, 4 și 5 sunt forțați să fie 0, în timp ce ceilalți sunt lăsați să fie în valorile lor anterioare.
Apoi, canalul dorit este selectat prin deplasarea la stânga a numărului canalului de trei ori și setarea biților utilizând bitul sau operatorul „-”.
ADCON0 - = canal << 3; // Setarea biților necesari
3. Porniți ADC făcând Go / Done bit ridicat: Odată ce canalul este selectat, trebuie să începem conversia ADC pur și simplu făcând GO_nDONE bit ridicat:
GO_nDONE = 1; // Inițializează conversia A / D
4. Așteptați ca bitul Go / DONE să scadă: bitul GO / DONE va rămâne ridicat până la finalizarea conversiei ADC, deci trebuie să așteptăm până când acest bit scade din nou. Acest lucru se poate face folosind o buclă while .
while (GO_nDONE); // Așteptați finalizarea conversiei A / D
5. Obțineți rezultatul ADC din registrele ADRESH și ADRESL: Când bitul Go / DONE devine redus, înseamnă că conversia ADC este finalizată. Rezultatul ADC va fi o valoare de 10 biți. Deoarece MCU-ul nostru este un MCU pe 8 biți, rezultatul este împărțit în 8 biți superiori și 2 biți inferiori. Rezultatul superior de 8 biți este stocat în registrul ADRESH, iar cel de 2 biți inferior este stocat în registrul ADRESL. Prin urmare, trebuie să le adăugăm în registre pentru a obține valoarea noastră ADC pe 10 biți. Acest rezultat este returnat de funcția așa cum se arată mai jos:
return ((ADRESH << 8) + ADRESL); // Returnează rezultatul
Funcția completă care este utilizată pentru selectarea canalului ADC, declanșarea ADC și returnarea rezultatului este afișată aici.
unsigned int ADC_Read (canal de caractere nesemnat) {ADCON0 & = 0x11000101; // Ștergerea biților de selecție a canalului ADCON0 - = canal << 3; // Setarea biților necesari __delay_ms (2); // Timp de achiziție pentru încărcarea condensatorului de reținere GO_nDONE = 1; // Inițializează conversia A / D în timp ce (GO_nDONE); // Așteptați conversia A / D pentru a finaliza returnarea ((ADRESH << 8) + ADRESL); // Returnează rezultatul}
Acum avem o funcție care va lua selecția canalului ca intrare și ne va întoarce valoarea ADC. Prin urmare, putem apela direct această funcție în bucla noastră while , deoarece citim tensiunea analogică de la canalul 4 din acest tutorial, apelul funcției va fi după cum urmează.
i = (ADC_Read (4)); // stochează rezultatul adc în „i”.
Pentru a vizualiza ieșirea ADC-ului nostru, vom avea nevoie de un fel de module de afișare, cum ar fi ecranul LCD sau segmentul 7. În acest tutorial folosim un afișaj cu 7 segmente pentru a verifica ieșirea. Dacă doriți să știți cum să utilizați 7 segmente cu pic, urmați tutorialul aici.
Codul complet este prezentat mai jos, iar procesul este, de asemenea, explicat în Video la sfârșitul anului.
Configurare și testare hardware:
Ca de obicei, simulați codul folosind Proteus înainte de a merge cu hardware-ul nostru, schemele proiectului sunt prezentate mai jos:
Conexiunile modulului de afișare cu șapte segmente din 4 cifre cu microcontroler PIC sunt identice cu proiectul anterior, tocmai am adăugat un potențiometru la pinul 7 care este canalul analog 4. Prin variația potului, o tensiune variabilă va fi trimisă la MCU care va fi citit de modulul ADC și afișat pe modulul de afișare pe 7 segmente. Consultați tutorialul anterior pentru a afla mai multe despre afișajul cu 4 cifre cu 7 segmente și interfața acestuia cu PIC MCU.
Aici am folosit aceeași placă de microcontroler PIC pe care am creat-o în Tutorialul intermitent cu LED-uri. După asigurarea conexiunii, încărcați programul în PIC și ar trebui să vedeți o ieșire ca aceasta
Aici am citit valoarea ADC din pot și am convertit-o la tensiunea reală prin maparea ieșirii 0-1024 ca 0-5 volți (așa cum se arată în program). Valoarea este apoi afișată pe segmentul 7 și verificată folosind multimetrul.
Asta e, acum suntem gata să folosim toți senzorii analogici disponibili pe piață, continuați și încercați acest lucru și, dacă aveți probleme ca de obicei, folosiți secțiunea de comentarii, vom fi bucuroși să vă ajutăm.