View Full Version : Questions about using the A to D

- 27th August 2014, 02:20
Hi all!
Okay so before some one tells me to read the manual the manual only gives a few "guidelines" and nothing in depth. For example it says the ADC_CLOCK can be a value of 2-5 bits and the default value is 3. It does not say what values 2, 4, and 5 are for. Now I have an 18F1320 and wish to use port b.0 as the input from a sensor putting out 0-5 volts. My best guess is this is what the code should look like?

21 Define ADC_BITS 10 ' Set number of bits in result
22 Define ADC_CLOCK 3 ' Set clock source (3=rc)
23 Define ADC_SAMPLEUS 50 ' Set sampling time in uS
25 adval Var word ' Create adval to store result
27 TRISB = %11111111 ' Set PORTB to all input
28 ADCON2 = %10000010 ' Set PORTB analog and right justify result
30 mainloop:
33 ADCIN 0, adval ' Read channel 0 to adval

The other part of this is that the ICD uses port b.1 and port b.4 so would the TRISB statement mess up the IDC?

Thanks in advance for any and all who wish to help educate me.

Best, Ed

- 27th August 2014, 03:57
The other part of this is that the ICD uses port b.1 and port b.4 so would the TRISB statement mess up the IDC? no

28 ADCON2 = %10000010 ' Set PORTB analog and right justify result

will not set portb analog , and changes adc clock to fosc/32 which contradicts
Define ADC_CLOCK 3 ' Set clock source (3=rc)

ADCIN 0, adval ' Read channel 0 to adval
ano is porta.1 is this what you mean if so then set adcon1 = %00000001

- 28th August 2014, 01:16
Thank you and my wish is to set port B.0 to be the analog input (pin 8). I was not planning on using any of the A ports except for the resonator.

- 28th August 2014, 03:11
my wish is to set port B.0 to be the analog input (pin 8)

portb.0 is an4 use
ADCIN 4, adval ' Read channel 0 to adval
and set adcon1 to %00010000

there is no need to use tris to set the pin to an input just use adcon1 to make it analogue

- 28th August 2014, 06:30

and set adcon1 to %00010000
Hmm.... I think you've got that backwards...
Looking at the 18F1320 datasheet, ADCON1 defaults to 0 which means that AN0-AN6 are all analog. If AN4 is the ONLY pin to be used as analog you need ADCON1 = %11101111


- 28th August 2014, 06:46
there is no need to use tris to set the pin to an input just use adcon1 to make it analogue

From the datasheet

17.6 Configuring Analog Port Pins
The ADCON1, TRISA and TRISB registers all configure
the A/D port pins. The port pins needed as analog inputs
must have their corresponding TRIS bits set (input). If
the TRIS bit is cleared (output), the digital output level
(VOH or VOL) will be converted.

Which I read as saying tris has to be set along with adcon1 to make it analogue?

- 28th August 2014, 07:03
I stand corrected on both counts
it just goes to show when it comes to pics assume nothing , read data sheet twice . the current pic18f45k20 I'm fooling with says in

19.1 ADC Configuration
The A/D operation is independent of the state of the
ANSx bits and the TRIS bits

and I read it again and yes the tris bit should be set , I misinterpreted that for sure

- 28th August 2014, 07:53
Yes the TRIS bit needs to be set.
That, however, doesn't meant you actually need to set it since it IS set by default at POR.


- 29th August 2014, 02:05
Thanks Guys, that part makes sense now. If the ICD uses pin 9 (RB1/AN5/TX/CK/INT1) AND PIN 10 (RB4/AN6/RX/DT/KBI0) does that change the ADCON1 pattern?

- 29th August 2014, 05:40
have a listen to this about icd setup , I believe if you don't make the pins analogue all should be ok
I have been wong before though

- 29th August 2014, 21:52
(A/D threads merged - Robert)

Hi All!
So I have my PIC doing the A to D conversion and the reading is strange! With a volt meter I know the voltage is .441 volts. This should give a value of 362. The value I get is 582 which would be for .710 volts! Now I am completely lost as to why the results are not what is expected. Can anyone explain what I am doing wrong?

Thanks, Ed

'************************************************* ****************
'* Name: XXXXSPEEDT2.bas *
'* Author: Ed Cannady *
'* Notice: Copyright (c) 2011 *
'* : All Rights Reserved *
'* Date: 8/29/2014 *
'* Version: 1.0 *
'* Notes: For a 18F1320 and MS4515 *
'************************************************* *****************

Define OSC 20
Include "Modedefs.bas"
include "hpwm10L.pbp" ' For future calculations


Define ADC_BITS 10

ADCON1 = %11101111
TRISB = %11111111

VOLTS VAR WORD ' Volts reading

VOLTS = 0 ' Start with a Volts value of zero




- 30th August 2014, 17:32
Just in case anyone is looking at this, my original external A/D went from 0-4096. The PIC A/D goes from 0-65535! So a divide by 16 makes everything correct!

- 31st August 2014, 07:09
No it doesn't. The ADC in the 18F1320 (as in most PICs) are 10 bits, ie they return a value ranging from 0 to 1023.

