PDA

View Full Version : MCP3208 12 bit A/D driver



polymer52
- 5th February 2010, 11:59
Here is a driver written in assembly for the MCP3204 or MCP3208 12 bit A/D converter.
I've included the PBP defines to use it with the 16F628 and can be dropped in your program exactly as shown.
It will scan through the inputs and store the results in an array.


'************************************************* ***********************************
'* The following must be defined in PBP (PIC16F628) Fuses are example only.
'*************************************** FUSES ***********************************
@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _LVP_OFF & _CP_OFF
'************************************************* ***********************************
TRISA=%00110000 'PortA data direction. 1=Input, 0=Output. Default is all inputs
TRISB=%11100010 'PortB data direction. 1=Input, 0=Output. Default is all inputs
CMCON=7 'Turn off analog comparators
DEFINE OSC 4 '4 MHz oscillator
PAUSE 100 'Wait .1 second
'************************************************* ***********************************
ADCE VAR PORTB.3 'A/D Chip enable Output
AH VAR BYTE 'Input = Channel select, Output High byte conversion
AL VAR BYTE 'Output Low byte conversion
CLK VAR PORTB.0 'Clock pin -> Output
DATAOUT VAR PORTB.1 'IO -> Processor <-Input
DATAIN VAR PORTB.2 'Processor -> IO ->Output
RESULT VAR WORD[8] '8 position array. Change to suit your needs
SPI_CNT VAR BYTE 'Bit count for SPI ->Output
Temp VAR WORD 'Temporary storage a/d readings

'*********************************** MAIN PROGRAM ***************************
MAIN:
J=0 'Clear counter
For J=0 to 3 'Loop through 4 inputs. Change to suit your needs
AH=J 'Select channel
GOSUB MCP3204 'Get A/D data
Temp.highbyte=ah 'Add High byte to Temp
Temp.lowbyte=al 'Add Low byte to Temp
RESULT[J]=Temp 'Store in array

NEXT J
GOSUB Somewhere and do stuff with RESULT[x]

GOTO MAIN
END

'*********************************** ASM Routine ********************************
MCP3204:
ASM
swapf _AH,f ;Channel select to high nibble
bsf _AH,7 ;Set for single ended
rrf _AH,f ;Position channel select for device
bsf _AH,7 ;Set start bit
bcf _ADCE ;Enable device
movlw _AH ;Point to channel select in AH
movwf FSR ; /
movlw 5 ;send out 5 bits
movwf _SPI_CNT
call doutw ; /
movlw 6 ;read 6 bits
movwf _SPI_CNT
call dinw ;Null bit + upper 4 bits of data to AH
movlw _AL ;Point to AL to read lower 8 bits of data
movwf FSR ; /
call din8 ; /
movlw 0x0f ;Mask out upper 4 bits of AH
andwf _AH,f ; /
bsf _ADCE ;Disable device
goto Done
;
doutw movwf _SPI_CNT
;
dout bcf _DATAIN ;Assume that the bit to be transfered is a
;'0'. Hence, de-assert DATAIN.
rlf INDF, F ;Rotate the actual bit to be transferred into
;the carry bit.
btfsc STATUS,C ;Test the carry, if our assumption was
;correct, skip the next instruction.
bsf _DATAIN ;No, actual bit was a '1'. Assert DATAIN.
bsf _CLK ;Clock (CLK) = '1'.
nop ;Adjust the number of nop instructions
;between the assertion and de-assertion of
;CLK in proportion to the PIC operating
;frequency.
bcf CLK ;Clock (CLK) = '0'.
decfsz _SPI_CNT, F ;Repeat until cnt = 0.
goto dout ;Cnt still > 0.
rlf INDF, F ;Restore register to its original condition.
bcf _DATAIN ;make sure DATAIN is low
return
;
din8 movlw 8 ;Initialize loop counter.
dinw movwf _SPI_CNT ;
din bcf STATUS,C ;assume data zero
btfsc _DATAOUT ;test DATAOUT for zero
bsf STATUS,C ;if not zero set carry
rlf INDF, F ;rotate data
bsf _CLK ;Clock (CLK) = '1'.
nop ;Adjust the number of nop instructions
;between the assertion and de-assertion of
;CLK in proportion to the PIC operating
;frequency..
bcf _CLK ;Clock (CLK) = '0'.
decfsz _SPI_CNT, F ;Repeat until cnt = 0.
goto din ;Cnt still > 0.
return
Done
nop
Endasm
RETURN