I am currently using an AT89C4051 microcontroller with a 22.1184Mhz crystal attached to it.
The following code that someone else posted here is suitable for me if I don't mind synchronous transmitting operation:
Transmission works perfectly, but there is however one problem with it. Every time I send a character, I have to wait as long as it takes for the transmit flag to be set (96 clock cycles I think). The problem is these clock cycles are precious because at any point I could receive data. So at first I wanted to do code like this:
**note: in the code, cc stands for clock cycles, and trigger is clock input.
Now the above may work wonderfully if I didn't care if data reception speed is ultra slow, but I'd like to have 9600bps for both receive and send. So I tried this method:
The problem is the second method does not work. I tried to make all my functionality work within 96 clock cycles so that the serial operations work but with this last idea, all I was able to do was transmit one and only the first character until I resetted the microcontroller, and then after only the first character could be transmitted again.
Is there a good way to make this asynchronous? Now I did try the interrupt route in the past with bad luck.
The following code that someone else posted here is suitable for me if I don't mind synchronous transmitting operation:
Code:
mov scon,#50h
mov tmod,#21h
mov th1,#f4h
mov tl1,#f4h
setb tr1
mov a,#'A'
mov sbuf,a
jnb ti,$
clr ti
Transmission works perfectly, but there is however one problem with it. Every time I send a character, I have to wait as long as it takes for the transmit flag to be set (96 clock cycles I think). The problem is these clock cycles are precious because at any point I could receive data. So at first I wanted to do code like this:
**note: in the code, cc stands for clock cycles, and trigger is clock input.
Code:
;setup serial
mainloop:
jnb RI,recv
;act on received character and ditch invalid characters (uses 19 cc)
recv:
jb trigger,processdata
ajmp mainloop
processdata:
;shift out result and shift in new data while trigger is toggled (uses 54 cc)
;format incoming data to prepare byte to serial and set accumlator to serial data (uses 13 cc)
CLR TI
mov SBUF,A
jnb TI,$
ajmp mainloop
Now the above may work wonderfully if I didn't care if data reception speed is ultra slow, but I'd like to have 9600bps for both receive and send. So I tried this method:
Code:
;setup serial
setb TI ;serial port ready to transmit
mainloop:
jnb RI,recv
;act on received character and ditch invalid characters (uses 19 cc)
recv:
jb trigger,processdata
ajmp mainloop
processdata:
;shift out result and shift in new data while trigger is toggled (uses 54 cc)
;format incoming data to prepare byte to serial and set accumlator to serial data (uses 13 cc)
jnb TI,$ ;only stall if data isn't received
CLR TI ;reset because last byte was received
mov SBUF,A ;send new data
ajmp mainloop
The problem is the second method does not work. I tried to make all my functionality work within 96 clock cycles so that the serial operations work but with this last idea, all I was able to do was transmit one and only the first character until I resetted the microcontroller, and then after only the first character could be transmitted again.
Is there a good way to make this asynchronous? Now I did try the interrupt route in the past with bad luck.