What is the general protocol to send information from one system to another? For example, let's say we have some information collected from microcontroller over a length of time that we want to send to another microcontroller. I've heard of SPI and I2C interfaces, but I am unclear when you use one method over another and how you implement it. Are there other methods besides SPI and I2C that are common? Is the implementation process similar for different microcontrollers? Is it basically parsing bytes of data that I am doing on the receiving microcontroller?

  • 4
    \$\begingroup\$ What is the concrete thing you want to do? \$\endgroup\$
    – starblue
    May 7, 2011 at 6:05
  • \$\begingroup\$ Just thinking of how to get different pieces of a system to pass data to each other in a small box, so distance can be assumed to be very short. The reason for having different pieces in a box is to simplify functions so that each piece has its own function (hopefully that makes sense..) \$\endgroup\$
    – O_O
    May 8, 2011 at 8:29
  • 2
    \$\begingroup\$ that is not what people normally call a system. Those are more what I would define as sub-systems. They form part of what you could consider a single system accomplishing a single set of tasks. It is semantics, but I think many of your answers are very broad because they do not have a perfect idea of what you are looking for from the question. \$\endgroup\$
    – Kortuk
    May 9, 2011 at 3:30
  • 1
    \$\begingroup\$ along the lines of what Kortuk said, it helps to define the problem. One important question to ask yourself is whether you might intend to replace individual subsystems with different implementations of the same function, or if this is a one-time as-is design. If you use a real bus, and expose implementation details of the subsystems to your cpu, then a subsystem change requires a s/w change for your controller, whereas if you use a communication interface, it doesn't matter how you implement a (replacement) subsystem, as long as it meets the same message protocol. \$\endgroup\$
    – JustJeff
    May 10, 2011 at 0:36
  • \$\begingroup\$ It is not simpler to split functionality across multiple devices for no other reason than separating tasks. Communications and synchronization are more complex than having two processes in the same micro. Now, if these processes have particularly incompatible latency profiles (one must update quickly while the other can take some time to complete a chunk), then there MAY be a valid reason to split them. Even then, the more common solution is to use interrupts or find a way to break the longer task down further. With what you've described I'm leaning towards thinking you should rethink this. \$\endgroup\$
    – darron
    May 10, 2011 at 14:25

7 Answers 7


SPI and I2C are kind of similar, in that they're really used more for attaching peripheral devices to a controller or cpu, than for actually transferring data between systems. USB is another interface that people seem to want to treat as a communication system, which is in fact a peripheral attachment bus.

Communication between systems isn't exactly like attaching a device to a bus. Bus attachment allows the processor to directly bang on registers in a device, whereas a communication interface allows you to send/receive streams of data. A device connected on a bus generally needs a device driver, whereas with communications, it really doesn't matter what is connected on the other end, as far as the host computer is concerned.

Of course, this is getting to be a hazier boundary all the time. Things like PCI and ISA are indisputably buses; I2C, SPI, USB are arguably buses; whereas RS232, RS485, and ethernet are definitely communications interfaces. But then there are things like CAN bus and 1553, which are definitely about moving data around, but in a very involved kind of way.

  • \$\begingroup\$ CANbus is very involved, and ethernet is not? CAN is very simple to get working for simple back and forth messaging. They are dedicated chips and most families support internal to their micro controllers. \$\endgroup\$
    – Kortuk
    May 9, 2011 at 3:18
  • \$\begingroup\$ @Kortuk - insofar as something like 232 has a sort of peer-to-peer symmetry, while 1553 or CAN impose a master/slave relationship, yes. I don't believe I said that ethernet is simple, just that it doesn't impose a bus controller/bus device distinction on the end points. \$\endgroup\$
    – JustJeff
    May 9, 2011 at 20:46
  • \$\begingroup\$ also, full disclosure - my opinion of CAN is entirely from tangential exposure; it has been an unused optional peripheral on several systems I've worked on, but after hundreds of passes through the documentation, you absorb a little about the unused options just by osmosis. So I'm labouring under the assumption that CAN is a controller/controlled-device type of architecture. \$\endgroup\$
    – JustJeff
    May 9, 2011 at 21:22
  • \$\begingroup\$ I think bus has different meanings in different contexts. From a schematic level, any interface with multiple signals can be considered a bus. As you move to higher levels with more abstraction, bus changes meanings. Slightly higher, bus usually means there are or can be multiple devices involved. RS485 multipoint is a definitely a bus, for instance. Much higher up, from a Linux device point of view, RS485 becomes a comm interface again and is demoted from being a bus... until you add your own protocol layer on top of it turning it back into a bus. At each level is has different meanings. \$\endgroup\$
    – darron
    May 10, 2011 at 14:37

