Questo è il nostro nono tutorial sull'apprendimento dei microcontrollori PIC utilizzando MPLAB e XC8. Fino ad ora, abbiamo coperto molti tutorial di base come iniziare con MPLABX, LED lampeggiante con PIC, Timer in PIC, interfacciamento con LCD, interfacciamento a 7 segmenti ecc. Se sei un principiante assoluto, visita l'elenco completo dei tutorial PIC qui e inizia a imparare.
In questo tutorial, impareremo come utilizzare ADC con il nostro microcontrollore PIC PICF877A. La maggior parte dei progetti di microcontrollore coinvolgerà un ADC (convertitore da analogico a digitale), perché è uno dei modi più utilizzati per leggere i dati dal mondo reale. Quasi tutti i sensori come sensore di temperatura, sensore di flusso, sensore di pressione, sensori di corrente, sensori di tensione, giroscopi, accelerometri, sensori di distanza e quasi tutti i sensori o trasduttori noti producono una tensione analogica da 0V a 5V in base alla lettura dei sensori. Un sensore di temperatura, ad esempio, può emettere 2,1 V quando la temperatura è di 25 ° C e salire a 4,7 quando la temperatura è di 60 ° C. Per conoscere la temperatura del mondo reale, l'MCU deve semplicemente leggere la tensione di uscita di questo sensore di temperatura e metterla in relazione con la temperatura del mondo reale. Quindi ADC è un importante strumento di lavoro per i progetti MCU e consente di imparare come possiamo usarlo sul nostro PIC16F877A.
Controlla anche i nostri articoli precedenti sull'utilizzo di ADC in altri microcontrollori:
- Come utilizzare ADC in Arduino Uno?
- Tutorial ADC Raspberry Pi
- Interfacciamento ADC0808 con Microcontrollore 8051
Microcontrollore ADC nel PIC PIC16F877A:
Sono disponibili molti tipi di ADC e ognuno ha la propria velocità e risoluzione. I tipi più comuni di ADC sono flash, approssimazione successiva e sigma-delta. Il tipo di ADC utilizzato in PIC16F877A è chiamato in breve ADC ad approssimazione successiva o SAR. Quindi impariamo un po 'di ADC SAR prima di iniziare a usarlo.
ADC di approssimazione successiva: L'ADC SAR funziona con l'aiuto di un comparatore e alcune conversazioni logiche. Questo tipo di ADC utilizza una tensione di riferimento (che è variabile) e confronta la tensione di ingresso con la tensione di riferimento utilizzando un comparatore e la differenza, che sarà un'uscita digitale, viene salvata dal bit più significativo (MSB). La velocità del confronto dipende dalla frequenza di Clock (Fosc) su cui sta operando il PIC.
Ora che conosciamo alcune nozioni di base sull'ADC, apriamo la nostra scheda tecnica e impariamo come utilizzare l'ADC sul nostro MCU PIC16F877A. Il PIC che stiamo utilizzando ha un ADC a 10 bit a 8 canali. Ciò significa che il valore di uscita del nostro ADC sarà 0-1024 (2 ^ 10) e ci sono 8 pin (canali) sul nostro MCU in grado di leggere la tensione analogica. Il valore 1024 è ottenuto da 2 ^ 10 poiché il nostro ADC è a 10 bit. Gli otto pin che possono leggere la tensione analogica sono menzionati nella scheda tecnica. Guardiamo l'immagine qui sotto.
I canali analogici da AN0 a AN7 vengono evidenziati. Solo questi pin saranno in grado di leggere la tensione analogica. Quindi prima di leggere una tensione di ingresso dobbiamo specificare nel nostro codice quale canale deve essere utilizzato per leggere la tensione di ingresso. In questo tutorial useremo il canale 4 con un potenziometro per leggere la tensione analogica su questo canale.
Il modulo A / D ha quattro registri che devono essere configurati per leggere i dati dai pin di ingresso. Questi registri sono:
• Registro alto dei risultati A / D (ADRESH)
• Registro basso dei risultati A / D (ADRESL)
• Registro di controllo A / D 0 (ADCON0)
• Registro di controllo A / D 1 (ADCON1)
Programmazione per ADC:
Il programma per utilizzare ADC con PIC Microcontroller è molto semplice, dobbiamo solo capire questi quattro registri e quindi leggere qualsiasi tensione analogica sarà semplice. Come al solito inizializza i bit di configurazione e iniziamo con il void main ().
All'interno di void main () dobbiamo inizializzare il nostro ADC utilizzando il registro ADCON1 e il registro ADCON0. Il registro ADCON0 ha i seguenti bit:
In questo registro dobbiamo accendere il modulo ADC facendo ADON = 1 e accendere il clock di conversione A / D usando i bit ADCS1 e ADCS0, il resto per ora non sarà impostato. Nel nostro programma l'orologio di conversione A / D è selezionato come Fosc / 16 puoi provare le tue frequenze e vedere come cambia il risultato. I dettagli completi sono disponibili a pagina 127 del datasheet. Quindi ADCON0 verrà inizializzato come segue.
ADCON0 = 0b01000001;
Ora il registro ADCON1 ha i seguenti bit:
In questo registro dobbiamo rendere A / D Result Format Select bit high by ADFM = 1 e make ADCS2 = 1 to select the Fosc / 16 again. Gli altri bit rimangono zero poiché abbiamo previsto di utilizzare la tensione di riferimento interna. I dettagli completi sono disponibili a pagina 128 del datasheet. Quindi ADCON1 verrà impostato come segue.
ADCON1 = 0x11000000;
Ora, dopo aver inizializzato il modulo ADC all'interno della nostra funzione principale, entriamo nel ciclo while e iniziamo a leggere i valori ADC. Per leggere un valore ADC è necessario seguire i seguenti passaggi.
- Inizializza il modulo ADC
- Seleziona il canale analogico
- Avvia ADC rendendo Go / Done un po 'alto
- Attendi che il bit Go / DONE si abbassi
- Ottieni il risultato ADC dal registro ADRESH e ADRESL
1. Inizializza il modulo ADC: abbiamo già imparato come inizializzare un ADC, quindi chiamiamo semplicemente questa funzione di seguito per inizializzare l'ADC
La funzione void ADC_Initialize () è la seguente.
void ADC_Initialize () {ADCON0 = 0b01000001; // ADC ON e Fosc / 16 è selezionato ADCON1 = 0b11000000; // È selezionata la tensione di riferimento interna}
2. Selezionare il canale analogico: ora dobbiamo selezionare quale canale useremo per leggere il valore dell'ADC. Creiamo una funzione per questo, in modo che sarà facile per noi passare da un canale all'altro all'interno del ciclo while .
unsigned int ADC_Read (unsigned char channel) {// **** Selezione del canale ** /// ADCON0 & = 0x11000101; // Cancellazione dei bit di selezione del canale ADCON0 - = channel << 3; // Impostazione dei bit richiesti // ** Selezione del canale completata *** ///}
Quindi il canale da selezionare viene ricevuto all'interno del canale variabile. In linea
ADCON0 & = 0x1100101;
La selezione del canale precedente (se presente) viene cancellata. Questo viene fatto utilizzando l'operatore bit per bit "&". I bit 3, 4 e 5 sono forzati a essere 0 mentre gli altri vengono lasciati ai valori precedenti.
Quindi il canale desiderato viene selezionato spostando a sinistra il numero del canale tre volte e impostando i bit utilizzando l'operatore bit per bit o "-".
ADCON0 - = canale << 3; // Impostazione dei bit richiesti
3. Avvia ADC rendendo Go / Done un po 'alto: una volta selezionato il canale dobbiamo avviare la conversione ADC semplicemente rendendo il bit GO_nDONE alto:
GO_nDONE = 1; // Inizializza la conversione A / D
4. Attendere che il bit Go / DONE si abbassi: il bit GO / DONE rimarrà alto fino a quando la conversione ADC non sarà stata completata, quindi dobbiamo aspettare che questo bit ritorni basso. Questo può essere fatto usando un ciclo while .
while (GO_nDONE); // Attendi il completamento della conversione A / D
5. Ottieni il risultato dell'ADC da ADRESH e registro ADRESL: Quando il bit Go / DONE diventa di nuovo basso significa che la conversione ADC è completa. Il risultato dell'ADC sarà un valore a 10 bit. Poiché il nostro MCU è un MCU a 8 bit, il risultato viene suddiviso in 8 bit superiori e 2 bit inferiori. Il risultato a 8 bit superiori viene memorizzato nel registro ADRESH e il 2 bit inferiore viene memorizzato nel registro ADRESL. Quindi dobbiamo sommarli ai registri per ottenere il nostro valore ADC a 10 bit. Questo risultato viene restituito dalla funzione come mostrato di seguito:
ritorno ((ADRESH << 8) + ADRESL); // Restituisce il risultato
La funzione completa che viene utilizzata per selezionare il canale ADC, attivare l'ADC e restituire il risultato è mostrata qui.
unsigned int ADC_Read (canale char non firmato) {ADCON0 & = 0x11000101; // Cancellazione dei bit di selezione del canale ADCON0 - = channel << 3; // Impostazione dei bit richiesti __delay_ms (2); // Tempo di acquisizione per caricare il condensatore di mantenimento GO_nDONE = 1; // Inizializza la conversione A / D while (GO_nDONE); // Attendi il completamento della conversione A / D ((ADRESH << 8) + ADRESL); // Restituisce il risultato}
Ora abbiamo una funzione che prenderà la selezione del canale come input e ci restituirà il valore ADC. Quindi possiamo chiamare direttamente questa funzione all'interno del nostro ciclo while , poiché stiamo leggendo la tensione analogica dal canale 4 in questo tutorial, la chiamata della funzione sarà la seguente.
i = (ADC_Read (4)); // memorizza il risultato di adc in "i".
Per visualizzare l'output del nostro ADC avremo bisogno di una sorta di moduli di visualizzazione come l'LCD o il 7 segmenti. In questo tutorial utilizziamo un display a 7 segmenti per verificare l'output. Se vuoi sapere come usare 7 segmenti con foto segui il tutorial qui.
Il codice completo è fornito di seguito e il processo è spiegato anche nel video alla fine.
Configurazione e test hardware:
Come al solito simuliamo il codice usando Proteus prima di andare effettivamente con il nostro hardware, di seguito viene mostrato lo schema del progetto:
Le connessioni del modulo display a sette segmenti a 4 cifre con microcontrollore PIC sono le stesse del progetto precedente, abbiamo appena aggiunto un potenziometro al pin 7 che è il canale analogico 4. Variando il potenziometro, una tensione variabile verrà inviata all'MCU che verrà letto dal modulo ADC e visualizzato sul modulo display a 7 segmenti. Controlla il tutorial precedente per saperne di più sul display a 7 segmenti a 4 cifre e sulla sua interfaccia con MCU PIC.
Qui abbiamo utilizzato la stessa scheda microcontrollore PIC che abbiamo creato in Tutorial lampeggiante LED. Dopo aver verificato la connessione, carica il programma in PIC e dovresti vedere un output come questo
Qui abbiamo letto il valore ADC dal potenziometro e lo abbiamo convertito nella tensione effettiva mappando l'uscita 0-1024 come 0-5 volt (come mostrato nel programma). Il valore viene quindi visualizzato sul 7 segmenti e verificato utilizzando il multimetro.
Ecco fatto, ora siamo pronti per utilizzare tutti i sensori analogici disponibili sul mercato, vai avanti e prova questo e se hai problemi come al solito usa la sezione commenti, saremo felici di aiutarti.