I am having a problem using a 2.5 volt reference for adc conversions. The result has an offset error( which is consistent and correctable in software). The error does not exist if 5 volts is used as reference. I have duplicated the problem in a seperate test circuit. No inputs or outputs where left floating. I have even used different chips to insure it was not a bad chip. At this point I figure it has to be something I am doing in intial setup. I have included the test circuits code below. Any help, suggestions, or ideas would be appreciated. (and yes I fully expect it to be some kind of dumb mistake on my part so feel free to point it out that way)
'************************************************* ********
' Config Settings *
'************************************************* ********
@ DEVICE pic16F917,FCMEN_ON
@ DEVICE pic16F917,IESO_ON
@ DEVICE pic16F917,BOD_OFF
@ DEVICE pic16F917,MCLR_OFF
@ DEVICE pic16F917,CPD_OFF
@ DEVICE pic16F917,WDT_OFF
@ DEVICE pic16F917,PWRT_ON
@ DEVICE pic16F917,INTRC_OSC_NOCLKOUT
'************************************************* ********
' LCD Defines *
'************************************************* ********
define LCD_DREG PORTB 'PORTB is LCD output register
define LCD_RSREG PORTC 'PORTD will contain LCD control bits
define LCD_RSBIT 0 'RS (register select) is bit 1
define LCD_EREG PORTC
define LCD_EBIT 2 'E (enable) is bit 2
define LCD_BITS 8
'************************************************* ********
' Constants *
'************************************************* ********
Samples CON 25 'number of A2D samples to average for result
'************************************************* ********
' Variable Declarations *
'************************************************* ********
Delay1 var byte ' timing loop variable
Delay2 var byte ' timing loop variable
ADval var word ' holds result of A2D conversion
ADCHS var byte ' A2D Channel to convert
' 20 = AN5(pin 8), 24 =AN6(Pin 9)
' 28 =AN7(Pin 10)
' value OR'ed with ADCON0 to complete the setup
ALoop var byte 'conversion sampling loop count
TempAD var word 'holds A2D samples for averaging
GOTO START
'************************************************* ********
' MPU Setup - inline assembly block *
'************************************************* ********
INIMPU:
asm
Delay1 res 1
Delay2 res 1
bsf STATUS,RP0 ; Select Bank 1
movlw 0xEC ; set A<5:1:0> as digital I/O
movwf ANSEL ; A<3:2> and E<2:0> as analog
movlw 0Fh ; set A<3:0> as inputs
movwf TRISA ; (A<3:2> analog, A<1:0> digital)
;A<7:4> as outputs(digital)
movlw 10h
movwf ADCON1 ; set A2D Clock Fosc/8
movlw 00h
movwf TRISB ; set PORTB as outputs
movlw 08h ; set PORTC C<2:0> as outputs
movwf TRISC ;C<7:3> as inputs
; C<7:4> not used, will be reconfigured if needed
movlw 0xFF
movwf TRISD ; set PORTD as inputs
movlw 0Fh
movwf TRISE ; set PORTE as inputs
bcf STATUS,RP0 ; Select Bank 2
bsf STATUS,RP1 ;
clrf LCDCON ; Disable VLCD<3:1>
; inputs on RC<2:0>
bcf STATUS,RP0 ;Select Bank 0
bcf STATUS,RP1 ;
;clear all outputs
clrf PORTA
clrf PORTB
clrf PORTC ; RS and RW low
clrf PORTD
clrf PORTE
DelayLoop ;allow time for display to initialize
decfsz Delay1,f
goto DelayLoop
decfsz Delay2,f
goto DelayLoop
return
endasm
'************************************************* ********
' Main Program *
' continous loop to get and display A2D result *
'************************************************* ********
Start:
gosub INIMPU 'initialize MPU
DoConvert:
ADCHS = 20 ' ORed with ADCON0 in A2D to select channel
gosub A2D ' get conversion - stored in ADval variable
lcdout $FE,1, dec adval 'put ADC count on display
pause 1000 'wait one second before doing it again
Goto DoConvert
'************************************************* ********
' Analog to Digital Conversion *
' The AD Module is turned on with the first call to this routine *
' and stays on *
'************************************************* ********
A2D:
ADVal = 0 ' clear results from last conversion
TempAD = 0 '
ADCON0 = %11100001 | ADCHS ' Configure and turn on A/D Module
pauseus 25 ' settling time
For ALoop = 1 to Samples ' number of samples to do
ADCON0.1 = 1 ' start conversion
notdone:
If ADCON0.1 = 1 Then notdone ' wait until conversion is done
ADval.highbyte = ADRESH ' Move HIGH byte of result to ADval
ADval.lowbyte = ADRESL ' Move LOW byte of result to ADval
TempAD = TempAD + ADval
next ALoop
ADval = TempAD/Samples 'get conversion result
' The result has an offset error, the average slope of which is
' 0.772023. .772 is accurate within a couple counts and thus is
' acceptable for our use here. To keep from dealing with floating
' point math we will multiply by 772 and divide by 1000 and only
' concern ourselves with the whole number result.
' Uncomment these two lines to use the correction
'Dummy = ADval*772 'compensate for error offset
'Adval = div32 1000 '
return
Bookmarks