Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

ADC conversion PIC16f687

Status
Not open for further replies.

chimera786

Member level 2
Joined
Jun 16, 2011
Messages
42
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,710
hello. I am running adc on PIC 16f687. Now, I known I can use the adc read command from mikro.. However, I want to use my own. This is the command I have:

Code:
void init(){
 ADCON0=0x00;       // pin A0 for analog read, left justified, Vref=VDD, ADO off
 ADCON1=0x20;       // Aquisition time is Fosc/32 @ 8Mhz
}

unsigned int Read(){
 ADON_bit=1;        // turn on ADC
 GO_DONE_bit=1;     // start conversion
 while (GO_DONE_bit);   // wait for conversion to get done
 ADON_bit=0;        // turn of ADC
 return ADRESH;      // read only the ADRESH register.
}

unsigned int test;

void main() {
     ANSEL=0x01;      // Pin A0 for analog read
     TRISA=0xFF;     // PORTA is all input
     TRISB=0x00;    // Port B is all OUTPUT
     CM1CON0.B7o=0;    // comparators off
     CM2CON0.B7=0;
     init();
     
     while (1){
     PORTB.B6=0;      // make port b pin off
     test=Read();      // get the result from ADRESH register--8 bit resolution
     if (test>240){    // if it is close to Vdd turn on PIN B6
      PORTB.B6=1;}
     }


As you can see, I am reading from ADRESH register, which is the upper 8 bits. This means that I have to quit the last two bits which are stored in the ADSEL register. This in turn means that I have only 8 bits of resolution.

Now, lets say I am okay with 8 bits of resolution. Accoding to my code, I can read ADRESH which is 8 bits long, equate that to 'test' and read it . However, when ever I use the 'if' condition that 'if' is greater than 240, it does not work. If I use, 'if (test >100)', then the program works. Why is this.

Also, what is I am trying to use the complete 10 bits. How am I to store the complete 10 bits.

Thank you. I do appreciate each and every reply.
 
Last edited by a moderator:

Hi;
What kind of hw connection did you applied to your A0 port.
To expect any voltage close to Vdd, you should apply a voltage accordingly. So check port A0 connection. It is floating, tied to any cct or else?

On the other hand, if you use right justified type of ADRESH and ADRESL (check ADCON1), then you can convert them something like below;
10bit_value=(int)(256.0*ADRESH+ADRESL);

Hope helps.
 
Have a look on this Code.. Hope this helps you..

You should use Right-Justified Setting for ADC data Storage

Code:
	ADCON0 = 0x81;
//Fosc/64 is Selected
//Channel-0 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0xCE;	//Changing this value to 0xC4
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
	while(1)
	{
		__delay_us(20);
		ADCON0bits.GO = 1; //Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here for End of COnversion
[B][I]		adc_data = ADRESH & 0x00FF;               //Declare adc_data as unsigned int type[/I][/B]
		adc_data = adc_data<<8;
		adc_data = adc_data | ADRESL;	
	}

Hope this help u


Regards
Arun Sharma
 
Have a look on this Code.. Hope this helps you..

You should use Right-Justified Setting for ADC data Storage

Code:
	ADCON0 = 0x81;
//Fosc/64 is Selected
//Channel-0 is Selected
//Analog-to-Digital Converter Module is Powered Up
	ADCON1 = 0xCE;	//Changing this value to 0xC4
//A/D Result Format Select Bit Right Justified
//and AN0 Channel as Analog Channel
	while(1)
	{
		__delay_us(20);
		ADCON0bits.GO = 1; //Start Conversion
		while(ADCON0bits.GO == 1);	//Wait Here for End of COnversion
[B][I]		adc_data = ADRESH & 0x00FF;               //Declare adc_data as unsigned int type[/I][/B]
		adc_data = adc_data<<8;
		adc_data = adc_data | ADRESL;	
	}

Hope this help u


Regards
Arun Sharma

Thank you for your answer arun. The code is very clear and straight forward. Please can you also explain how the left and right justification works and why is right justification preferred?


Hi;
What kind of hw connection did you applied to your A0 port.
To expect any voltage close to Vdd, you should apply a voltage accordingly. So check port A0 connection. It is floating, tied to any cct or else?

On the other hand, if you use right justified type of ADRESH and ADRESL (check ADCON1), then you can convert them something like below;
10bit_value=(int)(256.0*ADRESH+ADRESL);

Hope helps.

Hey emresel, thanks for your answer. I have pulled down my A0 connection to ground using a 1K resistor. The reason is that the maximum impedance that I can see on the pin is 10K ohms. So 1K should be good enough for any voltage change. About the Vdd voltage read, I literally am just feeding the A0 ADC pin with Vdd voltage, so I know what the voltage level should be.

So the result of the ADRESH and ADRESL should be attained using right justification and simply added together and then multiplied? Can you please explain how the left and right justification works and why is right justification preferred?


Thanks a bunch u guys
 

yeah sure chimera786


Suppose your adc converts an analog signal suppose 5V analog voltage to 1023
So 1023 in HexaDecimal is 3FF
if You Choose Right Justified then FF will be stored in ADRESL register
Means ADRESL = 0xFF;

and

ADRESH will contain 0x03

I generally follow this methodology as it is similar to real world
but if you choose left justified
the values in Register's are as follow:
ADRESH = 0x3F
ADRESL = 0xF0

which i personally feels not good for me.. but one can use this if they want
I like the Right Justified one...

And the logic to merge these into a single variable is also simple
Declare a variable as
unsigned int adc_data;

when conversion gets over use these statements
Code:
                adc_data = ADRESH & 0x00FF;               //Declare adc_data as unsigned int type
		adc_data = adc_data<<8;
		adc_data = adc_data | ADRESL;

//so if ADRESH contains 0x03
//and ADRESL contain 0xFF

//then adc_data contains 
adc_data = 0x03FF;


Hope this helps you...

:)
 
