Currently I have two microcontrollers setup in which entire ports are connected to each other (P1.1 connected to P1.1, P1.2 connected to P1.2, etc). I also have two pairs of extra GPIO pins connected as signal lines.
What I want to achieve is a way to send and receive a byte in as little time as possible.
Let's assume that the master requests the slave to add 1 to a number and the slave responds:
Here's my code so far for the slave microcontroller:
SLAVEDATA equ P1
SLAVEACK equ P2.0
SLAVECMD equ P2.1
jnb SLAVECMD,$ ;wait for command
mov SLAVEDATA,#0FFh ;tristate to allow input
nop ;wait how many uS?
mov A,SLAVEDATA ;see what number came in
inc A ;add 1
mov SLAVEDATA,A ;produce result
setb SLAVEACK ;send acknowledgement
jb SLAVECMD,$ ;wait till remote lowers comand line
clr SLAVEACK ;clear acknowledgement
;transaction complete
And here's the code for the master:
MASTERDATA equ P0 ;Master's P0 connects to slave's P1
MASTERACK equ P3.0 ;Master's P3.0 connects to slave's P2.0
MASTERCMD equ P3.1 ;Master's P3.1 connects to slave's P2.1
mov MASTERDATA,#20h ;Set number to 32
setb MASTERCMD ;tell slave to increment
jnb MASTERACK,$ ;wait until its done
mov MASTERDATA,#0FFh ;tristate port to allow input
nop ;delay by how many uS?
mov A,MASTERDATA ;Get result here
clr MASTERCMD ;tell slave were done
jb MASTERACK,$ ;wait until slave understands this
While I believe this code mostly works, I'm just not sure how long to make the program wait between the time the port pins are set to high and the time valid data is read on the pins.
If I don't wait at all, then I will get incorrect data. I believe it has to do with the FET's inside my AT89C4051 and AT89S52 that I am using but the manual does not indicate how long I should wait.
Both micros have the same crystals, capacitors and PCB track arrangements for the crystals and capacitors.
Each capacitor is 33pF ceramic
Each crystal is 22.1184Mhz which came out of the same package
Each PCB track in which the leads of the crystal are connected to is 1.9mm wide.
How do I calculate the minimum number of NOPs in my code so that valid data can be captured on the port pin after tristating it?
Also, because each micro has the same clock driving circuitry, could I replace the stalls (waiting for acknowledgements for example) with three nops? or will I still experience a minor clock drift?
Best Answer
In general, you shouldn't be using timed waits at all. Rather, you should be using a handshake that guarantees that the events on the databus occur in the required order.
Those events are:
Unfortunately, only two additional signals is not enough to manage this process for a bidirectional bus. You'll need at least one other signal connected between the two processors. There are a number of ways you could use such a signal. One of the simplest is to treat it as a read/write signal, controlled by the master CPU.
The transaction would then go something like this.
CMD
signal.CMD
asserted, reads the read/write signal, and then reads data bus and then assertsACK
.ACK
asserted, tristates the data bus, then negatesCMD
.CMD
negated, and negatesACK
.Note that if the slave is busy with something else when the master starts the transaction, it simply delays asserting ACK in step 2. The master waits as long as necessary.
To transfer the result:
CMD
signal.CMD
asserted, reads the read/write signal. It then drives the result onto data bus and assertsACK
.ACK
asserted, reads the data bus, then negatesCMD
.CMD
negated, tristates the data bus and negatesACK
.Note that if the slave requires some time to compute its result, it simply delays asserting ACK in step 6, and the master will simply wait as long as needed.