Santiago - 2009-01-24

First i have to say i'm starting with gcbasic and don't know all the features.

When working with ADC with 16f876a i see the 8 bits read and a 10 bit one, but i can't find the way to use Vref or select what channels will be analogic inputs or digital I/O.

Then i adapted some asm routines i had to gcbasic, just to can select the configuration and fast operation in adc readings.

Available functions and how to use are in the driver.

This is the code if useful to someone ( an use example follow the driver):

'________________________________________________________________________________
'
' 10 BIT ADC DRIVER FOR PIC16F87X FAMILY AND COMPATIBLES
'
' (optimized asm)
'
' Original driver name: adc_87X.h
'________________________________________________________________________________
'
'
' This library is free software; you can redistribute it and/or

' modify it under the terms of the GNU Lesser General Public

' License as published by the Free Software Foundation; either

' version 2.1 of the License, or (at your option) any later version.

' This library is distributed in the hope that it will be useful,

' but WITHOUT ANY WARRANTY; without even the implied warranty of

' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

' Lesser General Public License for more details.

' You should have received a copy of the GNU Lesser General Public

' License along with this library; if not, write to the Free Software

' Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
'
'________________________________________________________________________________
'
' AVAILABLE FUNCTIONS (examples):
'________________________________________________________________________________
'
' Configure ADC with fosc/32, 2 adc inputs and Vref+ at RA3:
'
' adc_conf FOSC/32, A2_R1 
'
'
' Configure ADC with fosc/16, 4 adc inputs, Vref+ at RA3 and Vref- at RA2:
'
' adc_conf FOSC/16, A4_R2
'
'
' Configure ADC with fosc/8, 5 adc inputs, no Vref inputs:
'
' adc_conf FOSC/8, A5_R0
'
'
' Open channel 1:
'
' adc_open CH1
'
'
' Read channel previously opened:
'
' adc_read
'
'
' Disable ADC module:
'
' adc_close
'
'________________________________________________________________________________
'
' DEFINITIONS (available options)
'________________________________________________________________________________
'
'Oscillator frecuency: used bit5=ADCON1.ADCS2, bit6=ADCON0.ADCS0, bit7=ADCON0.ADCS1
#define FOSC/2 0x00
#define FOSC/4 0x20
#define FOSC/8 0x40
#define FOSC/16 0x60
#define FOSC/32 0x80
#define FOSC/64 0xA0
#define FOSC_RC 0xE0

'ADC and Vref inputs(PCFG0-3 in ADCON1)
#define A8_R0 0x00
#define A7_R1 0x01
#define A5_R0 0x02
#define A4_R1 0x03
#define A3_R0 0x04
#define A2_R1 0x05
#define A0_R0 0x06
#define A6_R2 0x08
#define A6_R0 0x09
#define A5_R1 0x0a
#define A4_R2 0x0b
#define A3_R2 0x0c
#define A2_R2 0x0d
#define A1_R0 0x0e
#define A1_R2 0x0f

'select channel: used bits 3-5 = ADCON0.CHS0-CHS2
#define CH0 0x00
#define CH1 0x08
#define CH2 0x10
#define CH3 0x18
#define CH4 0x20
#define CH5 0x28
#define CH6 0x30
#define CH7 0x38

'________________________________________________________________________________
'
' FUNCTIONS
'________________________________________________________________________________

sub adc_conf(setfosc, channels) #NR

RLF setfosc,W ; We will take bit 5 from setfosc to put it in ADCON1.ADCS2 
ANDLW 0x40 ; 0x40 = 01000000 select bit 6 from setfosc (5º rotated)
IORWF channels,W ; Join channel and bit 6 from setfosc (5º rotated)
MOVWF ADCON1 ; set config at ADCON1 
BSF ADCON1,7 ; Right justified (10 bits)

; GCBASIC will take care about BANKSELs..!!!
MOVF setfosc,W
ANDLW 0xC0 ; 0xC0 = 11000000 select bits 6-7 from setfosc 
MOVWF ADCON0 ; Set frecuency in ADCON0 (ADCS0, ADCS1)

end sub

sub adc_open(channel) #NR

BCF ADCON0,3 ; Delete previous config
BCF ADCON0,4
BCF ADCON0,5
MOVF channel,W
IORWF ADCON0,F ; Set opened channel
BSF ADCON0,0 ; Enable ADC

end Sub

function adc_read As word

BSF ADCON0,2 ; Start conversion
BTFSC ADCON0,2 ; wait for not busy
GOTO $-1

adc_read = ADRESL
adc_read_H = ADRESH

end function

#define adc_close ADCON0.0 = 0

'_____________________________________________________________________________________
'
' **************************** END OF DRIVER **********************************
'_____________________________________________________________________________________

'USE EXAMPLE:

'_____________________________________________________________________________________
'_____________________________________________________________________________________

'________________________________________________________________________________
'
' Example to be used with adc-87X.h driver
'
'
' A led attached to PORTB.7 will light when Volt. level at PORTA.0 > Vdd/2
'
'________________________________________________________________________________
'

'General hardware configuration

#chip 16F876A, 20

#config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON

#include <adc-87X.h> 
'driver must be in "iclude" dir or probide full path

#define LED1 PORTB.7

'________________________________________________________________________________

DIR A0 IN
DIR B7 OUT

adc_conf FOSC/32, A1_R0

adc_open CH0

do while true

if adc_read > 512 then 
set LED1 on
goto outlabel
end if
set LED1 off

outlabel:

loop

'________________________________________________________________________________