1
\$\begingroup\$

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
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.