Il convertitore A/D (Analogico => Digitale) è forse una delle periferiche più interessanti a bordo dei picmicro. Non che sia l’unica periferica interessante, per carità, ma è di sicuro quella che ci può permettere di realizzare dei semplici controlli sull’ambiente circostante (temperatura, umidità, presenza di gas, presenza di luce, suono ecc) in maniera molto semplice e soprattutto procurandoci grandi soddisfazioni.
Tale modulo ha la funzione di acquisire un segnale analogico, ovvero un segnale di tensione variabile nel tempo, dall’esterno e convertirlo in una parola digitale per poterlo quindi processare, effettuarvi dei calcoli o semplicemente visualizzarlo magari su un display o su una barra a led.
L’esempio classico è l’interfacciamento con sonde di temperatura per poter realizzare termometri e termostati. Esistono una varietà di sonde che forniscono segnali analogici: sensori di prossimità ad infrarossi, le LDR (Light Dependent Resistors) utili per realizzare controlli della luminosità ambientale e interruttori crepuscolari, sensori di gas utilizzati in ambito domestico per realizzare allarmi ma anche etilometri ecc.
Le applicazioni sono infinite e l’interfacciamento con un segnale analogico è sicuramente più rapido e semplice da effettuare rispetto a quello di un segnale digitale, sebbene per sua natura sia più soggetto ai disturbi.
Essendo i PIC dispositivi TTL, possono ricevere sugli ingressi del convertitore A/D segnali con tensioni variabili da 0 a 5 volt, non possono quindi accettare tensioni negative e, per tensioni superiori a 5 volt è necessario adottare dei partitori di tensione (realizzati semplicemente con resistenze) in maniera tale da non ricevere mai in ingresso tensioni superiori a 5 volts.
Per ulteriori informazioni su come funziona un partitore di tensione, consultate la voce Partitore di tensione su wikipedia.
In realtà il PIC ha delle protezioni al suo interno per scaricare le tensioni che escono al di fuori di tale range, ma tali protezioni hanno comunque un limite ed è sempre meglio non approfittarne e quindi prevedere già dall’esterno che tali tensioni non vengano superate.
Il 16F877 ha un convertitore A/D a 10bit (in altri pic il convertitore è invece ad 8 bit). Cosa vuol dire? Vuol dire che è capace di convertire un valore di tensione, variabile da 0 a 5 volt, in una parola formata da 10bit, ovvero in valori digitali che spaziano da zero fino al valore 1023 (1024 valori possibili) . Facile farsi due conti per capire qual’è quindi il minimo valore di tensione acquisibile (la sensibilità): 5/1024 = 0.00488V, ovvero circa 5mV. A volte, quando i segnali in ingresso non forniscono almeno 5mV è necessario ricorrere all’utilizzo di amplificatori.
Il convertitore A/D all’interno dei PICMicro è sempre uno solo, ovvero c’è un unico modulo capace di eseguire questa operazione di conversione. Gli ingressi, invece, sono più di uno: i dispositivi a 28pin hanno in genere 5 ingressi analogici, i dispositivi a 40 e 44 pin ne hanno 8. I pin capaci di acquisire un segnale analogico sono quelli contrassegnati sui datasheet con la sigla ANx dove x sta per il numero di porta analogica, il quale non segue la stessa numerazione della porta digitale a cui fa capo.
Alcuni picmicro, come il 16F628A, hanno dei pin contrassegnati come ANx ma in realtà tali pic non possiedono un convertitore A/D vero e proprio bensì un comparatore, che è un qualcosa di leggermente differmente, operante sempre nel campo dell’analogico, ma soltanto in grado di confrontare due valori analogici e di dire quale dei due segnali è più grande dell’altro.
Facile capire che essendoci più di un ingresso analogico ma un solo convertitore, si dovrà fare in modo, ogni volta, di “avvisare” il modulo A/D da quale ingresso analogico prelevare il segnale. Essendo inoltre gli ingressi analogici distribuiti su alcune porte, ci saranno quindi anche dei registri appositi che ci permetterano di dire se una determinata porta, contrassegnata anche come analogica, dovrà comportarsi come un I/O digitale oppure come un ingresso analogico.
I registri che si occupano della conversione analogico/digitale sono soltanto 4, di cui 2 destinati al setup della periferica e 2 che contengono il risultato della conversione.
ADCON0
E’ il registro che si occupa di controllare le operazioni del modulo convertitore, ovvero: l’accensione/spegnimento, la selezione dell’ingresso dal quale prelevare il segnale, l’avvio delle operazioni di conversione ecc. I bit di tale registro sono:
bit 7,6 (ADCS1:ADCS0) : Servono a selezionare (insieme ad un terzo bit, ADCS3, presente sull’altro registro, ADCON1) la frequenza di clock con la quale far funzionare il convertitore. Vedremo in seguito l’importanza di questa scelta e in base a cosa va fatta. I valori possibili sono i seguenti:
Ricordo ancora una volta che Fosc rappresenta la frequenza di Clock del Picmicro.
bit 5,4,3 (CHS2:CHS0) : Eseguono la selezione dell’ingresso analogico dal quale prelevare il segnale da convertire secondo la tabella:
Sto parlando del pin dal quale prelevare il segnale, non del pin da impostare come ingresso analogico, operazione, quest’ultima, che vedremo tra poco.
bit 2 (ADGO, indicato come GO/DONE) : Portando a 1 tale bit, si avvia il processo di conversione. Tale bit viene riportato a zero dall’hardware nel momento in cui la conversione è terminata.
bit 1 : inutilizzato
bit 0 (ADON) : Accende (1) o Spegne (0) il convertitore A/D. Lo si spegne generalmente per consumare meno corrente e/o e quando il modulo non è utilizzato.
ADCON1
E’ il registro che si occupa del settaggio delle porte analogiche. Tramite questo registro, difatti, possiamo dire al pic quali pin devono comportarsi come ingressi analogici.
bit 7 (ADFM) : Serve a selezionare il formato nel quale il valore digitale, risultato dalla conversione, deve essere memorizzato. Abbiamo difatti detto che il risultato della conversione è un valore a 10bit. Essendo il picmicro in questione un sistema ad 8 bit, il valore digitale proveniente dal modulo A/D sarà per forza di cose memorizzato in due registri ad 8 bit, lasciando quindi inutilizzati 6 bit. Tale bit di configurazione serve in pratica a giustificare verso destra o verso sinistra il risultato della conversione, vedremo tra poco come.
bit 6 (ADCS2) : insieme ai bit 7 e 6 del registro ADCON0, serve a selezionare la frequenza di clock del convertitore A/D come abbiamo già visto prima.
bit 5,4 : inutilizzati
bit 3,0 (PCFG3:PCFG0) : hanno la funzione di impostare quali pin devono comportarsi come ingressi analogici secondo la seguente tabella:
La scelta degli ingressi analogici va ovviamente fatta, oltre che con questi 3 bit, anche con i registri TRIS interessati, in pratica bisognerà settare come ingressi le porte che vogliamo come analogiche.
Come vedete dalla tabella, non tutte le combinazioni di pin sono possibili e seguendo la colonna di destra possiamo scegliere la configurazione più adatta alle nostre esigenze in base al numero di canali analogici che necessitiamo per la nostra applicazione. In pratica il numero di destra indica, per il settaggio dei bit PCFG3:PCFG0, il numero di canali analogici disponibili e il numero di riferimenti di tensione. Il convertitore A/D ha di fatti la possibilità di avere dei riferimenti di tensione esterni con i quali effettuare la conversione, questo nel caso in cui volessimo un’applicazione super precisa (a patto che il segnale di riferimento esterno sia anch’esso super preciso!), altrimenti quando il numero di riferimenti esterni è pari a zero viene preso come riferimento la tensione di alimentazione (Vdd) del pic.
Per poter effettuare la conversione, difatti, è necessario confrontare il segnale con una tensione fissa, o meglio con un riferimento di tensione basso e un riferimento di tensione alto. Nel caso in cui non vengano scelte tensioni di riferimento esterne, il segnale verrà confrontato con VSS e VDD.
Vediamo dalla tabella, ad esempio, che con il settaggio dei bit PCFG3:PCFG0 al valore 011x (dove la x può stare indifferentemente a 0 o 1), le porte capaci di essere ingressi analogici, saranno invece tutte digitali, quindi nessun canale analogico disponibile. Mettendo invece a zero i 4 bit, tutte le porte contrassegnate come AN, saranno tutte ingressi analogici.
Selezionando, infine, una configurazione che prevede riferimenti di tensione esterni, tali riferimenti andranno applicati ai pin del picmicro contrassegnati con le sigle VRef (Vref+ come tensione di riferimento alta e Vref- come tensione di riferimento bassa).
ADRESH e ADRESL
Sono i due registri che contengono il risultato della conversione (nei pic con convertitore ad 8 bit c’è invece un unico registro chiamato soltanto ADRES). A seconda di come abbiamo impostato il bit ADFM, il risultato sarà memorizzato in maniera diversa:
Se abbiamo messo ADFM ad 1, il risultato verrà giustificato verso destra, ovvero gli 8 bit meno significativi del risultato saranno memorizzati in ADRESL e i due bit più significativi (il bit 9 e il 10 del risultato) saranno memorizzati in ADRESH come bit 0 e 1, i rimanenti 6 bit di ADRESH saranno posti a zero. Questa è in genere l’opzione più utilizzata perchè segue lo standard. Se invece ADFM=0, il risultato viene giustificato verso sinistra e verrà in pratica letto al contrario rispetto all’impostazione precedente.
Se utilizziamo quindi l’impostazione ADFM=1, per ottenere il valore a 16 bit sarà necessario sommare il valore del registro ADRESL a quello del registro ADRESH shiftato di 8 posizioni a sinistra, in quanto i bit più significativi del risultato si trovano in posizione 0 e 1 e devono invece trovarsi in posizione 8 e 9:
INT valore; valore=ADRESL + (ADRESH<<8);
Schema a blocchi del convertitore A/D
Possiamo quindi schematizzare con un diagramma come è costituito il modulo A/D:
Vediamo a destra gli ingressi analogici, tramite l’opportuna impostazione dei bit CHS2:CHS0 decidiamo quale “interruttore” chiudere per far giungere al modulo il segnale da campionare, ci sono quindi gli “interruttori” che, tra le altre cose, permettono di impostare la tensione di riferimento. Per le nostre prove utilizzeremo esclusivamente il riferimento interno, quindi nessuna configurazione che preveda riferimenti di tensione esterni.
Principio di funzionamento del convertitore A/D
Vediamo come è costituito il modulo convertitore A/D all’interno del PIC:
Sulla sinistra abbiamo la sorgente che fornisce il segnale analogico da campionare (VAIN), collegata al pin ANx. Tale sorgente ha una sua impedenza (Rs) che non va trascurata. Il datasheet dice difatti che tale impedenza non deve essere superiore a 10KΩ per poter avere una corretta acquisizione. Subito dopo il pin ANx abbiamo quindi un condensatore (Cpin) che ha la funzione di filtrare i disturbi, e due diodi di protezione che scaricano eventuali tensioni superiori a VDD o inferiori a VSS. Segue quindi il vero e proprio circuito di campionamento, preceduto da una leggera perdita di corrente (I leakage) dovuta alle giunzioni interne.
In condizioni normali, lo switch di campionamento SS è chiuso permettendo a CHOLD, di potersi caricare allo stesso livello di tensione presente sull’ingresso analogico da convertire. Lo Switch di campionamento ha anch’esso una propria impedenza (Rss) che è inversamente proporzionale alla tensione VDD di alimentazione del picmicro.
Quando viene avviata la conversione (ADGO=1), SS viene aperto in maniera tale da isolare CHOLD dalla linea e avviare quindi il processo di conversione che permette di tramutare il livello di tensione presente in CHOLD in un valore digitale. La conversione del valore analogico in una parola di 8 o 10 bit viene eseguita tramite un metodo chiamato ad approssimazioni successive.
Al termine della conversione il valore digitale è presente nei registri ADRESH e ADRESL, viene settato il flag di interrupt di fine conversione analogico/digitale (ADIF), ADGO viene rimesso a zero e SS viene richiuso per permettere a CHOLD di ricaricarsi e tenersi quindi pronto per un’altra eventuale conversione.
Per effettuare quindi una corretta acquisizione e conversione del segnale bisogna rispettare alcune tempistiche ben precise: abbiamo un tempo di acquisizione, che è necessario per poter caricare a piena capacità il condensatore di campionamento, ed un tempo di conversione, che inizia quando settiamo ADGO e termina quando viene settato ADIF, e rappresenta il tempo necessario al modulo A/D per poter effettuare l’operazione di conversione. La somma dei due tempi prende il nome di tempo di campionamento.
Le impedenze Rs e Rss influiscono sul tempo di acquisizione in maniera non trascurabile.
Chi ha studiato elettronica sa, difatti, che il tempo di carica di un condensatore è uguale a 5*R*C
Quanto minore è l’impedenza di ingresso del segnale, meno tempo ci vorrà per caricare il condensatore e quindi tanto inferiore sarà il tempo di acquisizione. Con un’impedenza di ingresso di 50Ω si ha un tempo di acquisizione (ripeto: un tempo di carica di CHold) tipico di circa 10.6µS, con un’impedenza di 10KΩ il tempo tipico sale a 19.7µS.
Tale tempo, purtroppo, non viene gestito in maniera automatica dal pic e si capisce, quindi, che, appena finita una conversione non possiamo avviarne immediatamente un’altra perchè non diamo al condensatore di campionamento il tempo necessario per ricaricarsi. Tra una conversione e l’altra, pertanto, dovremo rispettare un’attesa che è ragionevole scegliere tra 10 e 20µS.
Il tempo di conversione, invece, è funzione di un parametro chiamato TAD, che rappresenta il tempo necessario per convertire un unico bit o, in altre parole, il tempo di conversione per bit. La conversione AD richiede un tempo di 12TAD per una conversione completa a 10bit:
TAD rappresenta in pratica la frequenza di clock scelta per il convertitore A/D (impostata tramite i bit ADCS2:ADCS0 nei registri ADCON1 e ADCON0). La scelta del TAD va fatta in maniera accurata per alcuni semplici motivi:
- Bisogna che sia rispettato, per TAD, un valore minimo di 1.6µS. Quindi un clock troppo rapido non potrebbe rispettare tale requisito.
- TAD non deve nemmeno essere troppo elevato: insieme al segnale da campionare viene difatti inevitabilmente acquisito anche del rumore e con tempi maggiori tale fattore aumenta sempre di più in maniera non trascurabile; inoltre potrebbe accadere che il condensatore di campionamento si scarichi prima che la conversione sia terminata. In entrambi i casi il valore restituito dal convertitore è sicuramente corrotto.
Nella seguente tabella possiamo vedere alcuni valori di TAD in funzione del quarzo utilizzato per il clock del pic e del settaggio di ADCS1:ADCS0 (Nota: tale tabella non riporta tutti i valori di clock per il convertitore AD ed assume che ADCS2=0)
Notiamo alcuni valori ombreggiati: tali impostazioni non possono essere utilizzate perchè TAD risulta troppo breve o troppo lungo e causa quindi problemi per quanto detto prima.
Oltre al valore di TAD derivato dal clock è possibile selezionare una modalità in cui TAD viene ricavato da un circuito oscillatore RC interno al convertitore. Nei sistemi in cui il dispositivo entrerà in modalità sleep dopo l’avvio della conversione A/D e contemporaneamente operanti ad un clock superiore ad 1MHz, è richiesto l’utilizzo della sorgente di clock RC. In questo modo, il rumore digitale proveniente dai moduli in SLEEP viene bloccato: questo metodo fornisce l’accuratezza maggiore. Si capisce quindi che il convertitore AD è l’unico capace di continuare a funzionare anche quando tutto il resto del pic è “addormentato”.
La sorgente di clock RC fornisce un TAD tipico di 4µs (oscillante tra 2 e 6µS).
Dalla tabella precedente possiamo quindi vedere che per un pic operante alla frequenza di 20MHz è giusto scegliere la sorgente di clock RC oppure 32Tosc (che fornisce un TAD proprio di 1.6µS). Per altri valori di quarzo, e altre impostazioni fare i calcoli è semplice. Basta calcolare TOSC (che è l’inverso della frequenza del quarzo del picmicro) e quindi moltiplicarlo per 2, per 4, per 8 ecc e vedere quindi qual’è il valore migliore.
Settaggio e avvio del modulo A/D
- Configurare il modulo A/D impostando opportunamente i registri ADCON0 e ADCON1.
- Configurare le porte da usare come analogiche portando ad 1 i bit del relativo registro TRIStato.
- Se si desidera intercettare la fine conversione in una routine di interrupt procedere come segue oppure proseguire dal punto 4:
Portare a 0 il bit ADIF (A/D Interrupt Flag) del registro PIR1.
Portare a 1 il bit ADIE (A/D Interrupt Enable) del registro PIE1, in maniera tale che si possa scatenare un interrupt quando la conversione è terminata.
Portare a 1 il bit PEIE (Peripheral interrupt Enable) del registro INTCON, in maniera tale da attivare gli interrupt provenienti dalle periferiche esterne, quale appunto è il convertitore A/D
Portare a 1 il bit GIE (Global Interrupt Enable) del registro INTCON. - Dare un ritardo di almeno 10µS per far caricare correttamente il condensatore di campionamento del modulo AD
- Avviare la conversione portando a 1 il bit GO/DONE di ADCON0 (ADGO=1).
- Attendere il completamento della conversione A/D:
Aspettando che ADGO=0 nel caso in cui gli interrupt non li abbiamo attivati
oppure, se abbiamo previsto una routine di interrupt e abbiamo abilitato l’interrupt del modulo A/D, intercettando il settaggio di ADIF (ADIF=1).ADIF viene comunque settato anche se il relativo interrupt è disabilitato, ma nel caso in cui non stiamo usando l’interrupt, è più conveniente utilizzare ADGO perchè non ci dobbiamo preoccupare di resettarlo.
- Leggere il valore accedendo ai registri ADRESH e ADRESL
- Se stiamo sfruttando l’interrupt, riportare a zero ADIF (ADIF=0)
Il valore ottenuto sarò quindi un valore numerico da 0 a 1023 rappresentativo della tensione in ingresso, sapendo che ogni bit del valore ottenuto vale circa 5mV, fare il calcolo della tensione in ingresso è abbastanza semplice.
Nella prossima parte di questa lezione vedremo come mettere in pratica la teoria.
Ringrazio pubblicamente Andrea Nalesso per la preziosa collaborazione fornita e per l’interessamento
Articoli che potrebbero interessarti
Se desiderate che settorezero continui a rimanere gratuito e fruibile da tutti, non copiate il nostro materiale e segnalateci se qualcuno lo fa

