PDA

View Full Version : Hardware SPI with AD7680 16 bit ADC



Castor
- 30th May 2008, 16:46
http://img145.imageshack.us/img145/1979/adclf3.th.jpg (http://img145.imageshack.us/my.php?image=adclf3.jpg) http://img229.imageshack.us/img229/8586/ad7680cj8.th.jpg (http://img229.imageshack.us/my.php?image=ad7680cj8.jpg)

I'm trying to interface the AD7680 16 bit ADC with a pic18F4685 running at 20MHZ, external osc. The timing diagram for the AD7680 is attached as a thumbnail. The shiftin command is not an option.
I'm using the 24 sclk transfer which should output the result as: 4 leading 0, 16bit result, 4 trailing 0. For that i'm using 3 variables: one, two, three. In theory the result would be:

one: 0000 xxxx
two: xxxx xxxx
three: xxxx 0000, where x is a relevant bit




DEFINE OSC 20
DEFINE LCD_DREG PORTD' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_DBIT 4' Set LCD Register Select port
DEFINE LCD_RSREG PORTD' Set LCD Register Select bit
DEFINE LCD_RSBIT 0' Set LCD Enable port
DEFINE LCD_EREG PORTD' Set LCD Enable bit
DEFINE LCD_EBIT 2' Set LCD bus size (4 or 8 bits)
DEFINE LCD_BITS 4' Set number of lines on LCD
DEFINE LCD_LINES 2' Set command delay time in us
DEFINE LCD_COMMANDUS 3000' Set data delay time in us
DEFINE LCD_DATAUS 100

' -----[ Variables ]-------------------------------------------------------

led var portd.3 'led connected to portd.3
sd_mps var porte.1 'shutdown pin on the main power supply
ad_cs Var PortC.5 ' ad chip select line
' -----[ Initialization ]--------------------------------------------------

adcon1=$0F 'all digital i/o
CMCON=$07 'disable comparators

trisa=%11000001 'porta HZ; except mux pins
trisb=$FF 'portb HZ
trisc=%11010111 'portc HZ; except ad lines
trisd=%00000000 'set the lcd lines as digital output
trise=%00000000 'porte output

SSPCON1=%00110000
SSPSTAT=%11000000

'variables

one var byte
two var byte
three var byte

a_mux var porta.1
b_mux var porta.2
c_mux var porta.3
d_mux var porta.4
inh var porta.5

pause 2000 'lcd init
main:
high inh
lcdout $FE, 1 'clear lcd
high ad_cs
high led 'turn on running led
high sd_mps 'turn on the main power supply

low a_mux:high b_mux:low c_mux:low d_mux:low inh 'select channel 0
pauseus 10

low ad_cs 'turn on the a/d converter

SSPBUF = 0 ' write to SSPBUF to start clock
PauseUs 25 '25uS fudge factor
while !SSPSTAT.0 :WEND ' while buffer empty
PauseUs 25 '25uS fudge factor
SSPSTAT.0=0
one=SSPBUF

SSPBUF = 0
PauseUs 25 '25uS fudge factor
while !SSPSTAT.0 :WEND ' while buffer empty
PauseUs 25 '25uS fudge factor
SSPSTAT.0=0
two=SSPBUF

SSPBUF = 0
PauseUs 25 '25uS fudge factor
while !SSPSTAT.0 :WEND ' while buffer empty
PauseUs 25 '25uS fudge factor
SSPSTAT.0=0
three=SSPBUF

high ad_cs 'turn off the a/d converter

high inh 'disable mux
LCDOUT $FE, $80, BIN one 'print first byte of result, first line
LCDOUT $FE, $C0, BIN two
LCDOUT $FE, $94, BIN three
pause 1000

goto main

Castor
- 2nd June 2008, 08:32
If I use shiftin or a similar routine it works fine. Here is my shiftin clone. Why won't HARDWARE SPI work ?

Might it be because I connected the SPI's SDO (output) to the ADC CS line ? (see first post, first attachment)



DEFINE OSC 20
DEFINE LCD_DREG PORTD' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_DBIT 4' Set LCD Register Select port
DEFINE LCD_RSREG PORTD' Set LCD Register Select bit
DEFINE LCD_RSBIT 0' Set LCD Enable port
DEFINE LCD_EREG PORTD' Set LCD Enable bit
DEFINE LCD_EBIT 2' Set LCD bus size (4 or 8 bits)
DEFINE LCD_BITS 4' Set number of lines on LCD
DEFINE LCD_LINES 2' Set command delay time in us
DEFINE LCD_COMMANDUS 3000' Set data delay time in us
DEFINE LCD_DATAUS 100

' -----[ Variables ]-------------------------------------------------------
one var byte
two var byte
three var byte
result var word

a_mux var porta.1
b_mux var porta.2
c_mux var porta.3
d_mux var porta.4
inh var porta.5

led var portd.3 'led connected to portd.3
sd_mps var porte.1 'shutdown pin on the main power supply


