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,$ ;Receive bit 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