Another option for low-cost, low-speed communication "inside the box" is the serial peripheral interface.
Several months ago in Beginner’s Corner, we covered the inter-integrated circuit bus. I2C is a popular technology for low-cost, low-speed, communication "inside the box" ("I2C," August 2001, p. 87 ). Another choice to consider is the serial peripheral interface (SPI).
SPI vs. I2C
Both SPI and I2C provide good support for communication with slow peripheral devices that are accessed intermittently. EEPROMs and real-time clocks are examples of such devices. But SPI is better suited than I2C for applications that are naturally thought of as data streams (as opposed to reading and writing addressed locations in a slave device). An example of a "stream" application is data communication between microprocessors or digital signal processors. Another is data transfer from analog-to-digital converters.
SPI can also achieve significantly higher data rates than I2C. SPI-compatible interfaces often range into the tens of megahertz. SPI really gains efficiency in applications that take advantage of its duplex capability, such as the communication between a "codec" (coder-decoder) and a digital signal processor, which consists of simultaneously sending samples in and out.
SPI devices communicate using a master-slave relationship. Due to its lack of built-in device addressing, SPI requires more effort and more hardware resources than I2C when more than one slave is involved. But SPI tends to be simpler and more efficient than I2C in point-to-point (single master, single slave) applications for the very same reason; the lack of device addressing means less overhead.
Inside the box
SPI is a serial bus standard established by Motorola and supported in silicon products from various manufacturers. SPI interfaces are available on popular communication processors such as the MPC8260 and microcontrollers such as the M68HC11. It is a synchronous serial data link that operates in full duplex (signals carrying data go in both directions simultaneously).
Devices communicate using a master/slave relationship, in which the master initiates the data frame. When the master generates a clock and selects a slave device, data may be transferred in either or both directions simultaneously. In fact, as far as SPI is concerned, data are always transferred in both directions. It is up to the master and slave devices to know whether a received byte is meaningful or not. So a device must discard the received byte in a "transmit only" frame or generate a dummy byte for a "receive only" frame.
Figure 1: Single master, single slave SPI implementation
SPI specifies four signals: clock (SCLK); master data output, slave data input (MOSI); master data input, slave data output (MISO); and slave select (ÇSS). Figure 1 shows these signals in a single-slave configuration. SCLK is generated by the master and input to all slaves. MOSI carries data from master to slave. MISO carries data from slave back to master. A slave device is selected when the master asserts its ÇSS signal.
If multiple slave devices exist, the master generates a separate slave select signal for each slave. These relationships are illustrated in Figure 2.
Figure 2: Single master, multiple slave SPI implementation
The master generates slave select signals using general-purpose discrete input/output pins or other logic. This consists of old-fashioned bit banging and can be pretty sensitive. You have to time it relative to the other signals and ensure, for example, that you don’t toggle a select line in the middle of a frame.
While SPI doesn’t describe a specific way to implement multi-master systems, some SPI devices support additional signals that make such implementations possible. However, it’s complicated and usually unnecesary, so it’s not often done.
A pair of parameters called clock polarity (CPOL) and clock phase (CPHA) determine the edges of the clock signal on which the data are driven and sampled. Each of the two parameters has two possible states, which allows for four possible combinations, all of which are incompatible with one another. So a master/slave pair must use the same parameter pair values to communicate. If multiple slaves are used that are fixed in different configurations, the master will have to reconfigure itself each time it needs to communicate with a different slave.
At a higher level
SPI does not have an acknowledgement mechanism to confirm receipt of data. In fact, without a communication protocol, the SPI master has no knowledge of whether a slave even exists. SPI also offers no flow control. If you need hardware flow control, you might need to do something outside of SPI.
Slaves can be thought of as input/output devices of the master. SPI does not specify a particular higher-level protocol for master-slave dialog. In some applications, a higher-level protocol is not needed and only raw data are exchanged. An example of this is an interface to a simple codec. In other applications, a higher-level protocol, such as a command-response protocol, may be necessary. Note that the master must initiate the frames for both its command and the slave’s response.
Both SPI and I2C offer good support for communication with low-speed devices, but SPI is better suited to applications in which devices transfer data streams.
SPI’s full duplex communication capability and data rates (ranging up to several megabits per second) make it, in most cases, extremely simple and efficient for single master, single slave applications. On the other hand, it can be troublesome to implement for more than one slave, due to its lack of built-in addressing; and the complexity only grows as the number of slaves increases.
Far from being just a dumb "byte port," SPI is often an elegant solution for modest communication needs. It can also serve as a platform on which to create higher-level protocols.
David Kalinsky is director of customer education at OSE Systems and a lecturer and seminar leader on embedded software technologies. He has been involved in the design of many embedded medical and aerospace systems. David holds a Ph.D. in nuclear physics from Yale University and can be reached by e-mail at [email protected].
Roee Kalinsky is a senior design engineer at QThink, where he is presently involved in ASIC design and the development of design methodology. He has designed numerous embedded systems including networking, multimedia, and hand-held products. Roee holds a BSEE from the University of California at San Diego. He can be reached by e-mail at [email protected].