at89c2051 successive approximation a-to-d conversion
name sa_adc_test
; test program to loop on successive approximation a-to-d conversion.
; allows digital codes and resulting dac output to be viewed on 'scope.
dseg at 0020h
org 0060h ; stack origin
stack: ds 0020h ; stack depth
cseg
org 0000h ; power on/reset vector
jmp on_reset
org 0003h ; external interrupt 0 vector
reti ; undefined
org 000bh ; timer 0 overflow vector
reti ; undefined
org 0013h ; external interrupt 1 vector
reti ; undefined
org 001bh ; timer 1 overflow vector
reti ; undefined
org 0023h ; serial i/o interrupt vector
reti ; undefined
org 0040h ; begin constant data space
org 0080h ; begin code space
using 0 ; register bank zero
on_reset:
mov sp, #(stack-1) ; initialize stack pointer
mov ie, #0 ; deactivate all interrupts
mov a, #0ffh ; deactivate output ports
mov p1, a ;
mov p3, a ;
loop:
call adc ; convert
sjmp loop ; again
adc:
; convert analog-to-digital.
; executes a successive approximation algorithm in an attempt to
; find an eight-bit code which causes the dac output to match the
; unknown voltage at the comparator input. the algorithm returns
; one of 256 values ranging from 00000000 (zero volts) to 11111111
; (full scale). the exact correspondence between the code and input
; voltage is determined in hardware.
; before the search begins, zeros are written to the dac and the
; comparator is checked to verify that its output is low. if it is
; not, a code of zero is returned immediately. if the routine
; completes and the comparator output has never gone high, a code
; of all ones is returned, corresponding to full scale.
; delays have been inserted to allow for worst case op amp slew rate,
; resulting in a conversion time of approximately 275 microseconds.
; the code is returned in a. all other registers are preserved.
push b ; save
mov b, r7 ;
push b ;
mov b, #0 ; first code
call dac ; write dac
nop ; wait for op amp to slew f.s. to zero
nop ; plus settling time
nop ; total five us at 12 mhz
nop ;
nop ;
jb p3.6, xxx ; exit if comparator high
clr c ; intialize loop counter/bit mask
mov a, #10000000b ;
aaa:
orl b, a ; set bit in dac code
call dac ; try new code
nop ; wait for op amp to slew 1/2 f.s.
nop ; plus settling time
nop ; total five us at 12 mhz
nop ;
nop ;
jnb p3.6, bbb ; jump if voltage still low, keep bit
xrl b, a ; voltage too high, reset bit
bbb:
rrc a ; shift loop counter/bit mask
jnc aaa ; loop until bit in mask moves into c
xxx:
mov a, b ; return code in a
pop b ; restore
mov r7, b ;
pop b ;
ret
dac:
; write the eight bit code in register b to the dac.
; the six most significant bits of the code are written to the
; six most significant bits of port one. the two least significant
; bits of the code are written to bits five and four of port three.
; it is assumed that the comparator is in use, so the bits in port
; one corresponding to the comparator inputs are set.
; all unused bits are undisturbed.
; no delays are included for dac settling or op amp slewing.
; all registers are preserved.
push b ; save code
orl b, #00000011b ; enable comparator
mov p1, b ; write bits seven to two
pop b ; restore code
mov c, b.1 ; write bit one
mov p3.5, c ;
mov c, b.0 ; write bit zero
mov p3.4, c ;
ret
end