There is no one way to send data, there are many different ways to communicate depending on the distance, the data rate, the environment, the application ...

The lowest layer is the physical layer, which actually moves the bits around.

  • SPI and I²C are for short distances inside a device, where there is not much noise that could disturb the transmission.

  • For not too fast communication over distances up to some tens of meters serial communication via RS-232 is a good choice.

  • If there is more noise or longer distance differential signals are used, for example in RS-485. For faster data transmission there is Ethernet, which is becoming more and more popular.

  • Then there are also various wireless standards.

On top of the physical layer there are more layers organizing how the data is sent, for detecting and correcting errors in transmission, routing in a network, and many other things. For example, the internet protocol is a rather complex stack of several layers, typically on top of the Ethernet protocol.


A simple serial UART can be used (one Tx and one Rx line with no discrete clock) and can be easily adapted to cross between different potentials (even primary and secondary circuits) with optoisolators or magnetic isolators.

As far as protocols go, anything with defined command bytes and some sort of checksum scheme will work well. There really isn't a cover-all standard protocol that suits all types of communications. I2C has a signalling standards (defining addressing, stops, starts, etc.) but the protocol of what's actually being communicated is solely up to the developer.

PMBus, for example, is a power supply communication protocol that uses I2C as its physical medium.


There really isn't a "general" protocol, what you end up using depends highly on the application. In order for us to give you a better answer, we need to understand your requirements a little better. You mention that you would like to have separate micro-controllers talking to each other as subsystems.

Some questions about this application:

  1. Will there be more than 2 micro-controllers in this project?
  2. What are your speed and throughput requirements? How fast does the information need get there and how often are you sending/receiving data?

If you answered NO to question 1:

If there are only 2 micrco-controllers in this project, you can definitely use UART between them. If they both need to initiate communication, use flow control, otherwise it should be trivial to send data in one direction. For the most part it should be "fast enough" given that you select one of the higher baud rates. I2C and SPI are typically only good for master/slave architecture.

If you answered YES (more than 2 controllers) to question 1:

  • If there are more than 2 micro-controllers in your project, which one initiates communications? Will it only be one master controller (ie master-slave architecture)? Or would any of the subsystems be able to speak at any time?
  • Is there a need for any of the subsystems to talk to each other? eg: for devices A, B and C: A can send to B and C, and B can send to both A and C, etc.

So now you need something more scalable where you can drop addressable devices onto a common bus. The answer to these follow up questions will help you decide between I2C and SPI (master-slave) or something like CAN (multi-master).

Your micro-controller most likely has a UART peripheral, the others (especially CAN) may only be available on more higher end chips. In either case, there should be plenty of documentation on how to use these peripherals to move bytes around.


As @Jon noted, one issue in selecting a communications interface is whether one entity will always be responsible for initiating communications, or whether more than one entity may be so responsible. A related matter is whether one entity will always be ready to receive unsolicited communications. SPI is frequently used in applications where one side will always be ready to receive communication. Something like a 74HC595 shift register, for example, is never "busy". While SPI is good for communication between a microcontroller and hardware which the micro is supposed to control, it is really not good for communication between two microcontrollers. When two processors with I2C hardware are using it to communicate, software can take as long as it wants (within very generous constraints) to deal with what's going on, without causing data loss. If a processor were to take a 100 microseconds to process each incoming byte, that would severely limit throughput, but the sender would slow down enough for the receiver to keep up. The only way that can generally happen with SPI is if one has a separate wire for handshaking.

I2C is really a wonderful protocol. The biggest limitations that stop it from being the most perfect protocol imaginable are

  1. Its speed is somewhat limited; SPI can go much faster, and even UARTs can sometimes go a little faster
  2. (2) While it's very convenient that I2C only needs two wires, both wires must be capable of bidirectional open-collector communication. This makes it difficult to send I2C via repeaters.

