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?
|show 2 more comments|
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.
SPI needs at four lines: SCLK (serial clock), MOSI (Master Out Slave In), MISO (Master In Slave Out) 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. If you don't want that 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.
After each byte (address or data) is being 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.
|show 6 more comments|
(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:
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.
|show 3 more comments|
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.
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.
|show 5 more comments|
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.
|show 17 more comments|
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 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.
|show 1 more comment|