# ADC in PIC 16F1503

#### piccontrollerlearner

##### Member
I am using PIC 16F1503 and xc8 compiler.
I want to use 2 adc pins from 2 different ports (RA4, RC3).
While I am able to perform adc operation on port A (AN3), the same cannot be achieved on port C(AN7).
The code for ADC on port C is attached here.
Please help.
Thank you.

#### Attachments

• 3.2 KB Views: 18

#### Pommie

##### Well-Known Member
Most Helpful Member
RA4 is AN3 and RC3 is AN7. Just read them as ADC channels. So, to answer your question, you can read from both.

Mike.

#### piccontrollerlearner

##### Member
RA4 is AN3 and RC3 is AN7. Just read them as ADC channels. So, to answer your question, you can read from both.

Mike.
Yes but I can't read from AN7.
What is the mistake in my code?

#### Diver300

##### Well-Known Member
Most Helpful Member
ADCON1 isn't defined. With its default value the result is left justified, so the smallest non-zero reading is 0x0040. Your comparison with 500 will toggle at around 38 mV with a 5 V supply, not 2.5 V.

If you are only reading AN7 it won't matter, but the line where you have ADCON0 &= 0xf3 is wrong. It should be ADCON0 &= 0x83 to clear all 5 bits of CHS

You are using ANSELC incorrectly. ANSELC has four bits that make the four pins of port C analog or digital. AN7 is on the same pin as PortC3, so ANSC3 should be 1 and the other bits in ANSELC should be zero. The value of ANSELC has no real meaning as it's just a collection of individual bits. I think that you need to set it to 0b1000 to make AN7 an analog input.

#### Pommie

##### Well-Known Member
Most Helpful Member
Try,
Code:
unsigned int getADCvalue(unsigned char channel){
if(channel>7)
return 0;
ADCON0=channel<<2|1;          //select channel and ADC on
ADCON1=0b11110000;            //right justify, RC osc
ANSELA=0b0001000;             //RA4=analogue
ANSELC=0b0000100;             //RC3=analogue
__delay_ms(1);                //Time for Acqusition capacitor to charge up and show correct value
GO_nDONE  = 1;                //Enable Go/Done
while(GO_nDONE);              //wait for conversion completion
return ((ADRESH<<8)+ADRESL);  //Return 10 bit ADC value
}
Mike.

#### piccontrollerlearner

##### Member
ADCON1 isn't defined. With its default value the result is left justified, so the smallest non-zero reading is 0x0040. Your comparison with 500 will toggle at around 38 mV with a 5 V supply, not 2.5 V.

If you are only reading AN7 it won't matter, but the line where you have ADCON0 &= 0xf3 is wrong. It should be ADCON0 &= 0x83 to clear all 5 bits of CHS

You are using ANSELC incorrectly. ANSELC has four bits that make the four pins of port C analog or digital. AN7 is on the same pin as PortC3, so ANSC3 should be 1 and the other bits in ANSELC should be zero. The value of ANSELC has no real meaning as it's just a collection of individual bits. I think that you need to set it to 0b1000 to make AN7 an analog input.
I have defined ADCON1 as 0xF0, set ADCON0 &= 0X83 and ANSELC to 0b1000 as you said, but still can't read from AN7.

#### piccontrollerlearner

##### Member
Try,
Code:
unsigned int getADCvalue(unsigned char channel){
if(channel>7)
return 0;
ADCON0=channel<<2|1;          //select channel and ADC on
ADCON1=0b11110000;            //right justify, RC osc
ANSELA=0b0001000;             //RA4=analogue
ANSELC=0b0000100;             //RC3=analogue
__delay_ms(1);                //Time for Acqusition capacitor to charge up and show correct value
GO_nDONE  = 1;                //Enable Go/Done
while(GO_nDONE);              //wait for conversion completion
return ((ADRESH<<8)+ADRESL);  //Return 10 bit ADC value
}
Mike.
I have applied your code in my getADCvalue function, but still can't achieve the result.
Is there anything else that I have to change in my code apart from getADCvalue function?

#### Pommie

##### Well-Known Member
Most Helpful Member
but still can't achieve the result.
This tells us nothing. What does it do?
Is there anything else that I have to change in my code apart from getADCvalue function?
Just ensure both pins are input and the code is running. BTW, How do you know the code is executing?

Mike.
Edit, and WPUs are off.

#### piccontrollerlearner

##### Member
This tells us nothing. What does it do?
I meant that I can't read from AN7.

Just ensure both pins are input and the code is running.
As I have used AN3 as analog input successfully, right now I am trying only for AN7 separately.
BTW, How do you know the code is executing?
For simplicity, I have placed one end of a jumper to 5V. The output toggles when the other floating end is shorted to the analog pin.

#### Pommie

