This program implements a simple two-digit voltmeter, utilizing an
; AT89Cx051 microcontroller, two resistors, a capacitor and two HP5082-7300
; decimal LED displays. The code is compatible with both the AT89C1051 and
; AT89C2051 when operating with a 12 MHz clock. Code modifications may be
; required for operation at a different clock rate.
; The voltmeter application demonstrates the RC analog-to-digital conversion
; method. The microcontroller uses an output pin, which swings from ground to
; Vcc, to alternately charge and discharge the capacitor through a resistor.
; Utilizing the internal comparator, the microcontroller measures the time
; required for the voltage on the capacitor to match the unknown voltage and
; uses the result as an index into a table. The table contains display values
; corresponding to the capacitor voltage. Each display value is encoded in
; one byte as two BCD digits, which are displayed as volts and tenths of a
; volt on the two decimal displays. There is no software hysteresis, so the
; display may oscillate at a transition voltage.
; The conversion routine, ADC, is general purpose, returning the entry in
; the table which corresponds to the measured time. The table contents may
; be modified to any data format required by an application.
The NOP instructions in the conversion routine are used to delay the first
; sample in the charge and discharge portions of the measurement cycle.
; The amount of delay has an effect on measurement accuracy, and the number
; of NOPs may be adjusted (slightly) for best results.
;
; SCOUNT is defined as the minimum number of samples which must be taken to
; guarantee that the voltage on the capacitor has reached Vcc/2. TCHARGE and
; TDISCHARGE are defined as the minimum time required for the voltage on the
; capacitor to approach within 1/2 delta V of Vcc and ground, respectively.
; The minimum conversion time is approximately TCHARGE + TDISCHARGE, or
; six milliseconds. The maximum conversion time is approximately TCHARGE +
; TDISCHARGE + 2 * (5 microseconds * SCOUNT), or seven milliseconds.
;
; For additional information refer to the application note.
SCOUNT EQU 79 ; minimum samples to reach Vcc/2
TCHARGE EQU 3 ; cap charge time, in milliseconds
TDISCHARGE EQU 3 ; cap discharge time, in milliseconds
DSEG AT 0020H
ORG 0020H ; 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
$INCLUDE(vtable.asm) ; get lookup table
ORG 00E0H ; begin code space
USING 0 ; register bank zero
on_reset:
mov sp, #(stack-1) ; initialize stack pointer
mov IE, #0 ; deactivate all interrupts
mov p1, #0 ; write zeros to displays
mov a, #0ffh ; deactivate output ports
mov p1, a ;
mov p3, a ;
clr p3.7 ; discharge capacitor
mov a, #TDISCHARGE ; wait
call delay_ms ;
loop:
call adc ; convert
call vshow ; display voltage
sjmp loop ; again
ADC:
; Convert analog-to-digital.
; Triggers capacitor charge/discharge and samples the comparator
; output at regular intervals until the comparator changes state.
; The sample interval is five microseconds with a 12 MHz clock.
; A maximum of SCOUNT samples are taken during the charge portion
; of the cycle and SCOUNT samples during the discharge portion of
; the cycle. The number of samples is used as an index into a table
; containing voltage equivalents. The number of table entries is
; twice SCOUNT. If the comparator does not switch, the last table
; entry is returned. Assumes that the capacitor is fully discharged
; on entry, and discharges the capacitor before return.
; The table entry is returned in A. Nothing is saved.
; Charge capacitor.
mov a, #0 ; initialize loop count
setb p3.7 ; begin charging 1 uS
nop ; padding 1 uS
nop ; 1 uS
ad1:
jb p3.6, ad4 ; jump if comp output high 2 uS
inc a ; increment count 1 uS
cjne a, #SCOUNT, ad1 ; loop until timeout 2 uS
; Timeout.
; Be sure capacitor is fully charged.
mov a, #TCHARGE ; wait
call delay_ms ;
; Discharge capacitor.
mov a, #0 ; initialize loop count
clr p3.7 ; begin discharging 1 uS
nop ; padding 1 uS
nop ; 1 uS
ad2:
jnb p3.6, ad3 ; jump if comp output low 2 uS
inc a ; increment count 1 uS
cjne a, #SCOUNT, ad2 ; loop until timeout 2 uS
; Timeout.
dec a ; last count
ad3:
add a, #SCOUNT ; use top half of table
; Fetch table entry.
ad4:
mov dptr, #VoltTable ; pointer to base of table
movc a, @a+dptr ; get voltage data
push acc ; save data temporarily
; Be sure capacitor is fully discharged.
clr p3.7 ; begin discharging
mov a, #TDISCHARGE ; wait
call delay_ms ;
pop acc
ret
vshow:
; Display two BCD digits on a pair of HP5082-7300 displays.
; The four data lines to each display share P1.7:1.4. The units
; display is selected by a low on P1.3 and the tenths display by a
; low on P1.2. The units display is wired to light the decimal point.
; On entry, expects two packed BCD digits in A. Returns nothing.
; All registers preserved, including flags.
push psw
push acc
push acc ; save digits
orl a, #00001111b ; set unused bits
mov p1, a ; write units digit
clr p1.3 ; strobe data into display
setb p1.3 ;
pop acc ; restore digits
swap a ; move low digit into high nybble
orl a, #00001111b ; set unused bits
mov p1, a ; write tenths digit
clr p1.2 ; strobe data into display
setb p1.2 ;
pop acc
pop psw
ret
delay_ms:
; Delay for approximately one millisecond times the value in A.
; All registers preserved, including flags.
push psw
push acc
push b
mov b, #0
ddm:
djnz b, $ ; 512 uS @ 12 MHz
djnz b, $ ; 512 uS @ 12 MHz
djnz acc, ddm
pop b
pop acc
pop psw
ret
END
相关文章