12 bit ADC conversion simple code not working as expected
ADCON1= 0b00000000; //format setup see page 182 of datasheet


I think that's not right, for a start.  That register controls more than just the format.  Bits 0-2 control the voltage references (000 is ok for that - VDD and VSS). Bit 7 controls the format. But, bits 4-6 control the conversion clock.

You set those to 000 - that equates to \$F_{OSC}/2\$. That's a 16MHz internal clock source divided by 2 (judging by your config settings).  So an 8MHz conversion clock.  That's faaaast.  If you look at Table 17-1:



A 16MHz clock, with \$F_{OSC}/2\$ is 125ns clock period, with a pointer to note 2, which states:


  These values violate the minimum required T AD time.


So you are violating your \$T_{AD}\$ time, eh? So maybe the ADC isn't actually able to return any meaningful results then?

Maybe you should try slowing down the ADC so that it will operate within specifications - maybe to \$F_{OSC}/16\$ as the fastest valid setting for a 16MHz clock source.

That would equate to a setting of 0b101, which would make that line of code:

ADCON1= 0b01010000; //format setup see page 182 of datasheet


Another issue with that register is your format.  You have bit 7 set to 0.  That equates to "Sign and Magnitude" result.  It's better to work with the 2's complement result, since that is "normal" maths in a microcontroller.  You can see the difference in Table 17-2:



At the moment you are shifting your high value left 4 bits then ORing it with the lower 8 bits.  With "Sign and Magnitude" you end up with, for the example there of +2355:

ADRESH = 10010011
ADRESL = 00110000

ADRESH &lt;&lt; 4 = 100100110000
OR ADRESL = 100100110000


That is assuming it even keeps the highest 4 bits and doesn't truncate them (not sure off hand which it'll do).

That result is obviously wrong since the lower 4 bits of the ADRESH overwrite the upper 4 bits of ADRESL.

Using 2's complement mode, and shifting 8 bits not 4 results in:

ADRESH = 00001001
ADRESL = 00110011

ADRESH &lt;&lt; 8 = 0000100100000000
OR ADRESL = 0000100100110011


And that is your full 12 bits.

So first you need to set that 7th bit of your configuration to 1, so finally it is:

ADCON1= 0b11010000; //format setup see page 182 of datasheet


And then you need to fix your bit shifting:

analog_reading = ((bit_val &lt;&lt; 8) | ADRESL); //shift it up by 8 bits then
                                            //store ADRESL in the bottom 8 bits