Вы находитесь на странице: 1из 8

Interfacing an SPI ADC (MCP3008) chip to the Raspberry Pi using C++ (spidev)

In this entry I will demonstrate how to interface the MCP3008; an SPI-based analog to digital converter
(ADC) integrated chip, to the Raspberry Pi. This enables the Raspberry Pi to interpret analog voltages
that are in turn typically emitted by analog-based sensors to reflect a measure of a physical
characteristic such as acceleration, light intensity or temperature. We will start by briefly examining the
SPI interface.

Figure 1. 3 SPI slave devices connected to a single SPI master device

A gentle introduction to the Serial Peripheral Interface (SPI)

The Serial Peripheral Interface (SPI) is a communication bus that is used to interface one or more slave
peripheral integrated circuits (ICs) to a single master SPI device; usually a microcontroller or
microprocessor of some sort. Many SPI Peripheral ICs exist. They include, analog to digital converters
(ADC), digital to analog converters (DAC), general purpose input/output (GPIO) expansion ICs,
temperature sensing ICs, accelerometers and many more. In this regards the SPI bus is similar to the I2C
bus. the SPI's main advantage over the I2C bus is that the SPI bus speeds can be very fast; 10Mbps is not
unusual and maximum speeds can go as high as the hardware (master controller, slave peripheral, and
printed circuit board traces connecting them) will go. Speeds that exceed 50Mbps are not unusual.

Having said that, the main disadvantage of the SPI bus w.r.t the I2C bus is the numbers of wires required
by the bus. The I2C bus is a '2-wire' bus that theoretically can be used to connect up to 127 devices, and
significantly more if a 9-bit addressing scheme is used instead of the classical 7-bit address. The SPI bus
is a '3+n wire' bus. where 'n' is the number of slave devices attached to the master SPI device. For
example in the example shown in Figure 1, a total of 6 wires are required by the SPI bus and six
corresponding pins required on the master SPI device to interface the 3 slave SPI devices to the master
SPI controller. This means that not only is the number of wires on an SPI bus larger than on an I2C bus,
but that the number of wires continue to increase linearly as we add more slave devices on to the bus.
Notice that slave SPI devices almost always require 4 pins to attach themselves to the SPI bus.

The 3 SPI wires shared by all devices on the SPI bus are:

o Master in slave out (MISO). Data is moved from slave to master on this wire.

o Master out slave in (MOSI). Data is moved from master to slave on this wire.

o Serial clock (SCLK). This clock is always generated by the master controller and is used to
synchronize the transmission of data between devices on the bus.

In addition to these wires we have 'n' wires for 'n' slave devices on the bus. Each one of these wires
carries the chip select signal (SS or CS) for its respective device. Only one slave device can have its chip
select signal asserted by the master controller at a time.

Figure 2 SPI bus operation

The operation of the SPI bus is conceptually simple. Both the master controller and each slave device
contain a shift register. When the chip select signal of a slave device is asserted (usually by being pulled
low), the MISO, MOSI wires are used to connect its shift register with that of the master device. Clock
pulses are then generated (by the master device) to shift data between the two shift registers enabling
communication. In this sense the read and write operation are combined. For example by shifting the
contents of the master device shift register to that of the slave device, we are also shifting the data in
the slave device shift register to that of the master.

Finally, there are 4 different SPI modes that can be used. Each mode defines a particular clock phase
(CPHA) and polarity (CPOL) with respect to the data. For the purpose of this tutorial we will be utilizing
SPI mode 0 which is also known as mode (0,0) or mode (CPHA=0,CPOL=0).

To learn more about the SPI bus, I refer the reader to these excellent resources:

o Serial Peripheral Interface Bus (Wikipedia)

o Understanding the SPI Bus with NI LabVIEW


o Introduction to Serial Peripheral Interface

The MCP3008 SPI ADC chip

