• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

ADC in PIC 16F1503

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

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.
 

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.
 
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.
 
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?
 
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
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.
 
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
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.
 
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.
 
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.
 

Latest threads

EE World Online Articles

Loading
Top