# Is this machine code insufficient to chip timing?

I'm having trouble performing basic communication between two IC's. and AT89S52 and an AT89C4051. Both are connected using 6 GPIO pins of which 4 of them on each microcontroller are high nibbles of port pins. I also share the same 4 nibble pins on the AT89S52 with an HM628128 RAM IC.

The PCB trace length from pin to pin is less than 30mm. (I try to keep them as short as possible). and the clearance and trace width are 11 mils each, so I don't think that could cause the problem.

I did however look at an answer to one other question I posted here (Maximum reliable speed of GPIO pin given only capacitance and no resistance), and someone mentioned that by connecting parts to the GPIO line, the capacitance increases and that can increase the time required to make the input value of a GPIO line at a stable state which is why I deliberately sprinkled in a few NOPS into my code in hopes that I satisfied the timing requirements, but perhaps I didn't?

Initially I was going to post this on stackoverflow.com but for some reason I feel the problem has to do with poor timing with the hardware rather than software bugs. I did document it so everyone knows exactly what I'm trying to achieve. As you can see in code, I tried using synchronization but when it comes to receiving data, my code on the client stalls.

Each microcontroller uses the same clock speed of 22.1184Mhz with 33pF pull-down ceramic capacitors attached to it.

This is my code:

  ; ****************************************************
; Client: AT89S52
; ****************************************************

setmyID:
;send SETIDL command, #6, SETIDH, and #1 in that order to adapter
mov A,#61h
mov R5,A
mov R6,#SETIDL
swap A
lcall cmd
mov R6,#SETIDH
mov A,R5
lcall cmd
ret

cmd:
;reset triggers
setb CLK
setb RESULT

;only feed high nibble to adapter
anl A,#0F0h
mov R7,A
nop ;trying to sync with adapter but failed?

;set high nibble of port to my command and leave low nibble alone
mov A,D
anl A,#0Fh
orl A,R6
mov D,A

clr CLK ;lower clock line to tell adapter we have data
nop
jb RESULT,$;wait till adapter acknowledges it nop ;set high nibble of port to my data and leave low nibble alone mov A,D anl A,#0Fh orl A,R7 mov D,A setb CLK ;raise clock line to tell adapter we have data nop jnb RESULT,$ ;wait till adapter acknowledges it

;Make high nibble of port value high so it accepts input
nop
mov A,D
orl A,#0F0h
mov D,A

nop
jb CLK,$;wait until adapter sends data ;grab the data (to accumulator) nop mov A,D anl A,#0F0h setb RESULT ;tell adapter we got the data nop jnb CLK,$ ;wait until adapter acknowledges this

;PROBLEM: code never reaches here :(
ret

; ****************************************************
; ****************************************************

;endless main loop in adapter. Ports are all setup to accept data at this point

main:

;set lines high to accept input from client
setb RESULT
setb CLK

jb RESULT,noout

;Load result (LASTR) onto the data line. LASTR only has data in high nibble.
nop
mov A,D
anl A,#0Fh
orl A,LASTR
mov D,A

clr CLK ;let client know we sent data

nop
jnb RESULT,$;wait until client is ready to continue ;Allow incoming data into high nibble nop mov A,D orl A,#0F0h mov D,A ;and we're done ajmp main noout: jb CLK,main ;here, client wants to send data to us CLK is now low. ;First incoming nibble is command number nop mov A,D anl A,#0F0h mov R4,A clr RESULT ;tell client we got the command nop jnb CLK,$ ;wait until client sends data
nop
mov A,D
anl A,#0F0h
; function processing here (works) then restart loop
ajmp main


UPDATE

Correct me if my theory is wrong, but I was thinking my only two options are to either lower the crystal speed and/or use external pull-up resistors on the shared GPIO lines.

I'm thinking if I use external resistors, things might work because then the waiting time to turn the output of a pin into a stable state is low. For example, if I use 4.7K pull-up for every pin and each pin on each device has about a 10pF capacitance, then worst case scenario (seeing that resistors are then in parallel):

 4700 * 0.000000000030 = 0.141uS


But without the pull-up, I'd have to factor the resistance of each device and calculate the three in parallel. I'm gonna say 20K best case. so:

 20000 * 0.000000000030 = 0.6uS


With a 22.1184Mhz clock, its about 0.53uS per instruction execution which is under 0.6uS. This is why I was thinking of including pull-ups.

I'd rather not lower the clock speed but if its my only option then I will.

Am I right with my theories or is there another solution?

• I already mentioned this to you in an earlier Q of yours: the same clock speed does NOT mean they are the exact same clock. They can drift relative to each other. And different processors may even have slightly different setup and hold times relative to the clock phases, besides. You need to account for this in ANY robust communications scheme. (I even wrote a white paper on this about 15 years ago.) – jonk Oct 23 '17 at 18:47
• Only reliable way to do a communication bus with GPIO is with interruptions (i.e. detecting rising edge), as jonk said you cannot count on the process clock speeds to be the same. – lucas92 Oct 23 '17 at 19:06
• @jonk Thats why I made my code in both the adapter and client as shown so it waits until the other micro has finished. In the past I didn't give the other micro a chance to send out an acknowledgement. – user152879 Oct 23 '17 at 20:06
• @Mike Are you using a master-slave clocking arrangement? Or is this a peer-relationship between devices where either may acquire a master position? – jonk Oct 23 '17 at 20:20
• The at89S52 (client) is the master initiating almost everything, and the at89c4051 (adapter) is the slave, however the adapter can do other work if the client doesn't make any request. – user152879 Oct 23 '17 at 20:25