Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

PIC18 problemi su Tad dell'ADC

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] PIC18 problemi su Tad dell'ADC

Messaggioda Foto Utentethexeno » 26 nov 2013, 22:13

Ciao! Sto provando ad usare l'adc sul Pierin.
sicuramente è una cavolata: inizializzandolo e anche accendendolo, è come se non partisse a convertire e rimane nel loop di controllo del flag. Ma rimuovendo questo loop, si pianta lo stesso. In debug dice che ho un Tad troppo veloce, eppure ho inizializzato tutto. Persino esempi su pic18 sono fatti così come ho fatto io... sotto il codice. E' una versione quasi "dinamica", ma le operazioni di bitwise sono corrette (vedo dal debug) e l'errore persiste anche assegnando il tutto in modo statico.

Codice: Seleziona tutto
void main(void)
{
    /* Configure the oscillator for the device */
  //  ConfigureOscillator();
   
    /* Initialize I/O and Peripherals for application */
    InitApp();
    usart_init();
    init_adc(2); // !!!!!!!!!!!!!!!!!  3V3 ONLY!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  //  init_pwm();
    /* TODO <INSERT USER APPLICATION CODE HERE> */
    printf("EPIC!");

    while(1)
{

   ADCON0bits.GO = 1;
  while(ADCON0bits.GO);
  __delay_ms(15);
  a = ADRESH;        // 'a' should be 16bit int type
  a = a << 8;
  a |= ADRESL;
  printf("ADC: %d\n", a);
             
}


Inizializzazione

Codice: Seleziona tutto
void init_adc(uint8_t ch)
{
    //!!!!!!!!!!!!!!!!!!!!!!!!!!! NON E' 5V TOLERANT!!!!!!!!!!!!
    //12 bit
    ADCON0 |= (ch << 2);
    ADCON1 = 0x06; //      fosc/64
    ANCON0 |= ~(1 << ch); //shifto a sx 1 di ch posizioni e complemento per avere
                    // 0 sul canale scelto (analog behav)
   
    if ((ch - 8)>= 0){ //REsetto gli ultimi 4 bit, stessa cosa
    ANCON1 |= ~(1<<(ch-8)) ;
    ANCON1bits.VBGEN = 0; // mantengo a 0 quel che deve stare a 0
    }
    ADCON0bits.ADON = 1; //ADC [ON]
    PIE1bits.ADIE = 1; // int on
    IPR1bits.ADIP = 1; // high prior

}


Andando a seguire alla lettera la sequenza di inizializzazione non cambia il risultato, ho quindi postato la prima versione, che tiene solo conto dell'ordine dell'accensione dell'adc. Comunque, vi posto anche l'altra, statica e che segue il datasheet.

Codice: Seleziona tutto
void init_adc(uint8_t ch)
{
    //!!!!!!!!!!!!!!!!!!!!!!!!!!! NON E' 5V TOLERANT!!!!!!!!!!!!
    //12 bit
   
   
   // ANCON0 |= ~(1 << ch); //shifto a sx 1 di ch posizioni e complemento per avere
                    // 0 sul canale scelto (analog behav)
    ANCON0 = 0x00;
    ANCON1 = 0x00;
  //  if ((ch - 8)>= 0){ //REsetto gli ultimi 4 bit, stessa cosa
  //  ANCON1 |= ~(1<<(ch-8)) ;
  //  ANCON1bits.VBGEN = 0;
  //  }
    ADCON0 = 0b00001000;
    ADCON1 = 0b00001110; //      fosc/64
   
    ADCON0bits.ADON = 1; //ADC [ON]
    PIE1bits.ADIE = 1; // int on
    PIR1bits.ADIF = 0;
    IPR1bits.ADIP = 1; // high prior
  INTCONbits.GIEH = 1;  // high attivo ALL INT attivi
  INTCONbits.GIEL = 1;  // LOW attivo


Ovviamente nemmeno il flag di interrupt si modifica. Avete dei pareri? Insomma, stampa soltanto "EPIC!" e basta...

Grazie a tutti!
Avatar utente
Foto Utentethexeno
235 5 9
Frequentatore
Frequentatore
 
Messaggi: 298
Iscritto il: 12 apr 2010, 18:28

2
voti

[2] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto UtentePaolino » 27 nov 2013, 0:02

Non ho sotto mano il datasheet del PIC in questione. L'unica cosa che mi viene da suggerire è di non abilitare l'interrupt se poi vai a leggere i valori in polling.

Togli la riga:
Codice: Seleziona tutto
PIE1bits.ADIE = 1;


oppure, scrivi:
Codice: Seleziona tutto
PIE1bits.ADIE = 0;


Ciao.

Paolo
"Houston, Tranquillity Base here. The Eagle has landed." - Neil A.Armstrong

-------------------------------------------------------------

PIC Experience - http://www.picexperience.it
Avatar utente
Foto UtentePaolino
32,6k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 4226
Iscritto il: 20 gen 2006, 11:42
Località: Vigevano (PV)

0
voti

[3] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto Utentethexeno » 28 nov 2013, 20:15

Ha! mi hanno di nuovo fregato queste ISR vuote che credevo venissero ignorate. Funzionicchia :D

Solo che non capivo come mai mi andava da 64 a -64 (andamento tipo modulo e segno: da 64 fino a 32768, poi -32767 fino a -64), allora ho usato un unsigned int in tutto però va a scatti di 16, cioè da 128 a 65536. E per farlo sono costretto ad usare %u, altrimenti nulla.

Il codice è questo:

Codice: Seleziona tutto
   ADCON0bits.GO = 1;
  while(ADCON0bits.GO);
  __delay_ms(15);
  PIR1bits.ADIF = 0;
  __delay_ms(15);
  a = (unsigned int)((unsigned int)ADRESH << 8) + ADRESL;        // 'a' should be 16bit int type
  printf("ADC: %u\n", a);
             


Devo essermi perso in qualche casting...
Avatar utente
Foto Utentethexeno
235 5 9
Frequentatore
Frequentatore
 
Messaggi: 298
Iscritto il: 12 apr 2010, 18:28

1
voti

[4] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto UtentePaolino » 29 nov 2013, 9:36

Prova con:

Codice: Seleziona tutto
unsigned int ADCHi, ADCVal;

while(ADCON0bits.GO);
ADCHi = (unsigned int)ADRESH;
ADCHi = ADCHi <<8;
ADCVal = ADCHi + (unsigned int)ADRESL;
printf("ADC: %u\n", a);


Ciao.

Paolo.
"Houston, Tranquillity Base here. The Eagle has landed." - Neil A.Armstrong

-------------------------------------------------------------

PIC Experience - http://www.picexperience.it
Avatar utente
Foto UtentePaolino
32,6k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 4226
Iscritto il: 20 gen 2006, 11:42
Località: Vigevano (PV)

0
voti

[5] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto Utentethexeno » 6 dic 2013, 18:37

Niente, va da 128 a 65088 (ovviamente in modo granuloso, è su 12 bit in realtà) :(
(per leggere uso Arduino, ma anche altri come Termite.. però i caratteri son quelli, la stringa è quella, l'errore non è nell'interfaccia)

Per carità, risolverei dividendo tutto per 16, ma non è una soluzione secondo me...
Avatar utente
Foto Utentethexeno
235 5 9
Frequentatore
Frequentatore
 
Messaggi: 298
Iscritto il: 12 apr 2010, 18:28

0
voti

[6] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto Utentethexeno » 31 dic 2013, 1:17

Bene, ho trovato un po' di tempo per continuare.
Dunque, ero rimansto che sparava numeri coerenti ma moltiplicati per un tot (64 sembrava). Pensando che fosse la printf(), mi son fatto una funzioncina che tanto può sempre tornare utile, stampa correttamente una variabile di prova, ma l'adc continua imperterrito con il suo valore strano, andando da "000000064" a "000064256", perché la mia funzione stampa gli zeri prima. Ora pare qualcosa vagamente moltiplicato per 64 sempre. Ovviamente sto nei limiti se faccio uno shift di 4 anziché di 8, però ho una risoluzione ridicola.

Ecco il codice:

Codice: Seleziona tutto
void putlong( unsigned long l);
unsigned int adc_i = 0, adc_tot = 0;
char num[10];
/* i.e. uint8_t <variable_name>; */

/******************************************************************************/
/* Main Program                                                               */
/******************************************************************************/

void main(void)
{
    /* Configure the oscillator for the device */
    ConfigureOscillator();
   
    /* Initialize I/O and Peripherals for application */
    InitApp();
    usart_init();
    init_adc(2); // !!!!!!!!!!!!!!!!!  3V3 ONLY!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  //  init_pwm();
    /* TODO <INSERT USER APPLICATION CODE HERE> */
    printf("EPIC!");

    while(1)
{

   ADCON0bits.GO = 1;
  while(ADCON0bits.GO);
  PIR1bits.ADIF = 0;
  adc_i = (unsigned int)ADRESH;        // 'a' should be 16bit int type
  adc_i = adc_i << 8;
  adc_tot = adc_i + (unsigned int) ADRESL;
  //adc_tot = 3998;
  putlong(adc_tot);
  printf("%s \n", num);
  __delay_ms(15);
  __delay_ms(15);
  __delay_ms(15);
  __delay_ms(15);
}

}

void putlong( unsigned long l)
{
    uint8_t  i=0; //corrisponde alla dimensione+1 di num[] finale, 1 carattere per \0
    for (i=0; i<=9; i++)   //init num
    {
        num[i]='0';
    }
    if (num[i]=='\0')
    if (l==0) {
    putch('0');
    return;
    }

    i=9; //corrisponde alla dimensione+1 di num[] finale, 1 carattere per \0
    while (i>=1) { //per lasciare posto a \0
    num[i-1]=('0'+ l%10);
    l=l/10;
    if(l == 0)
    break;
    i--;
    }
    num[9]='\0'; //dim finale
}



L'init_adc() come al solito è questa:

Codice: Seleziona tutto
void init_adc(uint8_t ch)
{
    //!!!!!!!!!!!!!!!!!!!!!!!!!!! NON E' 5V TOLERANT!!!!!!!!!!!!
    //12 bit
   
   
   // ANCON0 |= ~(1 << ch); //shifto a sx 1 di ch posizioni e complemento per avere
                    // 0 sul canale scelto (analog behav)
    ANCON0 = 0x00;
    ANCON1 = 0x00;
  //  if ((ch - 8)>= 0){ //REsetto gli ultimi 4 bit, stessa cosa
  //  ANCON1 |= ~(1<<(ch-8)) ;
  //  ANCON1bits.VBGEN = 0;
  //  }
    ADCON0 = 0b00001000;
    ADCON1 = 0b00001110; //      fosc/64
   
    ADCON0bits.ADON = 1; //ADC [ON]
    PIE1bits.ADIE = 0; // int off
    PIR1bits.ADIF = 0;
    //IPR1bits.ADIP = 1; // high prior
  INTCONbits.GIEH = 1;  // high attivo ALL INT attivi
  INTCONbits.GIEL = 1;  // LOW attivo
}


Ovvero è configurata in modo statico, per provare, sul canale 2.
Ho provato a stampare anche invertendo ADRESH con L, casomai avessi invertito l'ordine, ma ovviamente nulla. Vorrei sapere se a voi questo main funziona, se qualcuno avesse voglia di provarlo. In caso positivo, allora il mio problema è su qualche configurazione e il problema è di un altro tipo.

PS: ovviamente spero la mia funzioncina, messa bene o male su, possa aiutare qualcuno che non vuole usare la printf.

Grazie ancora a chi ha ancora voglia di darmi una mano, buon anno. ;)
Avatar utente
Foto Utentethexeno
235 5 9
Frequentatore
Frequentatore
 
Messaggi: 298
Iscritto il: 12 apr 2010, 18:28

2
voti

[7] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto UtentePaolino » 31 dic 2013, 9:53

Ho dato un rapido sguardo alla routine di configurazione dell'ADC.
Ho notato che il dato che vai a leggere dall'ADC lo consideri giustificato a sinistra, infatti il bit ADFM del registro ADCON1 vale 0.
Prova con:

Codice: Seleziona tutto
...

    ADCON0 = 0b00001000;
    ADCON1 = 0b10001110; //      fosc/64 e giustificazione a destra

...


Ciao.

Paolo.
"Houston, Tranquillity Base here. The Eagle has landed." - Neil A.Armstrong

-------------------------------------------------------------

PIC Experience - http://www.picexperience.it
Avatar utente
Foto UtentePaolino
32,6k 8 12 13
G.Master EY
G.Master EY
 
Messaggi: 4226
Iscritto il: 20 gen 2006, 11:42
Località: Vigevano (PV)

2
voti

[8] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto UtenteTardoFreak » 31 dic 2013, 13:16

In questo articolo ho utilizzato l' ADC.
Ho quindi fatto un po' di ordine estraendo il codice dell' articolo (provato e funzionante) ed ho scritto in bella copia delle funzioni che ti potrebbero interessare.
Non le ho compilate ma dovrebbero funzionare.
Codice: Seleziona tutto
//------------------------------------------------------------------------------
// Prototipi delle funzioni
void adc_deInit(void);
void adc_initRatiometric(void);
void adc_calibrate(void);
unsigned short int adc_read(void);

//------------------------------------------------------------------------------
// De-inizializza l' ADC
void adc_deInit(void)
{
  ADCON0 = 0;
  ADCON1 = 0;
  IPR1bits.ADIP = 0;  // Bit di priorità interrupt ADC
  PIE1bits.ADIE = 0;  // Interrupt disabilitta
  PIR1bits.ADIF = 0;  // Flag interrupt azzerato
}

//------------------------------------------------------------------------------
// Inizializza l' ADC per misure ratiometriche (fra ground e Vdd)
void adc_initRatiometric(void)
{
  // Seleziona Vref positiva Vdd
  ADCON0bits.VCFG0 = 0;
  // Seleziona Vref negatica Vss
  ADCON0bits.VCFG1 = 0;
  // Seleziona il tempo di conversione 20TAD
  ADCON1bits.ACQT = 7;
  // Clock di conversione FOSC/64
  ADCON1bits.ADCS = 6;
  // Formato del risultato allineato a destra
  ADCON1bits.ADFM = 1;
  // Accensione
  ADCON0bits.ADON = 1;
}

//------------------------------------------------------------------------------
// Effettua la calibrazione automatica dell' ADC
void adc_calibrate(void)
{
  // Calibrazione ADC
  ADCON1bits.ADCAL = 1;
  ADCON0bits.GO = 1;
  while(ADCON0bits.GO);
  ADCON1bits.ADCAL = 0;
}

//------------------------------------------------------------------------------
// Fa partire la conversione e legge il valore dall' ADC
//  Uscita: valore letto
unsigned short int adc_read(void)
{
  unsigned short int valore;
 
  // Fa partire la conversione 45 us.
  ADCON0bits.GO = 1;
  // Aspetta la fine della conversione
  while(ADCON0bits.GO);
  // Legge il valore convertito
  valore = ADRES;
 
  return valore;
}

//------------------------------------------------------------------------------
// Main program di esempio di uso dell' ADC
void main(void)
{
  short int misura;
 
  // De-inizializza l' ADC
  adc_deInit();
  // Inizializza l' ADC
  adc_initRatiometric();
 
  // Calibra l' ADC
  adc_calibrate();
 
  // Seleziona l' ingresso da misurare
  ADCON0bits.CHS = 7;
 
  // Effettua la lettura;
  misura = adc_read();
 
  for(;;)
  {
  }
}
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[9] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto Utentethexeno » 31 dic 2013, 13:58

Hai ragione. La cosa frustrante (se si può dire così, perché ora ho risolto) è che era tra le prime cose che avevo pensato ma ero convinto che fosse configurato giusto.
Devo imparare a cambiare modo di ragionare, almeno per evitare queste sciocchezze. Grazie quindi due volte..

EDIT: Grazie anche a te TardoFreak, ho provato anche il tuo codice.

Ora, detto e fatto tutto questo, sia sul mio che sul codice di Tardo, l'adc è su 10 bit, quindi l'errore è nei bit di configurazione. Io, l'opzione 12BIT (o 0) l'ho abilitata. Vogliamo scommettere che è una cosa ancora più ridicola di prima? Il codice è questo:

Codice: Seleziona tutto
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1L
#pragma config WDTEN = OFF      // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
#pragma config PLLDIV = 3       // PLL Prescaler Selection (Divide by 3 (12 MHz oscillator input))
#pragma config CFGPLLEN = OFF   // PLL Enable Configuration Bit (PLL Disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset (Enabled)
#pragma config XINST = OFF      // Extended Instruction Set (Disabled)

// CONFIG1H
#pragma config CPUDIV = OSC1    // CPU System Clock Postscaler (No CPU system clock divide)
#pragma config CP0 = OFF        // Code Protect (Program memory is not code-protected)

// CONFIG2L
#pragma config OSC = HSPLL      // Oscillator (HS+PLL, USB-HS+PLL)
#pragma config SOSCSEL = HIGH   // T1OSC/SOSC Power Selection Bits (High Power T1OSC/SOSC circuit selected)
#pragma config CLKOEC = OFF     // EC Clock Out Enable Bit  (CLKO output disabled on the RA6 pin)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF       // Internal External Oscillator Switch Over Mode (Disabled)

// CONFIG2H
#pragma config WDTPS = 32768    // Watchdog Postscaler (1:32768)

// CONFIG3L
#pragma config DSWDTOSC = INTOSCREF// DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = T1OSCREF// RTCC Clock Select (RTCC uses T1OSC/T1CKI)
#pragma config DSBOREN = OFF    // Deep Sleep BOR (Disabled)
#pragma config DSWDTEN = OFF    // Deep Sleep Watchdog Timer (Disabled)
#pragma config DSWDTPS = 8192   // Deep Sleep Watchdog Postscaler (1:8,192 (8.5 seconds))

// CONFIG3H
#pragma config IOL1WAY = OFF    // IOLOCK One-Way Set Enable bit (The IOLOCK bit (PPSCON<0>) can be set and cleared as needed)
#pragma config ADCSEL = BIT12  // ADC 10 or 12 Bit Select (12 - Bit ADC Enabled)
#pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)

// CONFIG4L
#pragma config WPFP = PAGE_1    // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 1)
#pragma config WPCFG = OFF      // Write/Erase Protect Configuration Region  (Configuration Words page not erase/write-protected)

// CONFIG4H
#pragma config WPDIS = OFF      // Write Protect Disable bit (WPFP<6:0>/WPEND region ignored)
#pragma config WPEND = PAGE_0   // Write/Erase Protect Region Select bit (valid when WPDIS = 0) (Pages 0 through WPFP<6:0> erase/write protected)
#pragma config LS48MHZ = SYS48X8// Low Speed USB mode with 48 MHz system clock bit (System clock at 48 MHz USB CLKEN divide-by is set to 8)




Che poi è quello autogenerato, prendendo spunto da quello già scritto per il Pierin nella guida. Ovviamente continuerò a pensare, prima o poi salta sempre fuori qualche cosa.
Avatar utente
Foto Utentethexeno
235 5 9
Frequentatore
Frequentatore
 
Messaggi: 298
Iscritto il: 12 apr 2010, 18:28

0
voti

[10] Re: PIC18 problemi su Tad dell'ADC

Messaggioda Foto UtenteTardoFreak » 31 dic 2013, 15:18

thexeno ha scritto:... TardoFreak, ho provato anche il tuo codice ...

Funziona tutto?
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 6 ospiti