##### Well-Known Member
Most Helpful Member
What is in TRISC? And, how does an output toggle when you apply 5V?

Mike.

#### piccontrollerlearner

##### Member
What is in TRISC?
TRISCbits.TRISC3 = 1 is required to configure pin as input I guess.

And, how does an output toggle when you apply 5V?
It is my assumption that when 5V is applied, the corresponding ADC value on AN7 changes which leads to toggle output from 0 to 1.
As I was able to do it for AN3, I continued to do it for AN7.

#### Pommie

##### Well-Known Member
Most Helpful Member
Just looked at your InitADC and it is just plain wrong - look what you do to poor ANSELC. Also, read the manual on how to shut off the comparators - actually, don't they're off by default. Delete InitADC and use the debugger to debug the code. Hint, store the returned value in a 16 bit variable and look at it's value via the debugger.

Mike.

#### piccontrollerlearner

##### Member
By clearing bit 7 of comparator SFR, the comparator is shut off and as per suggestion in this thread, I have set ANSELC to 0b1000.
Also, while debugging my present code, I found that the returned ADC value is 0 for both ADC channels.
What should be done?
Thanks in advance.

#### Pommie

##### Well-Known Member
Most Helpful Member
Post all your code.

Mike.

#### piccontrollerlearner

##### Member
Code for AN7 channel is attached here.

#### Attachments

• 3.2 KB Views: 3

#### Pommie

##### Well-Known Member
Most Helpful Member
That appears to be the same as in the first post! What happened to Delete InitADC and the suggested getADCvalue? Change the code and repost.

Mike.

#### piccontrollerlearner

##### Member
When I delete InitADC and start debugging, the code execution halts at while(GO_nDONE); Possibly because to turn on ADC conversion, we use ADCON0, which is written in InitADC function.

#### Pommie

##### Well-Known Member
Most Helpful Member
Try this,
Code:
int ADC_Val;

unsigned int getADCvalue(unsigned char channel){
if(channel>7)
return 0;
ADCON0=channel<<2|1;          //select channel and ADC on
ADCON1=0b11110000;            //right justify, RC osc
ANSELA=0b0001000;             //RA4=analogue
ANSELC=0b0000100;             //RC3=analogue
__delay_ms(1);                //Time for Acqusition capacitor to charge up and show correct value
GO_nDONE  = 1;                //Enable Go/Done
while(GO_nDONE);              //wait for conversion completion
return ((ADRESH<<8)+ADRESL);  //Return 10 bit ADC value
}

void main(){
OPTION_REGbits.nWPUEN = 1;
TRISCbits.TRISC3 = 1;
TRISAbits.TRISA0  = 0;
RA0=0;
while(1){
ADC_Val = getADCvalue(7);            //read channel 7 = RC3
ADC_Val = getADCvalue(3);            //read channel 3 = RA4
if(ADC_Val<500){
RA0=0;
}else{
RA0=1;
}
}
}
Note, I pass the channel number to getADCvalue - AN7 is not 7.
Obviously, keep your config etc.

Set breakpoints to see what is in ADC_Val.

Mike.

#### Pommie

##### Well-Known Member
Most Helpful Member
When I delete InitADC and start debugging, the code execution halts at while(GO_nDONE); Possibly because to turn on ADC conversion, we use ADCON0, which is written in InitADC function.
I setup ADCON0 in MY version of getADCvalue which I, stupidly, thought you were using.

Mike.

#### piccontrollerlearner

##### Member
Try this,
Code:
int ADC_Val;

unsigned int getADCvalue(unsigned char channel){
if(channel>7)
return 0;
ADCON0=channel<<2|1;          //select channel and ADC on
ADCON1=0b11110000;            //right justify, RC osc
ANSELA=0b0001000;             //RA4=analogue
ANSELC=0b0000100;             //RC3=analogue
__delay_ms(1);                //Time for Acqusition capacitor to charge up and show correct value
GO_nDONE  = 1;                //Enable Go/Done
while(GO_nDONE);              //wait for conversion completion
return ((ADRESH<<8)+ADRESL);  //Return 10 bit ADC value
}

void main(){
OPTION_REGbits.nWPUEN = 1;
TRISCbits.TRISC3 = 1;
TRISAbits.TRISA0  = 0;
RA0=0;
while(1){
ADC_Val = getADCvalue(7);            //read channel 7 = RC3
ADC_Val = getADCvalue(3);            //read channel 3 = RA4
if(ADC_Val<500){
RA0=0;
}else{
RA0=1;
}
}
}
Note, I pass the channel number to getADCvalue - AN7 is not 7.
Obviously, keep your config etc.

Set breakpoints to see what is in ADC_Val.

Mike.
Unfortunately, this code also didn't work for me. But thanks for your continuous efforts.
Please suggest what to do next.

Loading