# Sending data from UART to microcontroller via AT89C2051 functioning as a UART/SPI bridge

I have an unusual setup. I have an AT89S52 microcontroller in which its UART is used by the PC. I needed a way to make a second UART based device work with it, so what I decided to do was make a UART to SPI converter using an AT89C2051 due to its smaller size and smaller cost. Now I have some trouble sending data from the AT89S52 to the 2nd UART through the UART to SPI converter.

I have attached code for the converter. Ideally what my program should do is (upon a clock trigger), it will read in 5 bits (4 for data, 1 for status) one by one and as it reads a bit, it outputs another on another pin. Once the bits are read into the converter, I'd like the converter to add a sequence number to the byte to increase chances of data integrity.

For example, if I wanted to send these nibbles (in hex):

D A B E


Then I want the UART connected device to see the following sent:

D0 A1 B2 E3


When the UART sends data, I want the sequence number checked to see if its correct and as long as it is correct, the data will be in a temporary variable until it's ready to be read, and the output is then the expected nibble of data.

Someone please review this code to see if there is anything I can do to improve it. I'm specifically interested in receiving all data as it comes in without losing data. and I'm also interested in being able to send all the data.

All microcontrollers are running at the same clock speed, and I only have 4 I/O lines I can work with. Because of the nature of the microcontrollers, I can force a logic low to any output because a logic high is actually high impedance, so if forcing a low on an output will make my job easier in this situation, then I'd like to know.

  ;DATA FORMAT to/from UART:
;max 8 bit chain -> nnnncccc. nnnn=data nibble. cccc=decrementing sequence #

;Data format to/from SPI master:
;5 bit chain -> nnnnc, nnnn=data nibble, c=special.
;For transmit, C=1=reset counter. For receive, C=0=Data received

DOUT equ P1.6 ;dat out
DIN equ P1.5 ;dat in to me
HASDAT equ P3.4 ;has data
CLK equ P3.5
HASDATI bit 0h
SEQTX equ 23h
SEQRX equ 22h

start:
;setup everything
mov P1,#0FFh
mov P3,#0FFh
setb HASDATI ;HASDATI: internal variable. 1=no data from serial
mov SP,#50h
mov PSW,#18h
mov PCON,#80h
mov SCON,#52h
mov TMOD,#22h
mov TH1,#0E8h ;4.8kbps serial speed
mov TL1,TH1
setb TR1 ;start serial
jb CLK,$;fix clock. wait for clock=LOW to start main: jb CLK,datio ;activate SPI when clock=HIGH continue: jbc RI,recvok ;assume data at serial sjmp main recvok: jnb HASDATI,main ;only enter serial port processing once until data is read mov B,SBUF ;Get data as B mov A,B ;copy it anl A,#0Fh ;get sequence # cjne A,SEQRX,noseq ;and if it matches... inc SEQRX ;use next sequence # anl SEQRX,#0Fh ;and make it 0 if its 16 clr HASDAT ;let callers know new data is in clr HASDATI sjmp main noseq: ;Sequence doesn't match so start over mov SEQRX,#0h setb HASDAT setb HASDATI sjmp main datio: mov R5,#0h ;clear output buffer mov R3,#5h ;We exchange 5 bits mov A,B ;load recently received data mov C,HASDATI ;and data reception indicator mov ACC.3,C ;attach indicator to data mov R4,A ;R4=data to output rrr: ;shift out bit mov A,R4 RLC A mov DOUT,C mov R4,A ;wait until remote lowers clock line jb CLK,$
mov A,R5
mov C,DIN
RRC A
mov R5,A
djnz R3,rrr
;Check MSB of lower nibble received
;and if its 1, set it to 0 and reset transmit counter
jnb ACC.3,noresc
mov SEQTX,#0h
clr ACC.3
noresc:
;lower nibble=transmit count, high nibble=data
orl A,SEQTX
CLR TI     ;reset transmit to UART flag
mov SBUF,A ;and send byte
inc SEQTX       ;use next sequence number
anl SEQTX,#0Fh  ;and if its 16, make it 0
setb HASDATI          ;reset data indicator since we got the data
setb HASDAT
mov B,#0h       ;reset new data value so if we read too fast, we get nothing
jnb TI,\$        ;stall until serial port finally read the byte
ajmp continue