1
\$\begingroup\$

I have programmed the 10 bit internal ADC in PIC18F458 and displaying ADC output through UART. I have connected a 10 K pot to the ADC input RA0 and varying it to seeing the corresponding ADC output. Since, its a 10 bit ADC configured with +Vref = +Vdd = 5V and -Vref = Vss = Gnd, I presumed that for 0 Kohms, the ADC output should be 0 and for 10 K ohms, it should be 1023, however I have been getting some weird ADC output values when simulated in Proteus, and I am not sure on how to validate if its the right output or not. I have attached the images of the proteus simulations, data table and the code. And another thing is that, If I am using an unsigned int data type (ADC_data) to displaying the ADC outputs, then how come I am still getting negative values too?, provided +Vref = 5V and -Vref = Gnd = 0V. Can someone please explain this?

 #define _XTAL_FREQ 20000000
 #include<P18F458.h>
 #include"UART.h"

#pragma config OSC=HS
#pragma config OSCS=OFF
#pragma config PWRT=OFF
#pragma config BOR=OFF
#pragma config WDT=OFF
#pragma config STVR=ON
#pragma config LVP=OFF
#pragma config CP0=OFF
#pragma config CP1=OFF
#pragma config CP2=OFF
#pragma config CP3=OFF
#pragma config CPB=OFF
#pragma config CPD=OFF
#pragma config WRT0=OFF
#pragma config WRT1=OFF
#pragma config WRT2=OFF
#pragma config WRT3=OFF
#pragma config WRTC=OFF
#pragma config WRTB=OFF
#pragma config WRTD=OFF
#pragma config EBTR0=OFF
#pragma config EBTR1=OFF
#pragma config EBTR2=OFF
#pragma config EBTR3=OFF
#pragma config EBTRB=OFF

#pragma config DEBUG=OFF

unsigned int ADC_data = 0;
void ADC_Init()
{

ADCON0bits.ADON = 1;
ADCON1bits.PCFG3 = 1;
ADCON1bits.PCFG2 = 1;
ADCON1bits.PCFG1 = 1;
ADCON1bits.PCFG0 = 0;
ADCON1bits.ADFM = 0;

ADCON0bits.CHS0 = 0;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = 0;

ADCON1bits.ADCS2 = 0;
ADCON0bits.ADCS1 = 1;
ADCON0bits.ADCS0 = 0;
}

void ADC_Convert()
{
ADCON0bits.GO_DONE = 1;
while(ADCON0bits.GO_DONE == 1);
ADC_data = (((unsigned int)ADRESH)<<8)|(ADRESL);
}


void main (void)
{
TRISAbits.TRISA0 = 1;
UARTInit();
ADC_Init();
while(1)
{
__delay_us(20);
ADC_Convert();
UARTNextLine("ADC Output is ");
UARTWriteInt(ADC_data,255);
}
}

enter image description here enter image description here enter image description here

Additional information :

Fosc = 20 MHz Tosc = 1/20MHz = 0.05us 32Tosc = 0.05us * 32 = 1.6us 11Tad = 11 * 1.6us = 17.6us

Note that , In the code I have given a delay of 20us before the A/D conversion starts and not 17.6us.

I am not sure if the ADC outputs what I have got is right or If there is some bug in the code that's generating inaccurate values. Any comments, suggestions and advice's on how to verify if my adc is working correctly would be helpful for me to continue and understand.

Thanking you all in advance ~VD

\$\endgroup\$
4
\$\begingroup\$

In your ADC initialisation, change this line

ADCON1bits.ADFM = 0;

to this

ADCON1bits.ADFM = 1;

As the datasheet explains on page 242

adc

Your configuration effectively resulted in a number that was shifted 6 bits to the right, so was 64 times bigger than expected.

This is illustrated in the following figure from the same section of the datasheet:

adc2

\$\endgroup\$
  • \$\begingroup\$ Changing ADFM bit from 0 to 1 worked!.Thanks. \$\endgroup\$ – PsychedGuy Oct 25 '15 at 7:17
2
\$\begingroup\$

I have not looked up your ADC device but I can tell you that the results that you are seeing are consistent with the A/D converter returning its 10-bit results left justified in the 16-bits that you read the result in.

Take your readings and shift them right 6 places and you may start to get what you expect.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.