You will produce a digital voltmeter which is controlled and
read over an RS-232 serial line connected to a PC window. The DVM will be
8-channel, with 3 digit accuracy, reading 0.00 to 5.00 volts.
Procedure:
You should wire a voltage divider using the 150 ohm resistor packs to produce eight voltages between 0 and 5 volts for testing the eight analog inputs. Connect the eight voltage divider outputs to A/D inputs, port0.0 through port 0.7 respectively. The resistor packs are arranged as eight separate 150 ohm resistors. Once all the input channels are connected to the voltage divider, you may want to check the voltages with a separate DVM.
As explained in the Users Guide, the 10-bit A/D
result is in two separate registers which also contain the channel number.
The following code fragment sets up the conversion, waits for completion,
then assembles the 10-bit result. The byte variable, ch_num,
is
set by the program
containing a number between 0 and 7. The word variable, v,
contains the 10-bit result.
After you read the 10-bit voltage,
you will need to figure out how to convert the result into
a 3 digit, ASCII formatted number.
addb ad_command, ch_num, #8h ;set A/D ch and trigger conversion
wait: bbs ad_result_lo,3, wait ;wait for result
ldb v+1, ad_result_hi ;read top bits result
ldb v, ad_result_lo ;read low bits result
shr v, #6h ;shift out channel info
One way of handling the serial i/o is to have interrupt routines for transmit
and receive functions. This scheme allows the fast cpu to perfrom other functions
while waiting for the slow serial interface. The program you are being asked
to write does not have enough to keep the cpu busy between messages sent,
so you will have to write some sort of synchronization scheme so that one
message is completely sent before the next is started. A code fragment below
shows basic transmit and receive interrupt routines.
Details:
;
$include(a:serial.inc)
;
rseg at 20H
mes_ptr:dsw 1 ;pointer to text message
m_end: dsw 1 ;end of the text message
busy: dsb 1 ;serial Tx busy
;
cseg at 2080H
;
start: ld sp, #100h ;stack pointer
clrb busy ;Tx is not busy now
;
di ;disable interrupts
;
;setup serial port
ldb ioc1, #20h ;enable Tx pin
ldb int_mask1, #3h ;enable xmit & recx intrrupts
ldb int_mask, #0h ;disable the rest
ldb sp_con, #9h ;standard serial mode & read enable
;next two bytes MUST be loaded in this order
ldb baud_rate, #77d ;9600 baud rate
ldb baud_rate, #80h ;rate upper byte
;
ei ;enable interrupts
;
;send the 'voltage=' message
wait1: jbs busy,0, wait1 ;wait for clear buffer
ld mes_ptr, #message ;message location
ld m_end, #mes_end ;message endbyte
ldb sbuf, [mes_ptr]+ ;send first byte
;transmit interrupt will now occur after each char is sent
incb busy ;set busy flag
;
; --- more program goes here ----
;
;transmit interrrupt
int08: pusha
cmp mes_ptr, m_end ;end of message?
bne writeit ;if not, write char
clrb busy ;else clear busy and leave
br return
writeit:ldb sbuf, [mes_ptr]+ ;trigger next char
return: popa
ret
;
;receive interrupt
;
int09: pusha
ldb temp, sbuf ;get a single char
popa
ret
;
;Constant strings
;
message:dcb 'Voltage='
mes_end equ $
;
crlf: dcb 0dH, 0aH ;CR, LF
;
go: dcb 'g'
stop: dcb 's'
decimal:dcb '.'
zero: dcb '0' ;Useful for generating ASCII digits
;
end
serial.inc
.
Write a program which will repeatedly:
s
to stop data collection
g
to start data collection
0
to 7
for channel number selection
Voltage on channel n=x.yz volts(CR)(LF)
over the 186KBs serial port to a terminal window on the PC. The (CR)(LF)
represents carriage-return and line-feed characters. The n
represents the current channel number and x.yz
the voltage on that channel.
For extra credit, add the ability to sample several channels, rather than
just one at a time. The command string from the PC might be
145(CR)
signifying that channels 1,4 and 5 should be sampled.
When you demonstrate the program to a staff member, you should exercise all the keyboard commands typed from the PC and show that the voltages displayed in the PC window are correct.
Your written lab report should include: