I2c Vs Uart Performance

Tradeoffs when considering SPI or I2C? Ask Question. Command (along with a read/write bit). This, along with some other overhead, requires more bits to be sent over an I2C bus vs SPI for the same functionality. EEPROM is 272 lines, again 1/2 comments probably, and that includes some high level management like default data, UART debug. Tradeoffs when considering SPI or I2C? Ask Question. Command (along with a read/write bit). This, along with some other overhead, requires more bits to be sent over an I2C bus vs SPI for the same functionality. EEPROM is 272 lines, again 1/2 comments probably, and that includes some high level management like default data, UART debug.

  1. I2c Vs Uart Performance Tool
  2. I2c Vs Uart Performance Tool
  3. I2c Vs Uart Performance Test
$begingroup$

What tradeoffs should I consider when deciding to use an SPI or I2C interface?

This accelerometer/gyro breakout board is available in two models, one for each interface. Would either one be easier to integrate into an Arduino project?

JYelton
16.7k28 gold badges94 silver badges195 bronze badges
Mark HarrisonMark Harrison
5,38924 gold badges52 silver badges84 bronze badges
$endgroup$

8 Answers

$begingroup$

Summary

  • SPI is faster.
  • I2C is more complex and not as easy to use if your microcontroller doesn't have an I2C controller.
  • I2C only requires 2 lines.

I2C is a bus system with bidirectional data on the SDA line. SPI is a point-to-point connection with data in and data out on separate lines (MOSI and MISO).

Essentially SPI consists of a pair of shift registers, where you clock data in to one shift register while you clock data out of the other. Usually data is written in bytes by having each time 8 clock pulses in succession, but that's not an SPI requirement. You can also have word lengths of 16 bit or even 13 bit, if you like. While in I2C synchronization is done by the start sequence in SPI it's done by SS going high (SS is active low). You decide yourself after how many clock pulses this is. If you use 13 bit words the SS will latch the last clocked in bits after 13 clock pulses.
Since the bidirectional data is on two separate lines it's easy to interface.

SPI in standard mode needs at least four lines: SCLK (serial clock), MOSI (Master Out Slave In), MISO (Master In Slave Out) and SS (Slave Select).In bideroctional mode needs at least three lines: SCLK (serial clock), MIMO (Master In Master Out) which is one of the MOSI or MISO lines and SS (Slave Select).In systems with more than one slave you need a SS line for each slave, so that for $N$ slaves you have $N+3$ lines in standard mode and $N+2$ lines in bidirectional mode. If you don't want that, in standard mode you can daisy-chain the slaves by connecting the MOSI signal of one slave to the MISO of the next. This will slow down communication since you have to cycle through all slaves data.

Like tcrosley says SPI can operate at a much higher frequency than I2C.

I2C is a bit more complex. Since it's a bus you need a way to address devices. Your communication starts with a unique start sequence: the data line (SDA) is pulled low while the clock (SCL) is high, for the rest of the communication data is only allowed to change when the clock is low. This start sequence synchronizes each communication.
Since the communication includes the addressing only two lines are required for any number of devices (up to 127).

edit
It's obvious that the data line is bidirectional, but it's worth noting that this is also true for the clock line. Slaves may stretch the clock to control bus speed. This makes I2C less convenient for level-shifting or buffering. (SPI lines in standard mode are all unidirectional.)

After each byte (address or data) is sent the receiver has to acknowledge the receipt by placing an acknowledge pulse on SDA. If your microcontroller has an I2C interface this will automatically be taken care of. You can still bit-bang it if your microcontroller doesn't support it, but you'll have to switch the I/O pin from output to input for each acknowledge or read data, unless you use an I/O pin for reading and one for writing.

At 400kHz standard I2C is much slower than SPI. There are high-speed I2C devices which operate at 1MHz, still much slower than 20MHz SPI.

stevenvhTeststevenvh
134k15 gold badges425 silver badges637 bronze badges
$endgroup$$begingroup$

(edit: To be clear, many of the following concerns have to do with signal integrity caused by board-to-board use of I2C/SPI devices, as Olin correctly points out.)

Unless you have constraints that strongly push you towards fewer wires (we had one project with a hermetically-sealed connector that each additional contact was rather expensive), avoid I2C when possible, and stick with SPI.

SPI is fairly easy to deal with on a hardware and a software basis. In hardware, there are two shared data lines, Master In Slave Out (MISO or SOMI) and Master Out Slave In (MOSI or SIMO), a shared clock generated by the master, and one chip select per device. The CS line goes low, the clock cycles and essentially shifts in input bits and shifts out output bits, until the transaction finishes, at which point the CS line goes high. When their CS line is high, slave devices don't communicate: they ignore the CLK and MOSI lines, and put their MISO pin into a high-impedance state to let someone else use it.

If you have a microcontroller using several SPI devices, and it has a built-in SPI peripheral, send the microcontroller's CS output to a demultiplexer (e.g. 74HC138) and control the address lines to select the device between SPI transactions; you write words to a register to queue them up for output, and read them back after the CS pin is raised high.

Because SPI signals are all unidirectional, they can be buffered, used across an isolation barrier with digital isolators, and can be sent from board to board using line drivers like LVDS. The only thing you have to worry about is the round-trip propagation delay, which will limit your maximum frequency.

I2C is a completely different story. While it's much simpler from a wiring standpoint, with only two wires SCL and SDA, both these lines are shared bidirectional lines that use open-drain devices with an external pullup. There's a protocol for I2C that starts by transmitting a device address, so that multiple devices can be used if each has their own address.

From a hardware standpoint, it is very difficult to use I2C in systems that have any significant noise. In order to buffer or isolate I2C lines, you have to resort to exotic ICs -- yes, they exist, but there aren't many: we used one on one project and realized that you could use one isolator, but you couldn't use two in series -- it used small voltage drops to figure out which side was the driving end of things, and two series drops were two much.

The logic level thresholds of I2C depend on Vcc so you have to be really careful if you use 3V/3.3V and 5V devices in the same system.

Any signals that use a cable of more than a foot or two have to worry about cable capacitance. Capacitance of 100pf/meter isn't out of the ordinary for multiconductor cable. This causes you to have to slow down the bus, or use lower pullup resistors, to be able to handle the extra capacitance properly and meet the rise time requirements.

So let's say you have a system that you think you've designed well, and you can deal with most of the signal integrity issues, and noise is rare (but still present). What do you have to worry about?

There are a bunch of error conditions you have to be prepared to handle:

  • Slave device doesn't acknowledge a particular byte. You have to detect this and stop and restart the communications sequence. (With SPI, you can usually read back the data you send if you want to make sure it was received without error.)

  • You're reading a byte of data from a slave device, and the device is 'hypnotized' because of noise on the clock line: You have sent the requisite 8 clocks to read that byte, but because of noise, the slave device thinks it has received 7 clocks, and is still transmitting a 0 on the data line. If the device had received the 8th clock, it would have released the data line high so that the master could raise or lower the data line to transmit an ACK or NACK bit, or the master could transmit a stop (P) condition. But the slave is still holding the data line low, waiting in vain for another clock. If a master is not prepared to try extra clocks, the I2C bus will be stuck in deadlock. While I have used several microcontrollers that handle the normal ACK/NACK conditions, I have never used one that handles this missed clock bit (or extra clock bit) condition successfully, and I've had to exit automatic I2C mode, enter into bit-banging mode, add clocks until the data line is high, and re-enter automatic I2C mode.

  • The really awful case is when a master is writing data to one slave device, and another slave interprets the device address incorrectly and thinks that the data transmitted is meant for it. We've had I2C devices (I/O expanders) that occasionally have registers set incorrectly because of this. It is nearly impossible to detect this case, and to be robust to noise, you have to periodically set all registers, so that if you do run into this error, at least it will be fixed after a short period of time. (SPI never has this problem -- if you happen to have a glitch on the CS line, it will never persist for long and you won't get data accidentally read by the wrong slave device.)

A lot of these conditions could be handled properly in the protocol if there were error detection (CRC codes), but few devices have this.

I find that I have to build complex software in my I2C master device to handle these conditions. In my opinion, it's just not worth it unless the constraints on wiring force us to use I2C and not SPI.

Jason SJason S
12.6k2 gold badges37 silver badges60 bronze badges
$endgroup$$begingroup$

The breakout board for device at SparkFun is actually for the I2C version only (MPU-6500). The MPU-6000 version has both SPI and I2C interfaces on the same chip, and I don't see that SparkFun has a board with that chip. So I believe you are limited to using I2C if you want to use that particular board. But I was going to recommend using I2C anyway in your situation for the following reasons.

In general, you will find that the I2C bus is easier to use from a hardware standpoint than the SPI bus. I2C is a 2 wire bus (SCL/SDA):

SPI is a 4 wire bus (SCLK/MOSI/MISO/CS):

You can have several devices connected to one I2C bus. Each device has its own set of address(es) built-in to the chip. The address is actually broadcast over the bus as the first byte of every command (along with a read/write bit). This, along with some other overhead, requires more bits to be sent over an I2C bus vs SPI for the same functionality.

I2c

Different classes of devices (memory, I/O, LCD, etc.) have different address ranges. Some devices, which are commonly used more than once in a system (such as the PCF8574 I/O expander), use one or more address lines (AD0-2 for the PCF8574) which can be tied high or low to specify the low bits of the address. The MPU-6500 has one such address line (AD0), so two of them can be used in the same system.

You can also have multiple devices on an SPI bus, but each device must have its own chip-select (CS) line. Therefore the 4-wire description is a bit of a misnomer -- it is really a three wire interface + one additional wire per device. I am not experienced with the Arduino series of boards, but I believe this would make using SPI more difficulty on the Arduino, since if you needed lots of chip select lines this would start to get cumbersome with the common pin assignments used by the various shields.

I believe most Arduino boards run at 5 volts, with some newer ones running at 3.3v. The MPU-6500 runs at 3.3v. If the minimum input 'high' voltage for a the I2C bus on a 5v CPU is 3v or below, you could avoid level conversion issues by just providing 10K pullup resistors to 3.3v on the SCL and SDA lines, since the bus is open-collector. Make sure any 5v internal pullups on an CPU are disabled.

However I checked the datasheet for the ATmega2560 (using the ADK 5v Arduino as an example), and its minimum input 'high' voltage is 0.7*Vcc, or 3.5v which is greater than 3.3v. So you need some sort of active level conversion. The TI PCA9306, which requires pullups resistors on both 5v and 3.3v sides of the chip, costs just 78 cents in single quantities.

Why then ever pick SPI over I2C? Mainly because SPI can be run much much faster -- up to many 10's of MHz in some cases. I2C is generally limited to 400 KHz. But this is not really an issue for the MPU-6050/6000 accelerometer, since it runs at 400 KHz for I2C, and only 1 MHz for SPI -- not that much of a difference.

tcrosleytcrosley
43k5 gold badges79 silver badges141 bronze badges
$endgroup$$begingroup$

In general, SPI is a faster bus - the clock frequency can be in a range of MHz. However, SPI requires at least 3 lines for bi-directional communication and an additional slave select for each device on the bus.

I2C only requires 2 lines, regardless of how many devices you have (within limits, of course). The speed, however, is in the range of kHz (100-400kHz is typical).

Most microcontrollers, nowadays, have hardware support for both buses, so both are equally simple to use.

ArmandasArmandas
6,2141 gold badge23 silver badges45 bronze badges
$endgroup$$begingroup$

SPI can be run much faster than I2C (some SPI devices go over 60MHz; I don't know if the 'official' I2C spec allows devices over 1MHz). Implementation of a slave device using either protocol requires hardware support, while both allow easy implementation of 'software bit-bang' masters. With relatively minimal hardware, one can construct an I2C-compliant slave which will operate correctly even if the host may arbitrarily decide to ignore the bus for up to 500us at a time, without need for additional handshaking wires. Reliable SPI operation, however, even with hardware support, generally requires that one either add a handshake wire, or else that the host 'manually' add a delay after each byte equal to the slave's worst-case response time.

If I had my druthers, controllers' SPI support would contain a few simple extra features to provide 8-bit-transparent bidirectional data transfers between controllers with handshaking and wake-up abilities, using a total of three unidirectional wires (Clock and MOSI [master-out-slave-in] from the master; MISO [master-in-slave-out] from the slave). By comparison, efficient and reliable communication between microcontrollers with 'stock' SPI ports, when both processors might independently be delayed for arbitrary lengths of time, requires the use of a lot more wires (Chip-Select, Clock, MISO, and MOSI to start with, plus some sort of acknowledge wire from the slave. If the slave might asynchronously start having data to send (e.g. because someone pushed a button), then one must either use yet another wire as a 'wakeup' signal or else have the master repeatedly poll the slave to see if it has data yet.

I2c Vs Uart Performance Tool

I2C does not provide all the abilities my 'improved' SPI would have, but it does offer built-in handshaking abilities which SPI lacks, and in many implementations it can be kludged to provide wake-up as well, even if the master is a software bit-bang. For inter-processor communication, I would therefore strongly recommend I2C over SPI except when higher speeds are needed than SPI can supply, and the use of extra pins is acceptable. For inter-processor communications where low pin count is needed, UARTs have a lot to recommend them.

supercatsupercat
39k1 gold badge65 silver badges115 bronze badges
$endgroup$$begingroup$

This question has been thoroughly explored in the excellent answers here, but perhaps there's one more point of view to I2C I could offer from a chip maker's point of view.

The I2C's electrical interface is an open collector. Now breathe and think of the implications. Using I2C, I can design a chip which is totally agnostic to the operating voltage of the bus. All that I need to be able to do is pull the SDA line low if it pleases me to do so, and compare the voltages of SCL and SDA to some ground-referenced threshold voltage, which I can choose. And if I leave out the normal high side protection structures and replace them with other structures, I can make a chip which can totally live its own life undependent from the rest of the system - SCL, SDA never feed any current to my chip and I certainly won't feed any current to those pins. That's why it's such a nice bus for real-time clocks and other low power stuff like that.

PkPPkP
$endgroup$I2c vs serial$begingroup$

One thing I haven't seen mentioned in the other answers is that I2C supports multiple masters on the same bus. If you need bidirectional communication and don't want to use a polling-based method, I2C will get the job done.

Over longer distances, CAN has the same capability and is more robust. But CAN is an asynchronous protocol that requires hardware support and a transceiver, so it may not be an option in a low-cost system.

Adam HaunAdam Haun
17.2k4 gold badges33 silver badges78 bronze badges
$endgroup$$begingroup$

Use the SPI protocol and write your bits directly to the device whenever the sync clock is rising. The xnor logic circuit can be used to match the 'homemade' address from a memory to select the wanted device as if it was an i2c device.

The i2c is integrating the authorial circuit inside the format of the device, standard...etc are complex and different, with a spi you can use a spi memory to display a video on screen, but not i2c.

I2c Vs Uart Performance Tool

laptop2d
33.4k12 gold badges40 silver badges100 bronze badges
lansupermanlansuperman
$endgroup$

I2c Vs Uart Performance Test

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

Posted on