PIC18f45k20 ADC - siempre devuelve cero

1

Estoy intentando leer un valor de un ADC PIC18f45k20 pero siempre obtengo un cero. Tiene que ser mi configuración que está mal, pero no puedo ver dónde. He revisado la hoja de datos y he buscado en Google (mucha información contradictoria aunque ...).

Detalles

  • PIC18f45k20
  • Cristal de 16 Mhz, PLL = 4 por lo que 64Mhz
  • Entrada en AN11 / RB4
  • XC8
  • Entrada de lectura de un LDR que actúa como un divisor de voltaje de + 3.3V. (He confirmado con un multímetro que esto genera voltajes alrededor de 1.5v-3v dependiendo de los niveles de luz)

Lo que he tratado de asegurar es

  1. TRISB para RB4 se ingresa
  2. ANSEL para ANS11 es analógico
  3. El canal 11 está seleccionado
  4. Usar Vdd y Vss como referencias en lugar de referencias externas
  5. TAD y velocidad apropiados, espero que esto sea correcto. Fosc / 64, 20 TAD

He comprobado la lista de verificación ADC (hoja de datos 19.2.9) y, por lo que puedo ver, todo es correcto. También he intentado sin usar las funciones XC8 ADC.h (es decir, solo ajustando los bits) y obtengo exactamente el mismo resultado.

¿Alguna idea?

///////////////////////////////////////////////////////////////////////////////
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
//more setting here...//////////////////////////////////////////////////////////////////////////////

#define _XTAL_FREQ  64000000
#define _CLOCK_FREQ 16000000 // xtal / 4

int main(int argc, char** argv)
{
    TRISA = 0b00000000;
    TRISB = 0b00010000;
    TRISC = 0b00000000;
    CM2CON0 = 0;
    CM2CON1 = 0;
    CVRCON = 0x0;

    ADCON0bits.CHS = 11;
    ANSELHbits.ANS11 = 1;

    ADCON1 = 0b00000000; // 00 = unimplemented, 0 = V- is Vss, 0 = V+ is Vdd, 0000 = unimplemented
    ADCON2 = 0b00111110; // 0 = left justified, 0 = unimplemented, 111 = 20 TAD, 110 = Fosc/64
    ADCON0 = 0b00101101; // 00 = unimplemented, 1011 = AN11, 0 = GO/DONE, 1 = ADON

    while(1)
    {
        ConvertADC();
        while(BusyADC())
        {
        }

        int r = ReadADC();       

        delay(500);
    }

    return (EXIT_SUCCESS);
}

void delay( int ms )
{
    while( ms > 0 )
    {
        __delay_ms(1);
        --ms;
    }
}

EDIT - 2014/06/14: puedo hacer que el ADC funcione en un PIC18f4550 sin muchos problemas. El código es equivalente, pero aún no puedo hacer funcionar el 45k20.

ADC en AN0 / RA0. Basado en el ejemplo de enlace

TRISA = 0b00000001;
TRISD = 0b00000000;

ADCON1 = 0b00001110;//VSS,VDD ref. AN0 analog only
ADCON0 = 0x00;//clear ADCON0 to select channel 0 (AN0)
ADCON2 = 0b00001000;//ADCON2 setup: Left justified, Tacq=2Tad, Tad=2*Tosc (or Fosc/2)
ADCON0bits.ADON = 0x01;//Enable A/D module

LATDbits.LATD0 = 1;

while(1)
{
    ADCON0bits.GO_DONE = 1;//Start A/D Conversion

    while(ADCON0bits.GO_DONE != 0);//Loop here until A/D conversion completes

    unsigned short r = ADRES;
    LATDbits.LD0 = r == last ? 0 : 1;
    last = r;

    delay(100);
}
    
pregunta Andre

1 respuesta

1

No me gusta "arreglar mi código" también :) No analizaré su código, no soy experto en PIC, simplemente comencé con microcontroladores de Microchip, ¡son increíbles! :)

Editado:

Así es como lo hago en PIC18F4550 PIC18F25k50 y funciona con seguridad. También debería funcionar en PIC18F4520 .

Fin de edición.

Usted tiene que cambiar la configuración de referencia de voltaje del puerto y probablemente.

volatile unsigned int millivolts = 0; // variable for result

void config_adc(void)
{
    // voltage reference selection

    // VREFCONbits.FVRS
    // 0b00 off
    // 0b01 1024mV
    // 0b10 2048mV
    // 0b11 4096mV
    VREFCON0bits.FVRS = 0b01;
    VREFCON0bits.FVREN = 1; // internal fixed voltage reference turned on

    ANSELAbits.ANSA0 = 1; // analog input A0 on
    TRISAbits.TRISA0 = 1; // pin A0 as input

    ADCON0bits.CHS = 0;   // analog channel select

    ADCON1bits.PVCFG = 0b10; // 0b10 for positive voltage reference = FVR BUF2 ("FVRS" configured earlier)
    ADCON1bits.NVCFG = 0b00; // 0b00 for negative voltage reference = AVss

    ADCON2bits.ADCS = 0b110; // 0b011 use FRC clock (internal clock dedicated for ADC)
    ADCON2bits.ACQT = 0b000; // manual acquisition mode
    ADCON2bits.ADFM = 1; // result bits adjusted to right

    ADCON0bits.ADON = 1; // ADC converter on
}

void main()
{
    config_adc();
    while(1)
    {

        ADCON0bits.GODONE = 1; // start conversion

        while (ADCON0bits.GODONE) // wait until conversion is done
        {
            asm("nop"); // im not sure if this is necessary
        }

    millivolts = (ADRESH * 256 + ADRESL); // im writing result into volatile variable to use it in interrupt routine

    }
}

También estoy usando XC8. El código no está completo, esto es solo parte de ADC.

    
respondido por el Kamil

Lea otras preguntas en las etiquetas