درايور نويسنده پيام با ۸۹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