The MCP3008 chip is an SPI based analogue to digital converter (ADC). It has 8 analog input channels
that can be configured for single ended and differential ADC conversions. The MCP3008 is a 10-bit
ADC that can convert up to 200 kilo samples per second (200ksps) (@ 5V!!). The MCP3008 comes in 28
PDIP and SOIC packages. A pinout is provided in Figure 3. The datasheet for the MCP3008 can be can be
downloaded from here.

Figure 3. Pinout of the MCP3008 IC taken form the MCP 3008 datasheet

Typically the VDD pin is connected to 3.3V power. The AGND and DGND pins can be connected directly
to the ground reference point. The VREF pin is the reference voltage which is the largest possible voltage
that the ADC can interpret. In our scenario we will connect the VREF pin to 3.3V (same as VDD). So if
3.3V was sampled on any of the ADC's channels it would be interpreted as the maximum digital value
that can be represented by this 10-bit ADC i.e. 2^10 - 1 = 1023. Similarly the smallest analog voltage that
the ADC can detect (also known as the 'LSB size') is VREF/1024. Which in our case is 3.3V/1024= 3.22mV
and represents a digital value of 1. The equation that converts between the analog voltage and its digital
interpretation is given by "Digital output code = 1024*VIN/VREF"; where VIN is the analog input voltage
and VREF is the reference voltage.

A complete SPI transaction for the MCP3008 (SPI mode 0) is depicted in Figure 4. The complete
transaction consists of 3 bytes being transmitted from master (Raspberry Pi) to slave (MCP3008) and 3
bytes transmitted from slave to master. Recall that due to the nature of the shift register operation of
the SPI bus, shifting 3 bytes into the slave device (writing to the slave MCP3008) will by default cause
the 3 bytes in the slave device to be shifted out into the master device (Raspberry Pi).
Figure 4. Complete SPI transaction for the MCP3008. Diagram taken from MCP 3008 Datasheet.

1. Raspberry Pi asserts the chip select signal connected to the MCP3008 (CS0 in our case) by
setting it to 0V. This is typically taken care of internally by the spidev driver whenever the proper
ioctl() function is called.

2. Raspberry Pi sends a byte containing a value of '1' to the MCP3008. This is a start bit. At the
same time the MCP3008 sends back a 'don't care' byte to the Raspberry Pi.

3. Raspberry Pi then sends a second byte whose most significant nibble (SGL/DIFF,D2,D1 & D0 bits)
indicate the channel that we want to convert and whether we want single-ended or differential
conversion (See Figure 5). For example if this nibble is "1000", the conversion will be single-
ended and take place on channel 0 (CH0 pin). The least significant nibble is sent as 'don't care'.
At the same time, the MCP3008 sends back the two most significant bits of the digital value
(result) of the conversion (bits 8 and 9).

4. Raspberry Pi sends another 'don't care' byte to the MCP3008. At the same time the MCP3008
send back a byte containing bits 7 through 0 0f the digital value (result) of the conversion.

5. The Raspberry Pi then merges bits 8 & 9 from the second received byte with bits 7 through 0
from the third received byte to create the 10-bit digital value resulting from the conversion.
Figure 5. Configuring the ADC conversion. Table taken from MCP3008 datasheet.

Connecting the Raspberry Pi to the MCP3008.


So let's connect the Raspberry Pi to the MCP3008 ! This can be done as shown in Figure 6.
Figure 6. Connecting the Raspberry Pi to the MCP3008

The connections between the Raspberry Pi and the other parts can be made via Male-to Female jumper
wires or via one of Adafruit’s Pi cobbler kits (ver1 or ver2). Note that in this particular scenario, I opted
for attaching the analog input coming from a potentiometer to channel 0 (CH0 pin). Also the SPI
peripheral on the Raspberry Pi has only two chip selects (CS0,CS1 pins) and can therefore only be used
to attach a maximum of two SPI slave devices to the Raspberry Pi. We chose the CS0 pin.

Вам также может понравиться