درايور نويسنده پيام با ۸۹C2051
By using a Dontronics DT004 Simmbus mother board it is possible to use the micro-controller of your choice to drive equipment that is designed to be controlled by a PC via it’s parallel port. In this example the device to be controlled is a walking message display. In Silicon Chip magazine February 1997 edition there was an article on just such a device. The only modification required to drive this display from a micro-controller instead of the PC was the inclusion of a 330R resistor from pin8 to ground of the first 74LS164 (IC1). This was found to be necessary to eliminate rogue clock pulses being generated. The micro-controller I used is the 89C2051, mounted on a Dontronics DT104 board. The board also needs an eeprom and max232 on the board. The RS232 interface is used to download messages to be displayed from a PC and the eeprom is used to store the message after downloading. At power up, the software waits a few seconds for a key to be received on the RS232 port. If nothing is received the message is transferred from the eeprom into the 2051’s ram. This is because the eeprom is too slow to read from, because the display is multiplexed. The amount of ram in the 2051 limits the length of the message to be displayed to 60 characters.
Photo of Dontronics DT104 board used for walking message display. Note the components in the top right hand prototype area are not needed for this project. However two of the yellow jumpers on the bottom of the board are required. The parallel port connections required are D0-D6, Strobe, Auto line feed and Select in. The D0-D6 and Strobe connections are connected to the 2051 port1.0 -port 1.6 and port 3.4 respectively. These connections are via the Dontronics DT004 motherboard and don’t require any additional wiring. However the Auto line feed and Select in signals are connected to the Simmbus pins 27 and 30 respectively. The Dontronics DT104 board does not have any connection to these pins. Therefore they need to be linked to a 2051 port. Auto line feed pin 27 should be linked to pin 23, 2051 port 3.2 and Select in pin 30 should be linked to pin 24, 2051 port 3.3. Note the extra jumper in the above picture is for another interfacing project.
Photo showing the walking message display being driven by a 2051 micro-controller. Note I chose to mount the walking message display board upside down compared to the original Silicon Chip article. The reason for this is that it simplified some of the coding.
Source code for walking message display written by Peter Averill
;Walking message display for 2051
;Written by Peter Averill
;version 2 Fix up 'S' display problems
;31-5-99
;
$mod2051
CR EQU 0dh ; carriage return
LF EQU 0ah ; line feed
BAUD_9600 EQU 0fdh ; 9600 baud
;eeprom equates
FADDR EQU 0a0h ; fixed address for AT24Cxx EEPROMs
PADDR EQU 0 ; programmable address (0..7)
; Register definitions for serial eeprom
zdata EQU r1 ; data register
addr_lo EQU r2 ; 2-byte address register
addr_hi EQU r3 ;
;register definitions for hex to dec routine
memptr equ r0 ;ram memory pointer
col equ r4 ;column increment
scans equ r5 ;number of time the diplay is multiplexed
;before incrementing
count equ r6 ;col count for each char displayed
char_count equ r7 ;
;
; Microcontroller connections to AT24Cxx serial bus lines.
SCL BIT p3.5 ; serial clock
SDA BIT p3.7 ; serial data
;
clear bit p3.4 ;master clear
clk bit p3.2 ;clock
row bit p3.3 ;row of display on
DSEG AT 20H
delay_value: ds 1
message: ds 48 ;max lenght of string to display
ORG 5fH ; stack origin
stack: DS 20H ; stack depth
CSEG
ORG 0000H ; power on/reset vector
jmp cold_start
ORG 0003H ; external interrupt 0 vector
reti ; undefined
ORG 000BH ; timer 0 overflow vector
reti
ORG 0013H ; external interrupt 1 vector
reti ; undefined
ORG 001BH ; timer 1 overflow vector
reti ; undefined
ORG 0023H ; serial I/O interrupt vector
reti
ORG 40H ; begin constant data space
menu: DB CR,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF,LF
db LF,LF,LF,LF,LF,LF,LF,LF,LF,LF
db 'Walking led message display program',LF,CR
db '___________________________________',LF,CR
db 'Written by Peter Averill',LF,LF,LF,CR
db 'Press:-',LF,CR
db ' s to load the message from the PC terminated in a $',cr,lf
db ' d to display message',CR,LF,LF,LF,0
matrix: db 00h,00h,00h,00h,00h ;space
db 00h,00h,7dh,00h,00h ;!
db 00h,60h,00h,60h,00h ;"
db 14h,7fh,14h,7fh,14h ;#
db 32h,49h,7fh,49h,26h ;$
db 62h,64h,08h,13h,23h ;%
db 36h,49h,35h,02h,05h ;&
db 00h,00h,00h,50h,60h ;'
db 1ch,22h,41h,00h,00h ;(
db 00h,00h,41h,22h,1ch
db 2ah,1ch,3eh,1ch,2ah ;*
db 08h,08h,3eh,08h,08h ;+
db 00h,01h,02h,00h,00h ;,
db 08h,08h,08h,08h,08h ;-
db 00h,00h,01h,00h,00h ;.
db 02h,04h,08h,10h,20h ;/
db 3eh,45h,49h,51h,3eh ;0
db 00h,21h,7fh,01h,00h ;1
db 27h,49h,49h,49h,31h ;2
db 22h,49h,49h,49h,36h ;3
db 0ch,14h,24h,7fh,04h ;4
db 7ah,49h,49h,49h,46h ;5
db 3eh,49h,49h,49h,26h ;6
db 41h,42h,44h,48h,70h ;7
db 36h,49h,49h,49h,36h ;8
db 32h,49h,49h,49h,3eh ;9
db 00h,00h,22h,00h,00h ;:
db 00h,01h,22h,00h,00h ;;
db 08h,14h,22h,41h,00h ;<
db 14h,14h,14h,14h,14h ;=
db 00h,41h,22h,14h,08h ;>
db 20h,40h,45h,48h,30h ;?
db 3eh,41h,4dh,4dh,39h ;@
db 1fh,24h,44h,24h,1fh ;A
db 7fh,49h,49h,49h,36h ;B
db 3eh,41h,41h,41h,22h ;C
db 7fh,41h,41h,22h,1ch ;D
db 7fh,49h,49h,49h,41h ;E
db 7fh,48h,48h,48h,40h ;F
db 3eh,41h,41h,45h,26h ;G
db 7fh,08h,08h,08h,7fh ;H
db 00h,41h,7fh,41h,00h ;I
db 42h,41h,41h,7eh,40h ;J
db 7fh,08h,14h,22h,41h ;K
db 7fh,01h,01h,01h,01h ;L
db 7fh,20h,18h,20h,7fh ;M
db 7fh,10h,08h,04h,7fh ;N
db 3eh,41h,41h,41h,3eh ;O
db 7fh,48h,48h,48h,30h ;P
db 3ch,42h,46h,42h,3dh ;Q
db 7fh,48h,4ch,4ah,31h ;R
matrix1: db 32h,49h,49h,49h,26h ;S
db 40h,40h,7fh,40h,40h ;T
db 7eh,01h,01h,01h,7eh ;U
db 78h,06h,01h,06h,78h ;V
db 7fh,02h,0ch,02h,7fh ;W
db 63h,14h,08h,14h,63h ;X
db 60h,10h,0fh,10h,60h ;Y
db 43h,45h,49h,51h,61h ;Z
USING 0 ; register bank zero
cold_start:
mov sp, #(stack-1) ; initialize stack pointer
call initialize ; initialize controller registers
mov p1, #0 ; write zeros to displays
clr clear ;clear display
clr clk
clr row
setb TI
setb ES
mov acc,#07fh
call delay_5mS
top: jnb ri,m1
clr es
mov a,sbuf
clr ri
call setup
setb es
m1: call get_mess ;loads message from eeprom into ram
setb clear
m5: mov char_count,#0
m3: mov col,#6
m4: mov scans,#10
m2: mov memptr,#message
mov a,memptr
add a,char_count
mov memptr,a
call char_cal
call scan_char1
inc memptr
call char_cal
mov count,#5
call scan_char
inc memptr
call char_cal
mov count,#5
call scan_char
inc memptr
mov a,@memptr
cjne a,#'$',m6
jmp m5
m6: call char_cal
mov count,#3
cjne col,#4,m7
m7: jnc m8
call scan_char
m8: djnz scans,m2
djnz col,m4
inc char_count
jmp m3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
char_cal:
mov a,@memptr
clr c
subb a,#20h
mov b,#5
mul ab
mov b,a
mov c,ov
jc greater255
mov dptr,#matrix
jmp cc1
greater255: mov dptr,#matrix1
inc dptr
cc1: ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
scan_char1:
mov a,#6
clr c
subb a,col
sd7: jz sd6
inc dptr ;inc dptr to start column
dec a
jmp sd7
sd6:
mov a,col
mov count,a ;load the number of columns to display
dec count
mov a,count
jz sd3 ;display space column only
mov a,b
movc a, @a+dptr ; get character
sd3: mov p1,a
setb row
setb clk
nop
clr clk
clr row
inc dptr
mov a,#60h
call delay
mov a,count
jz sd2
sd1: djnz count,sd4
jmp sd5 ;last column jmp to display space
sd4: mov a,b
movc a, @a+dptr
mov p1,a
setb clk
nop
clr clk
mov a,#60h
call delay
inc dptr
jmp sd1 ;jmp to check if last column
sd5: call char_space
sd2: ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
char_space: clr a
mov p1,a
setb clk
nop
clr clk
mov a,#60h
call delay
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
scan_char:
sc1: mov a,b
movc a, @a+dptr
mov p1,a
setb clk
nop
clr clk
mov a,#60h
call delay
inc dptr
djnz count,sc1
call char_space
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
setup:
su1: mov dptr, #menu
call send_string
call getch
call send_char
su2: cjne a,#'s',su3
call store
su3: cjne a,#'d',su1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
store:
mov a,#0ah
call send_char
mov a,#0dh
call send_char
clr a
mov ADDR_LO,a
get_next_char: call getch
mov zdata,a
call send_char
clr a
call write_byte
inc ADDR_LO
mov a,zdata
cjne a,#024h,get_next_char
mov a,#0ah
call send_char
mov a,#0dh
call send_char
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
get_mess:
mov memptr,#message
clr a
mov ADDR_LO,a
next_char: clr a
call read_random
mov @memptr,a
inc ADDR_LO
inc memptr
cjne a,#024h,next_char
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
getch:
setb es ;enable reception
jnb ri,$ ;wait for key press
clr es
mov a,sbuf
clr ri
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
initialize:
; Initialize controller registers.
mov PCON, #0 ; initialize power control register
mov IE, #0 ; deactivate all interrupts
mov SCON, #01000000b ; serial port mode one
mov TMOD, #00100001b ; timer one 8-bit auto-reload,
; timer zero 16-bit
mov TH1, #BAUD_9600 ; timer one reload value
mov TCON, #01010000b ; start timer one & zero
mov th0,#0b9h
mov tl0,#0afh
setb et0
setb REN ;enable rx int
setb EA ;global int enable
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
send_string:
; Transmit string pointed to by DPTR.
; String may be of any length, but must be null-terminated.
push acc
push dpl
push dph
ss1:
clr a
movc a, @a+dptr ; get character
jz ss2 ; check for terminator
call send_char ; send character
inc dptr ; point to next character
jmp ss1
ss2:
pop dph
pop dpl
pop acc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
send_char:
; Wait for transmitter to clear, add even parity bit to character
; in accumulator and transmit it. Does not wait for transmitter
; to clear before returning.
jnb TI, $ ; wait here for transmitter to clear
clr TI ; clear transmit flag
push acc ; save char
mov SBUF, a ; load character into transmitter
pop acc ; restore char
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
delay:
push acc
push acc
djnz acc, $ ; 500 uS @ 12 MHz
pop acc
djnz acc, $
pop acc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
delay_5mS:
; Delay for 5mS times the value in the accumulator.
push acc
push b
mov b, a
ddd:
mov a, #0
call delay ; 1mS
call delay ; 2mS
call delay ; 3mS
call delay ; 4mS
call delay ; 5mS
djnz b, ddd
pop b
pop acc
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
write_byte:
; AT24Cxx Byte Write function.
; Called with programmable address in A, byte address in
; register pair ADDR_HI:ADDR_LO, data in register XDATA.
; Does not wait for write cycle to complete.
; Returns CY set to indicate that the bus is not available
; or that the addressed device failed to acknowledge.
; Destroys A.
call start
jc x49 ; abort if bus not available
rl a ; programmable address to bits 3:1
orl a, #FADDR ; add fixed address
clr acc.0 ; specify write operation
call shout ; send device address
jc x48 ; abort if no acknowledge
mov a, addr_lo ; send low byte of address
call shout ;
jc x48 ; abort if no acknowledge
mov a, zdata ; get data
call shout ; send data
jc x48 ; abort if no acknowledge
clr c ; clear error flag
x48:
call stop
x49:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
read_current:
; AT24Cxx Current Address Read function.
; Called with programmable address in A. Returns data in A.
; Returns CY set to indicate that the bus is not available
; or that the addressed device failed to acknowledge.
call start
jc x45 ; abort if bus not available
rl a ; programmable address to bits 3:1
orl a, #FADDR ; add fixed address
setb acc.0 ; specify read operation
call shout ; send device address
jc x44 ; abort if no acknowledge
call shin ; receive data byte
call NAK ; do not acknowledge byte
clr c ; clear error flag
x44:
call stop
x45:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
read_random:
; AT24Cxx Random Read function.
; Called with programmable address in A, byte address in
; register pair ADDR_HI:ADDR_LO. Returns data in A.
; Returns CY set to indicate that the bus is not available
; or that the addressed device failed to acknowledge.
push b
mov b, a ; save copy of programmable address
; Send dummy write command to set internal address.
call start
jc x47 ; abort if bus not available
rl a ; programmable address to bits 3:1
orl a, #FADDR ; add fixed address
clr acc.0 ; specify write operation
call shout ; send device address
jc x46 ; abort if no acknowledge
mov a, addr_lo ; send low byte of address
call shout ;
jc x46 ; abort if no acknowledge
; Call Current Address Read function.
mov a, b ; get programmable address
call read_current
jmp x47 ; exit
x46:
call stop
x47:
pop b
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start:
; Send START, defined as high-to-low SDA with SCL high.
; Return with SCL, SDA low.
; Returns CY set if bus is not available.
setb SDA
setb SCL
; Verify bus available.
jnb SDA, x40 ; jump if not high
jnb SCL, x40 ; jump if not high
nop ; enforce setup delay and cycle delay
clr SDA
nop ; enforce hold delay
nop ;
nop ;
nop ;
nop ;
clr SCL
clr c ; clear error flag
jmp x41
x40:
setb c ; set error flag
x41:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
stop:
; Send STOP, defined as low-to-high SDA with SCL high.
; SCL expected low on entry. Return with SCL, SDA high.
clr SDA
nop ; enforce SCL low and data setup
nop
setb SCL
nop ; enforce setup delay
nop ;
nop ;
nop ;
nop ;
setb SDA
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
shout:
; Shift out a byte to the AT24Cxx, most significant bit first.
; SCL, SDA expected low on entry. Return with SCL low.
; Called with data to send in A.
; Returns CY set to indicate failure by slave to acknowledge.
; Destroys A.
push b
mov b, #8 ; bit counter
x42:
rlc a ; move bit into CY
mov SDA, c ; output bit
nop ; enforce SCL low and data setup
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
clr SCL ; drop clock
djnz b, x42 ; next bit
setb SDA ; release SDA for ACK
nop ; enforce SCL low and tAA
nop ;
setb SCL ; raise ACK clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
mov c, SDA ; get ACK bit
clr SCL ; drop ACK clock
pop b
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
shin:
; Shift in a byte from the AT24Cxx, most significant bit first.
; SCL expected low on entry. Return with SCL low.
; Returns received data byte in A.
setb SDA ; make SDA an input
push b
mov b, #8 ; bit count
x43:
nop ; enforce SCL low and data setup
nop ;
nop ;
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
mov c, SDA ; input bit
rlc a ; move bit into byte
clr SCL ; drop clock
djnz b, x43 ; next bit
pop b
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ACK:
; Clock out an acknowledge bit (low).
; SCL expected low on entry. Return with SCL, SDA low.
clr SDA ; ACK bit
nop ; enforce SCL low and data setup
nop ;
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
clr SCL ; drop clock
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NAK:
; Clock out a negative acknowledge bit (high).
; SCL expected low on entry. Return with SCL low, SDA high.
setb SDA ; NAK bit
nop ; enforce SCL low and data setup
nop ;
setb SCL ; raise clock
nop ; enforce SCL high
nop ;
nop ;
nop ;
clr SCL ; drop clock
ret
END