Personally, I'd like to see controller venders support a three-wire variant of SPI which included handshaking. I'm unaware of any controller that does so, though.

  • \$\begingroup\$ Funny you should mention this... I'm having to turn a SPI interface into a non-bidirectional I2C-like interface (the first byte is an address) to enable many more devices to participate on the bus than I have chip selects for. It works if your slave devices are all FPGAs. :) I too have wished there was something in between those two major synchronous standards. \$\endgroup\$
    – darron
    May 10, 2011 at 14:45
  • \$\begingroup\$ Oh, I guess I should clarify that the output enables on the slaves don't get asserted until it's address byte is received and they stay on until the single chip select is deasserted... so it's obviously slightly different than normal SPI + high level protocol. However, it's totally compatible with standard SPI from a master device point of view. (like a microprocessor) \$\endgroup\$
    – darron
    May 10, 2011 at 14:51
  • \$\begingroup\$ @darron: Cool. I wonder what would have to happen for the industry to start using an open-standard three-wire communications bus where wires are actively driven high and low? I guess there's a slight conflict between avoiding passive pull-ups and allowing any device to signal an interrupt, though that might be remedied by adding an interrupt pin which could be wired to the master or not at the slaves' convenience (my present implementation of the protocol only has one slave, so it can use the data return wire to asynchronously signal when it wants to be serviced). \$\endgroup\$
    – supercat
    May 10, 2011 at 15:03
  • \$\begingroup\$ @darron: To avoid having to use a chip-select pin, the master signals start-of-command by sending two rising edges on the data wire while the clock is low; slaves can indicate whether their last data byte was valid by outputting a status value when clock and data are both low (idle); otherwise they indicate that they want attention when clock is low and data is high. If I were designing master hardware for this protocol, I would add the ability to send 8 clocks pulses where the data wire mirrored clock, and in slave hardware include an asynchronous count of the number of rising edges during... \$\endgroup\$
    – supercat
    May 10, 2011 at 15:08
  • \$\begingroup\$ @darron: ...a data byte. If five or greater, the byte would be ignored (the slave would assume the master was interested in receiving a byte of data, but had nothing it actually wanted to say). That wouldn't be nearly as significant, though, as having the slave report the last-byte status when clock was low (which would, if the slave device was a processor, allow the master to know that the slave hadn't been ready and had missed the last 'transaction opportunity'. \$\endgroup\$
    – supercat
    May 10, 2011 at 15:10

In no particular order, the most popular physical-layer instances for 2 CPUs in the same box seem to be:

  • daisy-chain SPI (such as used by JTAG)
  • select-wire-per-slave SPI
  • "TTL-level RS-232" aka "asynchronous start-stop serial communication"(directly connecting the UART TX pin of one CPU to the UART RX pin of another CPU)
  • I2C
  • 8-bit data + strobe (such as the IEEE 1284 printer port parallel port)
  • shared-memory (only one CPU drives the address/data/control bus at a time)

These physical layer instances (as well as other physical-layer instances for 2 CPUs in separate boxes) typically provide a stream of bytes to the software that implements the higher levels of the communication system.

Smart programmers write the software in such a way that when the hardware guy decides to tear out one physical-layer instance and replace it with a completely different physical-layer instance, they only need to rewrite a few functions to feed their output stream of bytes to the hardware and read back a stream of bytes from the hardware, and all the higher-level protocol stuff continues to work unchanged.

The protocol to send information from one CPU to another CPU almost always involves interpreting the stream of bytes as a series of packets:

  1. preamble
  2. header
  3. (possibly escaped) serialized data
  4. trailer

Some people seem to enjoy making up entirely new, custom, incompatible protocols by mixing-and-matching (2) one of many kinds of header structure with (3a) one of many kinds of serializing data with (3b) one of many kinds of escaping that serialized data with (4) one of many kinds of trailer.

Some of the simplest protocols for encapsulating data into a packet include:

Slightly more complicated protocols for encapsulating data into a packet include:

There is a long list of protocols at

You may enjoy reading "Protocol Design Folklore" by Radia Perlman which describes how protocol design can go wrong.


No single 'general' protocol. Choice can (for instance) depend on:

  • distance
  • required throughput
  • availability of special peripherals
  • noise level
  • need for optical isolation
  • criticality (tolerable failure rate)
  • avialable CPU power at both ends
  • available I/O pins at both ends

In a lot of cases you must disitinguish the physical layer (signal levels) from the data link layer (+/- the way data is encoded)(check OSI model, lower 2 ..4 layers). Possible phyiscal layers are for instance:

  • simple 5V or 3.3V or even 1.8V TTL
  • any of the above but open-collector instead of push-pull
  • balanced lov voltage signaling (often used with FPGA's)
  • balanced higer volatge (RS485, RS432)
  • single ended higher voltage (RS232)
  • balanced trafo-coupled (various ethernet versions, PDIF audio)
  • optical (optical ethernet, toslink)

You can use one line to carry data and clock info, or split this into multiple lines. The latter used to be popular, but nowadays most new / fast protocols tend to use one line (or a pair of lines acting as one).

Ther are alot of ways to encode data and clock on a line. RS232 traditionally uses NRZ, there is Machester encoding, adn the various format uses on harddisks with curious names line 2.7 RLL.

To sum it up: there are a gazillion ways to do communication between systeems. And I haven't even mentioned connectors or higher-level aspects like error detection and recovery, data encoding, compression, and encryption...


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.