However, since the result is 10bits it needs two 8bit registers (bytes) to store the result and depending on how you have the ADC configured it returns the result left or right justified within those two bytes. So, if the input to the ADC is saturated it returns the value 1023, looking at the two registers for the result (ADRESH and ADRESL) it'll will be either (00000011 11111111 = 1023) or (11111111 11000000 = 65472) depending on if you choose to have the result right or left justified.

Check the ADCON2 register.


- 1st September 2014, 02:11
Hi Henrik!
Thanks! You are always a good friend and a very big help and I mean that sincerely. The PIC returns a "VOLTS" value of 5824 representing the .441 volts I see on a voltmeter. If I divide 5824 by 16 then the reading would be 364. I changed the code to be /16 rather than /10. Using a conversion chart where 5.00 volts equals 4096 then 364 is really close. The sensor does vary a little about every 28 second it will read either + or - 4 using the divide by 16 value or 5824 then 5888 without the divide. Not sure why this happens, it's not temperature related and the reference port and sensor port are connected together with a piece of tubing. I do not know how to display the value in the ADCON2 register to do a check.

Best, Ed

- 1st September 2014, 06:28
Hi Ed,
Your previous ADC had a resolution of 12 bits, ie a value ranging from 0 to 4095.
The PIC ADC has a resolution of 10 bits, ie a value ranging from 0 to 1023 in "steps" of 1 (0, 1 ,2 ,3, 4....) or from 0 to 65472 in "steps" of 64 (0, 64, 128, 192, 256...)

If you divide 65472 by 16 you'll get 4092 which is pretty close to 4095 - that's the reason it "works" for you. And if you divide the "step size" of 64 by 16 you'll get 4 so when you see you're value "bouncing" +/- 4 counts it's really only "bouncing" +/- 1 LSB which is kind of expected.

Try setting ADCON2.7 = 1 to right justify the result and see if you'll get a result from 0 to 1023 with "steps" of 1 instead. If needed, you can then get more resolution by oversampling. Take 16 readings, add them all up and divide by 4 to go from 10 bits to a "psuedo resolution" of 12 bits - for example.

I'm not saying what you're doing is wrong - as long as it works for you I'm happy :-)
I just wanted to clarify for you and others that might find your comment about the ADC is going from 0-65535 that the resolution of the ADC is NOT 16bits which you might think it is when reading your post.


- 1st September 2014, 08:03
Interesting explanation Henrik. I was trying to work out how 0-65535 was achieved knowing that the PIC ADC was 10 bit. Reading the datasheet

The module has five registers:
A/D Result High Register (ADRESH)
A/D Result Low Register (ADRESL)
A/D Control Register 0 (ADCON0)
A/D Control Register 1 (ADCON1)
A/D Control Register 2 (ADCON2)
The ADCON0 register, shown in Register 17-1,
controls the operation of the A/D module. The
ADCON1 register, shown in Register 17-2, configures
the functions of the port pins. The ADCON2 register,
shown in Register 17-3, configures the A/D clock
source, programmed acquisition time and justification.I was puzzling over the last word "justification" and the effect it would have. Now I know.

- 1st September 2014, 09:12
Hi Steve, Ed,

Just to clarify further, it can never return 65535 no matter how you configure it.
It'll look like this, where x is the actual conversion result returned by the 10 bit ADC:

xxxxxxxx xx000000 Left justified, ADCON2.7 = 0 (default)
000000xx xxxxxxxx Right justified, ADCON2.7 = 1
With left justification the two most significant bits in ADRESL are the two least significant bits of the 10 bit result.
With right justification the two least significant bits in ADRESH are the two most significant bits of the 10 bit result.

If you have the ADC set to left justification but look at the result as a "normal" 16 bit value each LSB of the ADC result will change the 16 bit value by 64 since the LSB of the ADC result is aligned with ADRESL.6.

So, with left justification and the ADC saturated the maximum value it can return is 65472 since the 6 least significant bits in ADRESL will be 0.


- 1st September 2014, 16:48
Hi Henrik!
Again thank you! You are correct. I connected a 10K resistor from the +5v to the ADC input pin and got 65472! Probably should have done that first! Just wondering, any way to eliminate the "bounce"?


- 1st September 2014, 17:22
Hi Ed,

Just wondering, any way to eliminate the "bounce"?

Make sure that VRef is stable.
In this case I think you're using Vdd as Vref so proper bypassing right at the supply pin(s) of the PIC. At Vdd/VRef=5V a difference of 4.88mV will make the ADC result "jump" a LSB. So any ripple larger than +/-5mV on the supply will be reflected on the readings.

Make sure that you feed the ADC input from a low(ish) impedence circuit.
If your sensor has a high output impedence you may need to buffer the signal with a OP-amp or whatever. Filter the sensor output then feed it to the buffer then to the ADC input.

Or you can simply try throwing a 10-100nF capacitor right on the ADC input pin....
Or just filter it in software.... which, again, will allow you to oversample and get more resolution (if needed).

Remember, you're seeing a "bounce" of 4 (or 64 actually) but in reallity it's only a single LSB - and that's pretty normal.