I'm trying to figure out the best way to integrate all devices flawlessly on the 8051 based microcontrollers. If each device was the same low speed, then I could multiplex each and every one of them within the timer routine by itself and forget about the serial interrupt, but one device needs to run about 10x faster. But I found a bottleneck...


Surely the optimal way is to have an interrupt for the serial routine and one for the timer so everything supposedly executes cleanly. I drafted rough code below:

Org (Timer)
(insert software uart routines here)

Org (Serial Interrupt vector)
push PSW
jbc RI,gotabyte
jbc TI,sentabyte
pop PSW

ajmp exitserial

  inc R1
  cjne R1,#ENDOFBUF,notend
    ajmp exitserial
  mov SBUF,@R1
ajmp exitserial

But there's a major problem. It seems that I can either receive and send data correctly on the higher speed device while having all the lower-speed devices out of sync (just because the serial interrupt has priority and delays execution of the timer handling the remaining UARTs by the time it takes to finish its interrupt), or I can have all low-speed devices work correctly while the high-speed device is out of sync (just because of the opposite situation... timer runs right at a bad time while the serial routine attempts to send or receive data). Trust me, I even ran a timer and have the TI and RI flags checked at a much higher speed than that of the UART and that even returned inaccurate data.

So I thought of an idea

Based on my past circuit boards and the hardware available to me, I'm thinking of offloading most of the serial routines to another 8051 based microcontroller (AT89C2051) since much of the serial data coming into the main system is almost immediately discarded after processing (such as checksum).

Question is, how do I best do data transfer between the two microcontrollers?

As It stands, I can make extra uarts and have all run at a slow speed on the main microcontroller, but I'm trying to think of a way to send the data back and forth reliably over three wires without introducing serious lags on either side to the point where data on any device is out of sync.

One may suggest SPI but that involves having one microcontroller stall until the clock line is set. Making it a UART line won't work because the smaller microcontroller that's connected to the high-speed radio might lose characters because the serial routine will constantly interrupt data flow.

If my idea of using two micros is best for my situation, then can someone point me to a good asynchronous data protocol I can go for using only three wires?

For clarity in my diagram, S1 through S4 are individual sensors, and RIN and ROUT are connections to the radio module. DIN, DOUT and DCLK are Data In, Data Out, and Clock, but those names could be changed later.

Both micros are run by independent 22.1184Mhz crystals with 33pF ceramic capacitors connected between each crystal pin and ground.


  • \$\begingroup\$ I've a method I've used on several occasions for fast data transfer between multiple (dozens) of MCUs with independent asynchronous clocking (they are each separate boards that normally operate alone) where all MCUs can equally acquire and master a 2-wire async-serial bus for burst transfers. But I'm not convinced you could produce working code for the concept. Nor am I sure from your writing that it's appropriate. (It's not unlike how the APIC bus works on Intel chips.) \$\endgroup\$ – jonk Jun 20 '18 at 1:34
  • \$\begingroup\$ If you're consisting a second micro, how about an external SPI connected multiple UART IC to handle all of the serial streams? \$\endgroup\$ – brhans Jun 20 '18 at 14:57
  • \$\begingroup\$ I already made my major PCB so that's out. The only modifications I can do are that to the high-speed stream only. \$\endgroup\$ – Mike -- No longer here Jun 20 '18 at 15:36

I would say, either:

  1. Do this with polling, and just check the fast device 10 times as often as you check the other devices. Or..

  2. Do everything with interrupts, but make sure they're extremely fast. Like just copy the new byte to a buffer and exit, process the data later. In this way you may be able to receive from many serial streams at the same time. This is more resource efficient, but you could create a situation where the serial coms experience occasional glitches if all devices are receiving a message at exactly the same time.

| improve this answer | |
  • \$\begingroup\$ I gotta watch #1 because if I scan too fast, then the instruction processing time might be too large to the point where the only thing executed in the system are just interrupts and never the mainline program. As for #2, I did explain the problems with using multiple interrupts. After All, the 8051 allows me to choose which interrupt has priority over which and if I don't make a selection then the timer interrupt has priority. \$\endgroup\$ – Mike -- No longer here Jun 20 '18 at 0:24
  • \$\begingroup\$ The important part of #2 is fast. For #1, you would just have to try it, but the polling should be pretty much as fast as checking a single flag for each serial port so that should not be the case. \$\endgroup\$ – Drew Jun 20 '18 at 3:11

because the serial interrupt has priority and delays execution of the timer handling the remaining UARTs by the time it takes to finish its interrupt

You missed the IP register in the 8051, which allows to set the timer to high and the serial port to low priority. Now your timer can preempt the serial port interrupt.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.