pedestrian readadc with all bells & whistles

womai

Senior Member
I was playing around with the ADC on a PIC12F683 - although the compiler I use has a built-in adc_read library function I wanted to have a bit more control over the actual settings (e.g. which sample clock to use). After writing the code I could not resist and ported it over to the Picaxe 08M (which incidentally is based on the 12F683...). With some small changes the same code should also run on other Picaxes up to the 28X1 and 40X1 (the X2 series has a different SFR setup and so would need a bit more work).

Anyway, here is the sample program. It basically replaces the readadc10 function. One application could be to use pin1 as the reference input (instead of the supply voltage as the built-in Picaxe readadc function does) by setting VCFG to 1 - could come handy when you input voltage range is smaller than 0V to VCC because it can give you better resolution over a smaller range.

To replace readadc instead of readadc10, change the format to left justified (ADFM=0) and only read back a single byte (adc_res_hi).

Wolfgang

Code:
symbol ANSEL = 0x9f

symbol ADCON0 = 0x1f
symbol ADON = bit0
symbol GO_DONE = bit1
symbol CHS0 = bit2
symbol CHS1 = bit3
symbol VCFG = bit6
symbol ADFM = bit7

symbol ADRESH = 0x1e
symbol ADRESL = 0x9e

symbol SFR_reg = b0
symbol counter = b1

symbol adc_res = w1
symbol adc_res_lo = b2
symbol adc_res_hi = b3

setfreq m4

dirs = %00000000 ' all inputs (especially pin1)

peek ANSEL, SFR_reg
SFR_reg = %01110010; // Use RC oscillator as sample clock; configure pin1 as analog (ADC) pin
poke ANSEL, SFR_reg

peek ADCON0, SFR_reg
VCFG = 0; // use Vdd as voltage reference
ADFM = 1; // result is right Justified
ADON = 1; // enable A/D converter
poke ADCON0, SFR_reg

adc_loop:

    'readadc10 1, adc_res ' built-in ADC routine
    gosub adc_read
    
    sertxd (#counter, ": ", #adc_res, cr, lf)
    inc counter
    pause 500
    
goto adc_loop


' acquires ADC
' result is in adc_res
adc_read:

    peek ADCON0, SFR_reg 
    
    ' select channel to measure (0 to 3)
     
    'CHS1 = 0 : CHS0 = 0 ' channel 0
    CHS1 = 0 : CHS0 = 1 ' channel 1
    'CHS1 = 1 : CHS0 = 0 ' channel 2
    'CHS1 = 1 : CHS0 = 1 ' channel 3

    poke ADCON0, SFR_reg
    
    GO_DONE = 1; // to start conversion
   
       poke ADCON0, SFR_reg ' conversion starts now
       
       ' wait for conversion to finish
    do
        peek ADCON0, SFR_reg
    loop while GO_DONE > 0

    ' read result into adc_res
    peek ADRESL, adc_res_lo
    peek ADRESH, adc_res_hi

return
 
Last edited:
Top