PIC18F26K22: Can't get the ADC to work using C18 Compiler

Thread Starter

madisonmccarthy

Joined Jun 22, 2016
2
Hello everyone,

I'm having a great deal of difficulties correctly configuring the ADC with this microcontroller. The PIC18 is embedded into a prototype board which limits my ANx pin usage to AN14, AN12, and a few others. I have tried supplying varying voltages to pin AN12 (the one I chose to use) and my circuit resistance is roughly 4.6K Ohms.

After scanning many forums as well as thoroughly reading the document sheet, I have been left with the code attached below

The output that I receive is a random numbers in the range of 0x10 - 0x20 with or without a voltage supplied. At one point, I was reading all zeros instead of random numbers.

I feel as though I am either missing a key step in this configuration, or have a problem hidden within the code I did not include. The board is also configured with a radio, however I did check the configurations and none of them overlapped with my configurations.

I would greatly appreciate any advice as to where to look for an issue, or what I may be forgetting to do!


Code:
#pragma config FOSC = INTIO67, PLLCFG = ON, PRICLKEN = ON, FCMEN = OFF
#pragma config PBADEN = ON, IESO = OFF, PWRTEN = ON, MCLRE = EXTMCLR
#pragma config BOREN = OFF, HFOFST = OFF, T3CMX = PORTC0, STVREN = ON, WRTC = ON, WRTD = OFF
#pragma config WDTEN = SWON, WDTPS = 8192, LVP = OFF, DEBUG = OFF
....
OSCCON = 0x70;                    //Configure oscillator    
OSCCON2 = 0x84;                    //set to Fcy = 64 MHz, Fosc = 16 MHz
OSCTUNE = 0x40;   //??

PORTBbits.AN12 = 1; //Enable AN12??
TRISBbits.RB0 = 1; // Enable RB0 as input
ANSELBbits.ANSB0 = 1; // Enable pin as analog
   
 ADCON0bits.CHS = 0b01100; //Setting the Channel as AN12
 ADCON1bits.NVCFG = 0; // Using Vdd
 ADCON1bits.PVCFG = 0; // Using Vss
 ADCON2bits.ADCS = 0b101; // Setting clock speed
 ADCON2bits.ACQT = 0b101; // Setting aquisition time
 ADCON2bits.ADFM = 1; // Right Justify
 ADCON0bits.ADON = 1;    /* A/D Enabled */
....
ADCON0bits.GO=1; // Start Conversion
                       
while (ADCON0bits.GO==1); //Polling until done

value = ADRESL; // Store the value into uint8 Data Type
....
 

nsaspook

Joined Aug 27, 2009
13,086
I've got a old C18 25k22 project that configs analog inputs. Maybe this will give you a hint at what's wrong, I haven't looked at the code for a while so it might be buggy.
Code:
#ifdef P25K22
OSCCON = 0x70; // internal osc 16mhz, CONFIG OPTION 4XPLL for 64MHZ
OSCTUNE = 0xC0; // 4x pll
TRISC = 0b11111100; // [0..1] outputs for DIAG leds [2..7] for analog
LATC = 0x00; // all LEDS on
TRISAbits.TRISA6 = 0; // CPU clock out
TRISBbits.TRISB1 = 1; // SSP2 pins clk in SLAVE
TRISBbits.TRISB2 = 1; // SDI
TRISBbits.TRISB3 = 0; // SDO
TRISBbits.TRISB0 = 1; // SS2
/* ADC channels setup */
TRISAbits.TRISA0 = HIGH; // an0
TRISAbits.TRISA1 = HIGH; // an1
TRISAbits.TRISA2 = HIGH; // an2
TRISAbits.TRISA3 = HIGH; // an3
TRISAbits.TRISA5 = HIGH; // an4
TRISBbits.TRISB4 = HIGH; // an11
TRISBbits.TRISB0 = HIGH; // an12 SS2, don't use for analog
TRISBbits.TRISB5 = HIGH; // an13
TRISCbits.TRISC2 = HIGH; // an14
TRISCbits.TRISC3 = HIGH; // an15
TRISCbits.TRISC4 = HIGH; // an16
TRISCbits.TRISC5 = HIGH; // an17
TRISCbits.TRISC6 = HIGH; // an17
TRISCbits.TRISC7 = HIGH; // an18
TRISBbits.TRISB4 = 1; // QEI encoder inputs
TRISBbits.TRISB5 = 1;
TRISBbits.TRISB6 = 1;
TRISBbits.TRISB7 = 1;
ANSELA = 0b00101111; // analog bit enables
ANSELB = 0b00110000; // analog bit enables
ANSELC = 0b11111100; // analog bit enables
VREFCON0 = 0b11100000; // ADC voltage ref 2.048 volts
OpenADC(ADC_FOSC_64 & ADC_RIGHT_JUST & ADC_12_TAD, ADC_CH0 & ADC_INT_ON, ADC_REF_FVR_BUF & ADC_REF_VDD_VSS); // open ADC channel
#endif
https://github.com/nsaspook/daq_gert/blob/master/RPi_PIC/SlaveO.c
 

ErnieM

Joined Apr 24, 2011
8,377
First thing is line 11: PortB is the digital output data latch. Changing it has no effect when the port is an input or in analog mode. That is minor.

Major is how you read the data: the conversion results in a 10 bit number sperad over two registers, see figure 17-2 of the data sheet. To use just the 8 bit part you need to left justify the result and read from ADRESH. Reading from a right justified result from the low register yields garbage as the two most significant bits are lost.
 

Thread Starter

madisonmccarthy

Joined Jun 22, 2016
2
Hi ErnieM,

Thanks for the advice with the digital data latch, I will remove that line since it is useless. In regards to the 10 bit number spread over two registers, I am aware that I am using only the lower 8 bits of information. My application (when correctly running) will always result in the two bits stored in ADRESH always being 1 due to my voltage range, which means I no longer care about their values.

Thank you for your code nsaspook, I will comb through it today and see if I can fix my errors!
 
Top