Questo sito e tutto il suo contenuto sono distribuiti sotto la licenza 
















#1 da S.D.R. il 4 marzo 2010
Bel lavoro Giovanni ;-)
#2 da Giovanni Bernardo il 5 marzo 2010
Bel lavoro S.D.R. ;)
#3 da mcgyver86 il 5 marzo 2010
Spettacolare… Grandissimo Giovanni, veramente ottima lezione.. Grazie per il tuo lavoro, piano piano sto entrando sempre di + nel mondo dei PICmicro!!
Posso suggerire una lezione? Interfacciare un PICmicro ad un display LCD e tastiera PS/2 (quella dei pc per intenderci!).. Naturalmente è solo una idea!!
Grazie, saluti
Alessio.
#4 da Giovanni Bernardo il 5 marzo 2010
Beh…tutto si può fare, e se qualcuno mi da un aiuto si possono fare grandi cose
#5 da S.D.R. il 5 marzo 2010
Ciao mcgyver86 ,
Ma a che tipo di LCD vuoi collegarlo ?
#6 da Giovanni Bernardo il 6 marzo 2010
Penso che collegarlo a un display hd44780 compatibile è la cosa più semplice. Le tastiere PS/2 utilizzano un protocollo di comunicazione seriale sincrono. Hanno una linea di clock e una linea dati. Inviano il bit di start, sul fronte di discesa del clock inviano il bit, 8 bit in totale per il tasto premuto (spero che almeno lettere e numeri seguano in qualche modo il codice ascii, adesso non lo so, mi devo documentare meglio), seguono quindi un bit di parità e un bit di stop. 11bit in totale. Funziona un po’ come l’I2C insomma e non dovrebbe essere difficile usare una tastiera. Proveremo pure questo.
#7 da MayTs il 13 aprile 2010
Non ho capito esattamente come si calcola il TOSC:
io per esempio sto usando un quarzo da 8 Mhz(uso un quarzo da 8 mhz, solo perché riesco a far scattare l’interrupt del timer esattamente ogni millisecondo, e per quello che sto facendo preferisco avere delle tempistiche più precise a discapito della velocità di esecuzione).
quindi usando il quarzo da 8 mhz come calcolo il TOSC e di conseguenza la frequenza ottenuta con tale TOSC?
Inoltre leggendo il datasheet mi sembra di aver capito che utilizzando un quarzo da 5 Mhz il massimo TOSC utilizzabile sia a 8TOSC, ma visto che nella tabella hai riportato anche il 32 TOSC impostandolo a 32 si rischia qualcosa?(quest’ultima domanda è solo a titolo informativo)
Grazie in anticipo per le delucidazioni
#8 da Giovanni Bernardo il 13 aprile 2010
TOSC = periodo, FOSC= Frequenza. TOSC=1/FOSC.
Se esprimi FOSC in Hz TOSC è in secondi.
Nel tuo caso il quarzo è da 8MHZ? FOSC=8MHz=8000000Hz, quindi TOSC=1/8000000Hz = 125 nanosecondi.
Se imposti 32Tosc ottieni: 32*125 = 4000 nanosecondi = 4 microsecondi. Quindi per il tuo scopo va bene. 8TOSC ti porterebbe a 1microsecondo ed è troppo poco, 16TOSC a 2microsecondi e pure va bene.
O si scrive 32TOSC o FOSC/32 è la stessa cosa in quanto TOSC=1/FOSC.
Con il quarzo da 5MHz, 8 TOSC è il minimo non il massimo, perchè con un valore di TOSC più basso ottieni un tempo troppo rapido, come spiegato nell’articolo. Spero di essere stato chiaro.
#9 da MayTs il 13 aprile 2010
Chiarissimo e Gentilissimo come sempre.
Grazie mille.
Manuel
#10 da Giovanni Bernardo il 13 aprile 2010
Grazie a te ;)
#11 da Cristianoscr il 22 luglio 2010
Eccomi che torno all’attacco! Il 12f675 ha porte analogiche? Sul datasheet non trovo niente al riguardo! Se le ha come faccio ad attivarle?
#12 da Cristianoscr il 22 luglio 2010
Dopo lungo penare ho scoperto che avevo tutto sotto gli occhi (dio cos’ho per la testa in questo periodo???) ma nel datasheet del 12f675 la frequenza di conversione A\D la devo impostare in un altro registro?? Precisamente nel registro ANSEL?
Piano piano sto imparando anch’io a leggere i datasheet…. A breve ti arriverà una cassa di moretti ;)
#13 da Giovanni Bernardo il 22 luglio 2010
Si il registro ANSEL ti permette di impostare singolarmente le porte da usare come analogiche. L’ho spiegato nell’esempio dei relè controllati via wireless in cui faccio uso di un 16F88 che pure ha questa caratteristica
#14 da damiano il 6 dicembre 2010
volevo chiedere alcune cose………
devo realizzare un firmware per pic, dove devo far scattare un interrupt che si aziona da input esterno( premendo un interruttore) e un altro che si attiva dall’ adc…… ovviamente quando ATTIVO IL pulsante devo fare un cosa, e con l’adc ne devo fare un altra, praticamente cause e funzioni da assegnare indipendenti……quello che volevo sapere è questo, l’interrupt è singolo, e quindi ogni volta devo verificare da cosa è scaturito e poi assegnarci un parte di programma. oppure gli interrupt, sono già differenti, è quindi per ogni causa ho un interrupt diverso??? con parti di software separati?
grazie spero di essere stato chiaro! aspetto risposte.vi ringrazio per la disponibilità!
#15 da Giovanni Bernardo il 6 dicembre 2010
Sui PIC10/12/16 la “funzione” di interrupt è una sola. Al verificarsi di qualsiasi interrupt, il programma salta all’unico interrupt vector presente, che viene “agganciato” dalla funzione void interrupt [nome_a_piacere](void). In questa funzione, poi, sei tu che devi discernere QUALE interrupt ha fatto eseguire il salto all’interrupt vector con una serie di IF come già spiegato.
Spero che prima di fare questa domanda tu abbia letto la lezione sugli interrupt: http://www.settorezero.com/wordpress/corso-programmazione-picmicro-in-c-lezione-4-cosa-sono-gli-interrupt-concetti-di-base-per-sistemi-operativi-multitasking-su-picmicro/
Sui PIC18, invece, hai due livelli di interrupt: alta e bassa priorità. Ad ogni tipo di interrupt puoi assegnare una priorità alta o una bassa. Ci sono quindi due interrupt vector (alto e basso). Anche qui se hai due interrupt con la stessa priorità, andrai a discernere l’interrupt con una serie di IF.
I pic a 16bit (pic24 e dspic), hanno 7 livelli di di priorità e ogni singolo interrupt ha la sua esclusiva funzione di gestione (con il C30).
#16 da damiano il 6 dicembre 2010
si avevo già letto la lezione, ma pensavo che gli interrupt tra adc è input esterni erano diversi.
cmq ti ringrazio molto per la riapoata e per il corso!
ancora grazie
damiano!
#17 da aigor il 25 dicembre 2010
Domanda, non e’ possibile usare uno switch/case per discriminare chi ha generato l’interrupt?
#18 da Giovanni Bernardo il 25 dicembre 2010
Che senso ha usare uno switch case ? Uno switch case si utilizza per discriminare vari valori che può avere UNA variabile… Al limite lo si potrebbe fare dicriminando il valore di un registro nel caso in cui i flag di interrupt si trovano tutti nello stesso registro… ma poi? Se si verificano due interrupt insieme che fai.. uno lo processi e l’altro no?
#19 da Vito1984 il 25 gennaio 2011
Ciao Giovanni,
devo campionare un’onda sinusoidale raddrizzata da 50Hz (periodo dunque 20ms) in un intervallo di tempo che va da 4ms a 6ms per OGNI semionda. Ho bisogno di venti campioni alla volta (uno a 4 ms, uno a 4.1 ms, eccetera, fino a 6ms). Sto usando un quarzo a 4Mhz e il pic16F877A, il mio problema è che ciascuna conversione dura molto più di 0.1ms… quindi non riesco assolutamente a effettuare 20 campionamenti in 2ms… In particolare mi sono accorto che il tempo di esecuzione dell’istruzione
valoreAN = ADRESL+(ADRESH<<8);
è di quasi 0.4ms… come potrei fare x risolvere? posto la routine di conversione:
void ADC_Conversion(void)
{
CHS0=0;
CHS1=0;
CHS2=0;
ADCON1 =0b10001000; //TENSIONI DI RIFERIMENTO ESTERNE
//seleziona il clock per la conversione 4MHz/32
ADCS0 = 0;
ADCS1 = 1;
//Accende l'A/D
ADON = 1;
__delay_us(30);
//start Conversion
ADGO=1;
//aspetta la fine della conversione, il bit ADGO torna a 0 da solo
while(ADGO){}
valoreAN=0; //inizializzo la variabile;
valoreAN = ADRESL+(ADRESH<<8); //assegno alla variabile valoreAN il contenuto a 10 bit che sta nei due registri
}
Grazie
#20 da Giovanni Bernardo il 26 gennaio 2011
Hai provato con un quarzo da 20MHz? Queste cose comunque si fanno coi dsPic che hanno un ADC ultraveloce.
#21 da Video Lab il 4 marzo 2011
Ciao Giovanni,
come sempre grazie grazie grazie.
Ho letto e straletto questa lezione, e mi sono aiutato sia con il datasheet che con il file settings.h che hai postato con l’esempio della lezione successiva… però non capisco una cosa..
Nel file setting hai settato il registro ADCON1 così: ADCON1=0b10001110 quindi
PCFG0= 0
PCFG1= 1
PCFG2= 1
PCFG0= 1
e commenti così: // abbiamo selezionato tutte le porte come analogiche
Nel tuo esempio hai utilizzato come porta la AN1..
però andando a vedere la tabella del datasheet e quella che hai postato qui sopra non sembrerebbe così
bit AN7 AN6 AN5 AN4 AN3 AN2 AN1 AN0 Vref+ Vref- C/R
1110 D D D D D D D A VDD VSS 1/0
Dalla tabella sembrerebbe che come ingresso analogico settiamo solo AN0..
Grazie per l’attenzione.
Nino
#22 da Giovanni Bernardo il 5 marzo 2011
Quella è la selezione del canale da cui leggere. Puoi leggere un solo canale per volta.
#23 da Giovanni Bernardo il 5 marzo 2011
Tu hai un registro in cui setti quali porte devono funzionare come analogiche, ed è una cosa. E un altro registro in cui setti la porta da cui leggere. Hai un solo modulo A/D e più canali analogici, il modulo A/D può leggere un solo canale per volta quindi ogni volta vai ad impostare un diverso canale analogico da leggere, qui ho settato tutti come analogici ma leggo da uno soltanto. Leggiti anche l’esempio che ho scritto qui per capire meglio: http://www.settorezero.com/wordpress/corso-programmazione-picmicro-in-c-approfondimenti-leggere-piu-canali-analogici-insieme-ed-inviare-i-risultati-su-seriale/
#24 da Video Lab il 5 marzo 2011
Che decidi di leggere da un solo canale con il settaggio di ADCON0 così ADCON0=0b10001001;
lo avevo capito e precisamente scegli AN1
Con ADCON1 decidi quali sono le porte che vuoi usare coma Analogiche, e fin qui tutto ok
però guardando la tabella di ADCON1 se setto così ADCON1=0b10001110;
praticamente dico che tutte le porte sono Digitali, esclusa AN0. Giusto ?
Ma nel tuo esempio vai a leggere da AN1…. e secondo le impostazioni di ADCON1 risulterebbe settata come ingresso Digitale…
Io non capisco questo…. mi tornerebbe tutto se ADCON0 fosse settato così ADCON0=0b10″000″001 e non 0b10″001″001
Scusa se sono duro di comprensorio.
E grazie per la pazienza.
Nino
#25 da Giovanni Bernardo il 5 marzo 2011
Scusa ma a quale esempio ti stai riferendo? Non sto capendo niente. In questo articolo non c’è esempio del convertitore A/D.
Se metti ADCON1=0b10001110 allora i primi 4 bit, essendo messi a 1110, selezionano soltanto AN0 come ingresso analogico e il resto sono digitali. Fin qui ok. Poi che ho scritto sbagliato nei commenti potrebbe essere perchè spesso riutilizzo codice già scritto e mi salta di correggere i commenti. Se mi fai sapere a quale codice ti riferisci mi fai un piacere, perchè così non sto capendo niente.
#26 da Video Lab il 5 marzo 2011
Scusa per il casino che ho postato qui ma con il copia/icolla è venuta una porcata, cancella pure se puoi, i file sono quelli che hai postato del progetto del trimmer con la barra di led. (la seconda parte della lezione)
Scusa ancora, e se non ti colleggo in serata, buon week-end.
Nino
#27 da sigi91 il 8 marzo 2011
{{Chi ha studiato elettronica sa, difatti, che il tempo di carica di un condensatore è uguale a R*C}}
SBAGLIATO !!!
è uguale a 5*R*C (R*C= tau)
#28 da Giovanni Bernardo il 8 marzo 2011
Scusa la dimenticanza! Corretto… Bisogna stare attenti con gli studenti freschi!! :D
#29 da frabeltra il 15 aprile 2011
domandona,
ma di default le porte RAx–>ANx sono messe come digitali o analogiche? o alla fime e sempre meglo setterle in qualunque caso?
#30 da Giovanni Bernardo il 15 aprile 2011
Come analogiche, In ogni caso basta vedere le tabelle iniziali del datasheet in cui è indicato lo stato al reset (POR Power On Reset) di tutti i registri. Vedi anche quest’altro articolo: http://www.settorezero.com/wordpress/picmicro/perche-il-led-che-ho-collegato-sulla-porta-rxy-non-si-accende-disattivare-comparatore-e-convertitore-ad/
#31 da marco2551 il 28 dicembre 2011
Ciao, ho una domanda un po particolare, non riesco a capire una cosa.
Ho visto che se setto una porta come digitale (tramite ADCON1) e tento di fare una lettura ADC naturalmente non funziona.
Al contrario se setto la porta come analogica mi viene permesso di settare tale porta non come input ma come output (tramite TRISA) e inoltre posso portarla a livello logico alto.
Quindi mi chiedo, cosa succede all’interno del pic quando setto una porta come digitale o analogica tramite il registro ADCON ??
#32 da apacchio il 20 gennaio 2012
Ciao, innanzitutto ti ringrazio per questa guida ! Volevo chiederti riguardo il settaggio del ADCON1.
Quando usiamo l’ ADC e il comparatore dobbiamo abilitare i pin delle porte ANx come ANALOGICI (ovvero gli ultimi 4 bit = 0000, come di default), mentre se non usiamo ADC e comparatore li settiamo come DIGITALI, in modo da usarli normalmente ad esempio per lampeggiare un led…. giusto ?
Spero di essere stato chiaro e grazie anticipamente per la risposta
#33 da Giovanni Bernardo il 20 gennaio 2012
Si… Il comparatore poi si imposta con i registri CMCON
#34 da angelorosso il 5 marzo 2012
Ciao Giovanni, sto lavorando ad un programmino per PIC 12F683, imposto il registo ADCON0 per definire le modalità di conversione A\D ma nel main, quando voglio settare a 1 il bit per far partire la conversione (GO-DONE”negato”) non mi riconosce il nome usato. Ho provato con:
- GO
-ADGO
-ADCON0.GO
-ADCON0_GO
Dove sbaglio? non c’è un metodo più semplice per impostare un singolo bit di un registro?
#35 da Giovanni Bernardo il 5 marzo 2012
L’ultimo articolo che ho scritto, proprio relativo al PIC12F683 e guardacaso che utilizza il modulo AD, è già andato “al vento”?
#36 da angelorosso il 5 marzo 2012
No, non è andato al vento…non scrivo cose a caso. Nel listato .C del progetto (immagino ti riferisci all’alcool test) usi le seguenti istruzioni
[quote]GO=1; // start conversion
while(GO); // waiting end conversion
advalue=ADRESL+(ADRESH<<8);[/quote]
dopo una rapida ricerca nel file pic12f683.h mi sono accordo che quel valore non lo chiama "GO" ma "GODONE", evidentemente abbiamo due versioni differenti di HI-TECH C .
Già che siamo in tema, per leggere il valore "advalue" usi il comando "ADRESL+(ADRESH<<8)", non avendone compreso bene il significato ho sperimentato il comando "(256*ADRESH) + ADRESL;" ovviamente con giustificazione a destra….pensi restituisca un valore corretto?
#37 da Giovanni Bernardo il 5 marzo 2012
Allora nell’header non hai visto bene, perchè ci sono due definizioni equivalenti (GO e GO_nDone) e puoi usare una o l’altra, tanto fanno riferimento alla stessa locazione di memoria. Tutto questo ammesso che stiamo parlando del PICC versione 9.83. Se usi la giustificazione a destra il risultato lo leggi come ho scritto io. Leggi l’articolo sul bitshift per maggiori informazioni.
#38 da Giovanni Bernardo il 5 marzo 2011
Allora… Usando la freedomII, il trimmer è collegato su AN1. Quindi l’impostazione di ADCON0 è corretta, perchè legge da AN1, è sbagliata l’impostazione di ADCON1… puoi mettere i primi 4 bit a 0000 e così sono tutte analogiche oppure hai ampia scelta… Quell’impostazione probabilmente mi è rimasta da qualche prova che ho fatto con il sensore che sta sulla freedomII
#39 da Giovanni Bernardo il 5 marzo 2011
Il fatto che fin’ora nessuno se ne sia accorto, comunque, conferma la mia tesi che al 90% delle persone importa solo scaricarsi i sorgenti, per poi magari ripubblicarli sui “siti a punteggio”. Ti ringrazio, al più presto cerco di correggere il sorgente… caso mai qualcun altro trovasse il difetto…
#40 da MBrix il 28 aprile 2011
…o che magari legge l’articolo e poi ci ragiona su e lo adatta al proprio micro o alla propria applicazione.
In ogni caso non credo che le persone che sfruttano gli altri possano mai cambiare, ma quali soddisfazioni avranno mai???
Ti ringrazio per questi articoli molto, molto, molto utili per chi come me da autodidatta cerca di imparare e si compiace del primo led lampeggiante! Forza!
#41 da Giovanni Bernardo il 29 aprile 2011
Ma così pure è giusto… voglio dire… Quello che non è giusto è sfruttare il lavoro degli altri spacciandolo per proprio e ancor peggio usarlo per fini davvero futili quali recuperare un paio di punti in un sito per poter accedere ai livelli alti! E’ tutto il sistema italiano che è sbagliato