ADC reading keeps jumping around on dspic33FJ128MC802, cannot get a stable reading, mplab8.92, xc16 compiler

1.7k views Asked by At

Good evening,

I'm trying to implement a simple 1 channel ADC reader on a dspic33FJ128MC802, that manually starts sampling data, automatically converts when the sampling is done, and reads and stores data.

This has never been an issue for me, except with this microcontroller, which doesn't seem to have a normal ADC implemented,

I've read through the datasheet section on ADC several times, and I've configured it to my best ability, however the ADC1BUF0 value keeps jumping around inconsistently, between 0 and 4096, when I have a Lab power supply connected directly to the input pins of the ADC.

What I see is the ADC1BUF0 value seems to roughly correspond to the input voltage (0-3.3V), when I pause the debugger, it gives a couple (2-4) readings that are within range +-100 (out of 4096 is not bad). Then if I continue to run and pause, with the voltage kept the same, the values stored in the buffer suddenly begin to jump +- 500, sometimes even showing 4095 (all 1's) and 0.

Then when I change the lab PSU to a different voltage, it seems to repeat the process of showing me a few correct values, then start to jump around again.

So essentially, it will show me a correct value about 1/2 of the times I pause the debugger.

I don't know what is causing this, I know that I need to run the debugger after changing voltage so that it can clear out the buffers, but something about this microcontroller seems definitely wrong.

Please let me know what can be done to fix this,

The compiler is XC16, IDE is Mplab 8.92

Thanks,

Below is my configuration:

[code]

void InitADC() {
    TRISAbits.TRISA0=1; 

    AD1CON1bits.FORM = 0; // Data Output Format: integer//Signed Fraction (Q15 format)
    AD1CON1bits.SSRC = 7; // Interan Counter (SAMC) ends sampling and starts convertion
    AD1CON1bits.ASAM = 0; // ADC Sample Control: Sampling begins immediately after conversion
    AD1CON1bits.AD12B = 1; // 12-bit ADC operation
    AD1CON1bits.SIMSAM =1; // 10-bit ADC operation
    AD1CON2bits.CHPS = 0; // Converts CH0
    AD1CON2bits.CSCNA = 0; // Do not scan inputs
    AD1CON2bits.VCFG = 0; // Use voltage reference Vss/Vdd
    AD1CON2bits.ALTS = 0; // Always use input select for channel A
    AD1CON2bits.BUFM = 0; // Always start filling at buffer 0
    AD1CON3bits.ADRC = 0; // ADC Clock is derived from Systems Clock
    AD1CON3bits.SAMC = 0; // Auto Sample Time = 0*Tad
    AD1CON3bits.ADCS = 2; // ADC Conversion Clock Tad=Tcy*(ADCS+1)= (1/40M)*3 = 75ns (13.3Mhz)

    // ADC Conversion Time for 10-bit Tc=12*Tab = 900ns (1.1MHz)
    AD1CON1bits.ADDMABM = 1; // DMA buffers are built in conversion order mode
    AD1CON2bits.SMPI = 0; // SMPI must be 0

    AD1CON4bits.DMABL = 0; // Only 1 DMA buffer for each analog input

    //AD1CHS0/AD1CHS123: A/D Input Select Register
    AD1CHS0bits.CH0SA = 0; // MUXA +ve input selection (AIN0) for CH0
    AD1CHS0bits.CH0NA = 0; // MUXA -ve input selection (Vref-) for CH0
    AD1CHS123bits.CH123SA = 0; // MUXA +ve input selection (AIN0) for CH1
    AD1CHS123bits.CH123NA = 0; // MUXA -ve input selection (Vref-) for CH1
    IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
    IEC0bits.AD1IE = 0; // Do Not Enable A/D interrupt

    AD1CSSL = 1; //Scan from AN0 only
    AD1PCFGL = 0b111111110; //Only AN0 in analog input mode

    AD1CON1bits.ADON = 1; // Turn on the A/D converter
}

int main() {
    ADPCFG = 0xFFFE; //make ADC pins all digital except AN0 (RA0)
    while(1)
    {
       AD1CON1bits.SAMP = 1; 
       while(!AD1CON1bits.DONE);
       myVoltage = ADC1BUF0;
    }
    return 0;
}

[/code]

1

There are 1 answers

0
Mich On

Seems like I missed a semicolon after while(!AD1CON1bits.DONE)

Without the semicolon it did not wait for the conversion to complete.

I corrected this in the original post, in case someone wants to use the source in this post

Thank you,