dat var portc.4
sclk var portc.3
ad_cs var portc.5 ' ad chip select line

i var byte

' -----[ Initialization ]--------------------------------------------------

adcon1=$0F 'all digital i/o
CMCON=$07 'disable comparators

trisa=%11000001 'porta HZ; except mux pins

' 7 6 5 4 3 2 1 0 <= TRISA
' | | | | | | | |___________ charger control
' | | | | | | |
' | | | | | | |_____________ MUX - A
' | | | | | |
' | | | | | |_______________ MUX - B
' | | | | |
' | | | | |_________________ MUX - C
' | | | |
' | | | |___________________ MUX - D
' | | |
' | | |_____________________ MUX - INH
' | |
' | |_______________________ oscilator
' |
' |_________________________ oscilator

trisb=$FF 'portb HZ

' 7 6 5 4 3 2 1 0 <= TRISB
' | | | | | | | |___________ charger enable
' | | | | | | |
' | | | | | | |_____________ backup battery level
' | | | | | |
' | | | | | |_______________ CAN TXD
' | | | | |
' | | | | |_________________ CAN RXD
' | | | |
' | | | |___________________ keyswitch
' | | |
' | | |_____________________ DCD - C
' | |
' | |_______________________ DCD - B
' |
' |_________________________ DCD - A

trisc=%11010111 'portc HZ; except ad lines

' 7 6 5 4 3 2 1 0 <= TRISC
' | | | | | | | |___________ capacitor enable
' | | | | | | |
' | | | | | | |_____________ matrix switch off
' | | | | | |
' | | | | | |_______________ DC/DC sync
' | | | | |
' | | | | |_________________ A/D converter SCLK, SPI SCK
' | | | |
' | | | |___________________ A/D converter DATA, SPI SDI
' | | |
' | | |_____________________ A/D converter CS, SPI SDO
' | |
' | |_______________________ DCD - D
' |
' |_________________________ standby

trisd=%00000000 'set the lcd lines as digital output

' 7 6 5 4 3 2 1 0 <= TRISD
' | | | | | | | |___________ LCD RS
' | | | | | | |
' | | | | | | |_____________ LCD R/W
' | | | | | |
' | | | | | |_______________ LCD E
' | | | | |
' | | | | |_________________ running LED/main contactor
' | | | |
' | | | |___________________ LCD D4
' | | |
' | | |_____________________ LCD D5
' | |
' | |_______________________ LCD D6
' |
' |_________________________ LCD D7

trise=%00000000 'porte output

' 7 6 5 4 3 2 1 0 <= TRISE
' | | | | | | | |___________ buzzer
' | | | | | | |
' | | | | | | |_____________ main power supply SD
' | | | | | |
' | | | | | |_______________ DCD - G1, G2
' | | | | |
' | | | | |_________________ MCLR, programmer interface
' | | | |
' | | | |___________________ 0
' | | |
' | | |_____________________ 0
' | |
' | |_______________________ 0
' |
' |_________________________ 0


pause 2000 'LCD power up delay
main:
high inh
lcdout $FE, 1 'clear lcd
high led 'turn on running led
high sd_mps 'turn on the main power supply

low a_mux:high b_mux:low c_mux:low d_mux:low inh 'select channel 0
pauseus 100
high sclk 'clock idles high
low ad_cs 'turn on the a/d converter

result=0 ' result = 00000000 00000000
for i=0 to 7 ' output 8 clocks
one = one * 2 ' Shift each bit to the left
one = one + dat ' Data in port
pulsout sclk,5 ' Clock pulse port, 1 msec
next i

for i=0 to 7 ' output 8 clocks
two = two * 2 ' Shift each bit to the left
two = two + dat ' Data in port
pulsout sclk,5 ' Clock pulse port, 1 msec
next i

for i=0 to 7 ' output 8 clocks
three = three * 2 ' Shift each bit to the left
three = three + dat ' Data in port
pulsout sclk,5 ' Clock pulse port, 1 msec
next i

high ad_cs ' turn off the a/d converter
high inh ' disable mux

result=0 ' result = 00000000 00000000
result=two ' result = 00000000 xxxxxxxx
result=result<<4 ' result = 0000xxxx xxxx0000
result.highbyte=result.highbyte|one<<4 ' result = xxxxxxxx xxxx0000
result.lowbyte=result.lowbyte|three>>4 ' result = xxxxxxxx xxxxxxxx
' voila, 'result' holds the 16 bit conversion result

result=result*/16 'quantisation



LCDOUT $FE, $80, BIN one 'print first byte of result, first line
LCDOUT $FE, $C0, BIN two 'print second byte of result, first line
LCDOUT $FE, $94, BIN three 'print third byte of result, first line
LCDOUT $FE, $D4, DEC result
'must be around 2500
pause 1000


goto main

precision
- 2nd June 2008, 11:16
Here is my shiftin clone.



What is shiftin clone?

.

Castor
- 3rd June 2008, 09:01
it's a routine that does the same thing as the PHP shiftin function