yeah sure chimera786


Suppose your adc converts an analog signal suppose 5V analog voltage to 1023
So 1023 in HexaDecimal is 3FF
if You Choose Right Justified then FF will be stored in ADRESL register
Means ADRESL = 0xFF;

and

ADRESH will contain 0x03

I generally follow this methodology as it is similar to real world
but if you choose left justified
the values in Register's are as follow:
ADRESH = 0x3F
ADRESL = 0xF0

which i personally feels not good for me.. but one can use this if they want
I like the Right Justified one...

And the logic to merge these into a single variable is also simple
Declare a variable as
unsigned int adc_data;

when conversion gets over use these statements
Code:
                adc_data = ADRESH & 0x00FF;               //Declare adc_data as unsigned int type
		adc_data = adc_data<<8;
		adc_data = adc_data | ADRESL;

//so if ADRESH contains 0x03
//and ADRESL contain 0xFF

//then adc_data contains 
adc_data = 0x03FF;


Hope this helps you...

:)


Very nice Arun :smile:. Again, very clear and very straight forward. So, to understand the above lines of code:

adc_data = ADRESH & 0x00FF; --------> This command keeps all the bits in the ADRESH register by 'and'ing it with 0x00FF.

adc_data = adc_data<<8; ----------> This command shifts the bits??? (i am little unclear on this one)

adc_data = adc_data | ADRESL; -------> This command 'OR's (the 'add'ed and 8 times shifted value) with ADRESL to attain the final 10 bit result.

Can you please explain:

adc_data = adc_data<<8; ----------> This command shifts the bits??? (i am little unclear on this one)

Thanks!
 

Okay

Suppose ADRESH = 0x03F;
and ADRESL = 0xFF;

when you apply this statement
adc_data = ADRESH & 0x00FF;
adc_data = 0x0003;
Okay

now adc_data = adc_data<<8;
shift this data by eight BITS not bytes..
adc_data = 0B0000000000000011 //this is in binary
adc_data = adc_data<<8;
means

adc_data = 0B0000001100000000;
means adc_data = 0x0300;

okay
now apply this command

adc_data = adc_data | ADRESL

this will give u final result


Hope this Help you..
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top