I'm trying to do a direct two-way communication between two AT89C2051 microcontrollers with only two GPIO pins so that I have other GPIO lines free for other tasks.
P3.7 is the data wire, and P3.2 (INT0) is the control wire, and they are externally pulled high to VCC (of 5 volts) through 10K resistors.
One microcontroller has an 18.432Mhz crystal connected to it so I can connect it to my computer at a clean 9600bps baud. The other microcontroller is connected to a 20Mhz crystal (which is the highest speed lowest-priced compact crystal I ordered from the internet) for fast memory and wireless communication.
Initially I was going to reserve 4 GPIO pins for data communication but I wouldn't have any free for other tasks such as memory and LED manipulation.
This is my idea behind the two wires.
The sender loads P3.7 with the one bit and then sends P3.2 low then waits a bit for remote processing. This repeats until the whole byte is sent.
When the receiver receives data, the interrupt is supposed to be executed (from the remote sender making P3.2 low) and the byte received from P3.7 is stored in a temporary location until all bytes are received which a counter tracks. Once all are received, a flag is set.
The sending seems to be ok, but the receiving always stalls.
Do I need to adjust my timings or is there a better approach of doing half-duplex bi-directional communication with only two wires connected to the same pins (with pull-up resistors) on both micros?
Here is my code for reference. I have to remove the first line of code after programming the first chip to ensure the correct code is on each chip.
UNIT equ 1h ;1 = 8051 to interface to PC, 0 = 8051 to interface to radio. RDATS EQU 40h ;remote data temp RDAT EQU 42h RDATCT EQU 41h RDI EQU 0h ;remote-data-interrupt bit CT EQU 1h ;carry temp - receive CTS EQU 2h ;carry temp - send org 0h ljmp main ;INT 0 natural address is here (03h) ljmp intZ org 002Bh ;called intZ: clr EX0 ifdef UNIT clr P3.4 ;This is supposed to execute on 8051 connected to PC but does not. endif mov CT,C push ACC mov C,P3.7 mov A,RDATS RLC A mov RDATS,A inc RDATCT mov A,RDATCT cjne A,#8h,no8 setb RDI mov RDAT,RDATS mov RDATCT,#0h no8: jnb P3.2,$ pop ACC mov C,CT ifdef UNIT setb P3.4 endif setb EX0 reti sendrdat: clr EX0 mov CTS,C mov R7,#8h push ACC sendrmore: clr C rlc A mov P3.7,C clr P3.2 nop nop setb P3.2 djnz R7,sendrmore pop ACC mov C,CTS setb EX0 ret serialin: clr RI jnb RI,$ mov A,SBUF ret serialout: clr TI mov SBUF,A jnb TI,$ ret pserial: rewr: clr A movc A,@A+DPTR jz exl acall serialout inc DPTR ajmp rewr exl: ret main: mov RDAT,#0h mov RDATS,#0h mov RDATCT,#0h clr RDI mov P3,#0FFh mov P1,#0FFh mov SP,#50h ;skip most ram so SP doesnt be wrecked mov scon,#50h mov tmod,#020h mov 087h,#80h ;pcon.7 mov TH1,#0F6h ;9600 baud on 18.432Mhz setb EX0 setb EA setb TR1 IFDEF UNIT ajmp PCmode ELSE ajmp RADmode ENDIF ;branch PCmode: clr RI jnb RI,$ mov DPTR,#ptest1 acall pserial ;send 0AAh to remote 8051 mov A,#0AAh acall sendrdat mov DPTR,#ptest2 acall pserial ; code stalls here forever. ; It should only stall until remote 8051 calls this one. rwait: nop ;no overloading processor jnb RDI,rwait ;RDAT = remote byte received mov A,RDAT push ACC mov DPTR,#ptestr acall pserial pop ACC acall serialout mov A,#0Dh acall serialout mov A,#0Ah acall serialout mov DPTR,#ptestdone acall pserial sjmp $ RADmode: ;radio mode... only obey commands at this time nop jnb RDI,RADmode clr RDI mov A,RDAT cjne A,#0AAh,nosig ;AAh=get signature = 41h (A) mov A,#041h acall sendrdat nosig: ajmp RADmode sjmp $ ptest1: db 'Sending data to unit 2...',0Dh,0Ah,00h ptest2: db 'Receiving data from unit 2...',0Dh,0Ah,00h ptestr: db 'Received: ',00h ptestdone: db 'This is a test that worked!',0Dh,0Ah,00h END