|
;AD 2500 Assembler synthax used.
;This code works with AD7714 running at 2457.6 KHz, the POL (pin 4) = 1.
;The MCU is Atmel AT89C2051 running at 11059.2 KHz.
;The AD7714 ADC is connected to MCU with two wires (SCLK and SDAT).
;(both DIN and DOUT are tied together to SDAT)
;The ADC gets initialized, calibrated and then all its 4 channels
;are sequentially read 10 times a second to adc_bin 3-byte buffer
;as a 23-bit plus sign absolute value (LSB first).
;Channel samples can be processed on-the-fly - just write
;the appropriate Process_ADC_chX routines.sclk .reg p3.5 ;ADC (AD7714) serial clock out
sdat .reg p3.7 ;ADC serial data I/O (DIN and DOUT tied together)flags .reg 28h ;Misc flag bit register
adc_bin .reg 4ch ;ADC binary sample buffer (LSB), 3 bytes
sign .reg flags.1 ;ADC sign bit (1=negative)
f25 .reg flags.2 ;25 ms flag.org 0
res_vec:
ljmp init.org 0bh
t0_vec:
ljmp t0_int;&&&&&&&&&&&&&&&&&&&&&&&&&&&
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;Initialization.org 30h
init:
mov sp,#50hmov tmod,#00100001b ;Setup T0 as 16-bit, T1 as 8-bit auto-reload timer
mov tl0,#<-23040 ;For 40 Hz int (every 23040 timer clocks)
mov th0,#>-23040 ;at Fxtal = 11059.2 KHzmov r7,#40 ;Set up T0 extender to 1000 mS for 1st time
clr f0 ;Clear 100 mS flag
clr f25 ;Clear 25 mS flagmov ie,#00000010b ;Enable T0 ints
clr tf0
setb tr0 ;Run T0
setb ea ;Global int enable
jnb f0,$ ;Wait for 1000 mS before first ADC channel calibration
clr f0 ;Clear 100 mS flagmov a,#3 ;Select ADC ch4
mov r3,#00100100b ;Self-cal, gain=2 (+-1.25V), no burnout current
call initadc ;Initialize ADC and launch self-calibration sequencejnb f0,$ ;100 mS delay before next ADC channel calibration
clr f0 ;Clear 100 mS flagmov a,#2 ;Select ADC ch3
mov r3,#00100100b ;Self-cal, gain=2 (+-1.25V), no burnout current
call initadc ;Initialize ADC and launch self-calibration sequencejnb f0,$ ;100 mS delay before next ADC channel calibration
clr f0 ;Clear 100 mS flagmov a,#1 ;Select ADC ch2
mov r3,#00100100b ;Self-cal, gain=2 (+-1.25V), no burnout current
call initadc ;Initialize ADC and launch self-calibration sequencejnb f0,$ ;100 mS delay before next ADC channel calibration
clr f0 ;Clear 100 mS flagmov a,#0 ;Select ADC ch1
mov r3,#00100100b ;Self-cal, gain=2 (+-1.25V), no burnout current
call initadc ;Initialize ADC and launch self-calibration sequence
;*************** Main cycle *************main:
jnb f0,main ;Wait for a new 100-mS interval flagclr f0 ;Reset 100 mS flag for current cycle
clr f25 ;Reset 25 mS flagmov a,#0 ;Set ch0 for next conversion
call readadc ;Read ADC ch3 value
; call Process_ADC_ch3 ;Any routine to process ADC ch3 value
jnb f25,$ ;Ensure ADC conversion cycle is complete
clr f25 ;(25 mS)mov a,#1 ;Set ch1 for next conversion
call readadc ;Read ADC ch0 value
; call Process_ADC_ch0 ;Any routine to process ADC ch0 value
jnb f25,$ ;Ensure ADC conversion cycle is complete
clr f25 ;(25 mS)mov a,#2 ;Set ch2 for next conversion
call readadc ;Read ADC ch1 value
; call Process_ADC_ch1 ;Any routine to process ADC ch1 value
jnb f25,$ ;Ensure ADC conversion cycle is complete
clr f25 ;(25 mS)mov a,#3 ;Set ch3 for next conversion
call readadc ;Read ADC ch2 value
; call Process_ADC_ch2 ;Any routine to process ADC ch2 value
ajmp main ;That's all until next 100 mS;*************** End of main cycle *************
;^^^^^^^^^^^^^^^^^ Subroutines ^^^^^^^^^^^^^^^^
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;Issues ADC initializing commands and sets mode from r3
initadc:
push 2
mov r2,amov a,#0ffh ;Reset ADC serial interface
call spi_tx
call spi_tx
call spi_tx
call spi_txmov a,#00100000b ;Request FILT_H register write
orl a,r2
call spi_tx
mov a,#01000000b ;Bipolar, 24 bit word, no current boost, high(153)
call spi_txmov a,#00110000b ;Request FILT_L register write
call spi_tx
orl a,r2
mov a,#10011001b ;low(153), full (3x) conversion time = 24 mS
call spi_txmov a,#00010000b ;Request MODE register write
orl a,r2
call spi_tx
mov a,r3 ;Set requested mode
call spi_txpop 2
ret
;
;&&&&&&&&&&&&&&&&&&&&&&&&&&&
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;Reads and stores raw ADC data as 23-bit abs value, manages sign flag
readadc:
orl a,#01011000b ;3 LSbits = ch# for next conversion cycle
call spi_tx ;Transmit ADC ch# for next conversion cyclecall spi_rx ;MSB
mov c,acc.7
cpl c ;!!! AD7714 sends MSb=0 for negative
mov sign,c ;Store sign (1=neg)
mov adc_bin+2,acall spi_rx ;2SB
mov adc_bin+1,acall spi_rx ;LSB
mov c,sign ;Shift 23-bit word left w/cyclic carry
rlc a
mov adc_bin+0,amov a,adc_bin+1
rlc a
mov adc_bin+1,amov a,adc_bin+2
rlc a
mov adc_bin+2,ajnb sign,adc_pos ;Don't negate a positive rdg
mov a,adc_bin ;Do negate a negative rdg
cpl a
add a,#1
mov adc_bin,amov a,adc_bin+1
cpl a
addc a,#0
mov adc_bin+1,amov a,adc_bin+2
cpl a
addc a,#0
mov adc_bin+2,aorl a,adc_bin+1 ;Convert -16777216 to -16777215 if necessary
orl a,adc_bin
jnz adc_poscpl a
mov adc_bin,a
mov adc_bin+1,a
mov adc_bin+2,aadc_pos:
ret
;
;&&&&&&&&&&&&&&&&&&&&&&&&&&&;^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;SPI byte receive to A
spi_rx:
clr sclk ;Strobe SCLK to 0
mov c,sdat ;Send SDAT to carry flag
setb sclk ;Strobe SCLK back to 1
rlc a ;Shift in the carry flag to Aclr sclk ;Repeat the above 7 times more
mov c,sdat
setb sclk
rlc aclr sclk
mov c,sdat
setb sclk
rlc aclr sclk
mov c,sdat
setb sclk
rlc aclr sclk
mov c,sdat
setb sclk
rlc aclr sclk
mov c,sdat
setb sclk
rlc aclr sclk
mov c,sdat
setb sclk
rlc aclr sclk
mov c,sdat
setb sclk
rlc aret
;
;&&&&&&&&&&&&&&&&&&&&&&&&&&&;^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;SPI byte transmit from A
spi_tx:
rlc a ;Shift out the ACC MSbit to carry flag
clr sclk ;Strobe SCLK to 0
mov sdat,c ;Send carry flag to SDAT
setb sclk ;Strobe SCLK back to 1rlc a ;Repeat the above 7 times more
clr sclk
mov sdat,c
setb sclkrlc a
clr sclk
mov sdat,c
setb sclkrlc a
clr sclk
mov sdat,c
setb sclkrlc a
clr sclk
mov sdat,c
setb sclkrlc a
clr sclk
mov sdat,c
setb sclkrlc a
clr sclk
mov sdat,c
setb sclkrlc a
clr sclk
mov sdat,c
setb sclkrlc a ;!!! Restore A
setb sdat ;!!! Release QBD port line for further input
ret
;
;&&&&&&&&&&&&&&&&&&&&&&&&&&&;~~~~~~~~~~ Interrupt service routines ~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~
;T0: sets F0 flag every 100 milliseconds
t0_int:
clr tf0mov tl0,#<-23040 ;For 40 Hz int (every 23040 timer clocks)
mov th0,#>-23040 ;setb f25 ;Set 25 mS flag
djnz r7,t0iret ;R7 = timer0 extender
mov r7,#4 ;Preload r7 for next 100 mS cycle
setb f0 ;Set 100 mS flag
t0iret:
reti
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~;~~~~~~~~~~ End of interrupt service routines ~~~~~~~~~~~~~~~~~
.end
E-mail: info@telesys.ru