I'm trying to figure out the best approach to transfer high-speed data one way between two microcontrollers (with their own crystals of the same speed) of the same variety (between AT89C4051 and AT89S52) from an electrical standpoint.
I have them wired up as follows:
AT89S52 P0 is connected to AT89C4051 P1
AT89S52 P1.1 is connected to AT89C4051 P3.7
The AT89C4051 has 6 bytes of data that the AT89S52 needs, and the AT89S52 always initiates the download.
My options are as follows:
** OPTION 1. Transfer byte-wide. **
Code in AT89C4051 (transmitter) will be this:
mov R1,#DATALOCATION
jb P3.7,$ ;Wait for falling edge
mov P1,@R1 ;send out byte
inc R1 ;Increment pointer
jnb P3.7,$ ;Wait for rising edge
mov P1,@R1
inc R1
;and this code (minus first line) repeats twice for remaining bytes
And the AT89S52 will have this code:
mov R0,#DATASPACE
mov P0,#0FFh ;Make ports accept data
clr P1.1 ;lower line to get first byte
mov @R0,P1 ;Load next byte in
inc R0 ;increment pointer
nop ;waste cycles to let AT89C4051
nop ;be ready for next byte. Is this wait time enough under worst
;case scenarios???
setb P1.1 ;raise line to get next byte
mov @R0,P1 ;Load next byte in
inc R0 ;increment pointer
nop ;waste cycles to let AT89C4051
nop ;be ready for next byte
;and this code (minus first line) repeats twice for remaining bytes
That is my 8-bit approach which seems fast, but I didn't have enough pins free to use one for an acknowledgement pin as the rest are used.
** OPTION 2. Transfer nibble-wide **
Code in AT89C4051 (transmitter) will be this:
mov R1,#DATALOCATION ;pointer = start of data
jb P3.7,$ ;Wait for falling edge (but this means stalls which I don't like)
mov A,@R1 ;get byte
orl A,#0F0h ;and accept lower nibble.
clr ACC.7 ;Make P1.7 our ack bit (ack=0)
mov P1,A ;return data in lower nibble with P1.7=0 as ack
jnb P3.7,$ ;Wait for rising edge
mov A,@R1 ;get byte
orl A,#0Fh ;and accept high nibble. (ack=1)
swap A ;and put it in our low nibble slot
mov P1,A ;return data in lower nibble with P1.7=1 as ack
inc R1
;and this code (minus first line) repeats 5x for remaining bytes
Code in AT89S52 (receiver) will be like this:
mov R0,#DATALOCATION ;pointer = start of data
mov A,@R0 ;Load byte
orl A,#0F0h ;set our nibble and make rest of lines high to receive ack
mov P1,A ;and show it
clr P1.1 ;lower clock
jb P1.7,$ ;wait till remote is ready
mov A,@R0 ;Load byte again
orl A,#0Fh ;set our nibble and make rest of lines high to receive ack
swap A ;swap nibbles so we get right nibble
mov P1,A ;show data
setb P1.1 ;raise clock
jnb P1.7,$ ;wait till remote is ready
inc R0
;and this code (minus first line) repeats 5x for remaining bytes
which is best?
But the part that makes me concerned is timing and hardware.
The micros are connected no more than 10cm away from each other and all PCB traces are 12mils wide with 12mils clearance. When I run any microcontroller circuit, if my hand touches both leads of the crystal, then the speed of operation seems to vary (probably because human resistance affects crystal frequency?)
Given all environments the micros can be exposed to (except water), which of my two ideas is best to ensure I get data at the highest speed possible? and I only have 9 I/O lines to play with here.
So do I resort to the nibble method and wait for acknowledgements even if the response takes a while? or am I safe to use the byte method?
Remember, we have to assume worst-case scenarios. fingers touching crystal area (as a test), weak batteries, etc. because the last thing I want to happen is data loss.
For clarification, each crystal lead is connected to 33pF ceramic capacitors which are also grounded. (I'm using the standard microcontroller crystal setup). and my ground planes are large.
UPDATE
As requested, I included the important connections. Both crystals are 22.1184Mhz. The capacitor and resistor connected to the reset pin is 47nF and 100K. All other capacitors are 33pF.
I also included a basic timing diagram. I had to use paint to draw the lines in because I have no program on my computer to do professional diagrams.