Spi data transfer speed. AVR training course. Working with SPI module. Part 1. Library for working with the SPI interface

The SPI interface is one of the most popular serial interfaces today. It was invented by Motorola and quickly gained popularity due to its exceptional simplicity and high speed. At the same time, SPI probably cannot be fully called an interface; rather, it is simply a communication principle, since all that is meant by SPI is data transfer logic between two devices (“Master” - “Slave”), much less attention is paid to physics, it is implemented, one might say, “according to circumstances,” but there is no lower-level protocol at all, here each manufacturer comes up with something of its own.

Well, let's start with the main thing. So, what's the logic here? The logic is that data is transmitted sequentially, bit by bit, while reading and setting data are separated in time using a special clock signal on a special bus. This bus is called the clock bus (or synchronization bus), and the essence of the separation is that data is read and set on opposite edges of the clock pulses generated on the bus. This, clearly separated in time, alternation of settings and readings makes it possible to use the same register for both receiving and transmitting data. Previously (when memory was small and expensive, operating systems were stored on floppy disks, and mammoths ran through the fields) this was a serious advantage, moreover, this is what SPI was originally designed for, but now there are no problems with memory capacity and most devices can easily afford to have separate input and output registers.

The device that controls the clock bus (that is, generates clock pulses on it) is the “Master” or “Master”. Actually, the “Master” manages all data exchange - he decides: when to start the exchange, when to end it, how many bits to transfer, etc. The second device participating in the exchange is the “Slave” or “Slave”. In SPI, unlike, for example, the same I2C, the “Slave” has absolutely no rights, it cannot influence the clock bus at all and cannot in any way inform the master that it is not on time or, conversely, that it is already ready for exchange. That is, the “Master” himself must know: when to ask the “Slave”, what and at what speed, so that he can answer him.

In total, for full-duplex exchange (in both directions simultaneously), the SPI interface uses 4 lines (see figure): SCLK, MOSI, MISO and SS.

  1. SCLK— clock bus (on this line the master generates clock pulses)
  2. MOSI (M aster O ut, S love I n) — master output, slave input (via this line the master transmits data to the slave)
  3. MISO (M aster I n, S love O ut) - master input, slave output (via this line the master receives data from the slave)
  4. SS (S love S elect) - selection of a slave (using this line the master controls exchange sessions)

“1” and “0” are encoded by the voltage level on the data buses (MOSI, MISO) in ordinary positive logic, that is, a high voltage level on the bus corresponds to “one”, and a low level corresponds to “zero”. At the same time, how the installation of these levels on the buses is organized is not specified anywhere, that is, the transmitter outputs can be either “push-pull” or “open collector”. A high level usually corresponds to the supply voltage of the microcircuit (that is, if we are dealing with five-volt microcircuits, then a high level is a voltage close to five volts, if we are talking about microcircuits powered by 3.3V, then a high level is a voltage close to to 3.3V).

The SS signal marks the beginning and end of an exchange session. This signal is usually inverse, that is, during a data exchange session, the master must set the SS line to a low level, and in the absence of exchange, to a high level. The presence of the SS signal allows the master to organize a connection to several slaves using the same clock signal and the same data buses, without any additional protocols (a variant of such a connection is shown in the figure on the left). True, there is one drawback: in this case, the master will have to connect to each slave via a separate SS line (in order to manage exchange sessions with each slave independently of each other), which increases the total number of wires used.

The names of the lines, in general, are not a standard and may differ depending on the manufacturer (for example, instead of MOSI, MISO and SCLK, the lines may be called DI, DO and SC, or SI, SO and CLK, the SS line may be called CS or RESET).

Moreover, there do not have to be four lines - sometimes there can be only three, for example, if data is transferred in only one direction or one bidirectional data bus is used instead of two unidirectional data buses. Obviously, in the latter case, only half-duplex exchange is possible, that is, at one point in time you can only transmit or only receive data (but you cannot transmit and receive at the same time).
That is, neither by the name of the lines, nor by the voltage levels on them, nor even by their number, it is impossible to unambiguously identify SPI, but this can be done perfectly well by the method of data transfer itself, by how they are installed on the bus and read.

As I already mentioned, data is transmitted bit by bit, and data is installed and read on opposite edges of the clock signal. The moment of reading data in English literature is called latch(fixation, snapping), and the moment the data is installed on the bus - shift(shift). The installation moment is called a shift due to the characteristics of most serial interfaces. Usually, no one transmits data one bit at a time; as a rule, they are sent in packs of 8 or more bits (the pack size is most often a multiple of eight). In this regard, a shift register is made at the output of the transmitter, where the entire packet of transmitted bits is loaded at once, and the value of the low or high bit of this shift register is set on the data bus (depending on how we transmit - low or high bit forward), and to set it to bus of the next transmitted bit - just “shift” this register. This is how transmitters are arranged in SPI, and in I2C, and in the usual RS232, and many other places (it’s just more convenient in hardware). Well, okay, let's return to our SPI.

The logical level of the signal on the clock bus in the inactive state (when there is no data transmission) is called polarity and is designated CPOL (that is, if in the absence of transmission the SCLK bus is low, then CPOL = 0, and if at this time the SCLK bus is high, then then CPOL=1). The order of alternating readings and shifts is called phase and is designated CPHA (if a read occurs on the first edge on SCLK, then CPHA = 0, and if a shift occurs on the first edge on SCLK, then CPHA = 1).

Depending on the combination of CPOL and CPHA values, there are 4 operating modes of the SPI interface, which are designated as Mode0, Mode1, Mode2 And Mode3. Below is a picture illustrating how data is installed and read, depending on the selected mode.

I would like to emphasize that SS is precisely the exchange session control line, and not just the slave selection line. The difference here is that if we consider SS simply a slave selection line, then when a master is connected to one single slave, there is a temptation not to control this line, but to hard-short it to the common wire (such as so that the slave is always selected). However, the logic of the slave is usually such that the beginning of the session is accompanied by various preparatory procedures, such as loading data into the output shift register and resetting the pulse counter, and the slave begins to perform some actions (in accordance with the commands received via SPI from the master) only after completion exchange session. In addition, you may well need several communication sessions (for example, if in the first session you send commands, and in the next you want to receive a report on the result of their execution). I think it’s clear that if you tightly pull the SS line to the common wire, then there can be no question of any recognition of the beginning and end of the exchange session (the beginning is recognized by the decline on the SS line, and the end by the rise); accordingly, the entire data exchange will be disrupted . So the importance of the SS signal should not be underestimated.

And finally, I’ll say that the most popular modes are Mode0 and Mode3.

More details about how the exchange occurs, what an SPI master should be able to do and how to implement it in software on a microcontroller (using the example of PIC and AVR controllers) can be read in the article

SPI - Serial Peripheral Interface - serial

peripheral interface

SPI is a serial synchronous standard for data transfer between microcircuits in full duplex mode.

This interface was originally developed by Motorola to provide simple and inexpensive interfacing of microcontrollers and peripherals, and is currently used in products from many manufacturers.

The SPI interface, along with I2C, is one of the most widely used interfaces for connecting microcircuits. Its name is an abbreviation for “Serial Peripheral Interface” (SPI bus).

SPI bus), which reflects its purpose - a bus for connecting external devices. The SPI bus is organized on a master-slave basis. The bus master is usually a microcontroller, but it can also be programmable logic, a DSP controller, or an ASIC. External devices connected to the bus master form bus slaves. Their role is played by various kinds of microcircuits, incl. storage devices (EEPROM, Flash memory, SRAM), real time clock (RTC), ADC/DAC, digital potentiometers, specialized controllers, etc.

The main building block of the SPI interface is a conventional shift register, whose synchronization and bitstream input/output signals form the interface signals. Thus, it is more correct to call the SPI protocol not a data transfer protocol, but a data exchange protocol between two shift registers, each of which simultaneously performs both the function of a receiver and a transmitter.

1. Electrical connection

IN difference from a standard serial port standard serial port), SPI is a synchronous interface in which any transmission is synchronized with a common clock signal generated by the master device (processor). The receiving peripheral (slave) synchronizes the receipt of the bit sequence with the clock signal. Multiple chips can be connected to one serial peripheral interface of a chip master. The master selects the slave for transmission by activating the chip select signal on the slave chip. Peripherals not selected by the processor do not participate

in SPI transmission.

SPI uses four digital signals:

MOSI (eng. Master Out Slave In) - output of the master device (alternative designation DO, SDO, DOUT), input of the slave device for serial data reception (alternative designation DI, SDI, DIN). Serves to transfer data from the master device to the slave.

MISO (eng. Master In Slave Out) - input of the master device for serial data reception (alternative designation DI, SDI, DIN), output of the slave device for serial data transmission (alternative designation DO, SDO, DOUT). Serves to transfer data from a slave device to a master device.

SCLK (eng. Serial Clock) - serial clock signal (alternative designation DCLOCK, CLK, SCK). Serves to transmit a clock signal for slave devices.

CS or SS - chip selection, slave selection

(eng. Chip Select, Slave Select).

There are three types of connection to the SPI bus, each of which involves four signals. The simplest connection, which involves only two microcircuits, is shown in Figure 1.

Rice. 1. The simplest connection to the SPI bus

Here, the bus master transmits data along the MOSI line synchronously with the SCLK signal generated by it, and the slave captures the transmitted data bits on certain edges of the received synchronization signal. At the same time, the slave sends its data package. The presented circuit can be simplified by eliminating the MISO line if the slave IC used does not provide for response data transmission or there is no need for it. One-way data transfer can be found in such chips as DACs, digital potentiometers, programmable amplifiers and drivers. Thus, the considered option for connecting a slave IC requires 3 or 4 communication lines. In order for the slave IC to receive and transmit data, in addition to having a clock signal, the SS line must also be driven low. Otherwise, the slave IC will be inactive. When only one external IC is used, it may be tempting to eliminate the SS line by driving the slave IC's select input hard low. This solution is extremely undesirable and can lead to failures or even the impossibility of data transfer, because The chip select input serves to reset the IC to its initial state and sometimes initiates the output of the first bit of data.

If it is necessary to connect several microcircuits to the SPI bus, either an independent (parallel) connection is used (Fig. 2) or a cascade (serial) connection (Fig. 3).

Rice. 2. Independent connection to the SPI bus

Rice. 3. Cascade connection to the SPI bus

Independent connection is more common, because achieved when using any SPI-compatible chips. Here, all signals, except for the selection of microcircuits, are connected in parallel, and the bus master, by transferring one or another SS signal to a low state, specifies with which slave IC it will exchange data. The main disadvantage of this connection is the need for additional lines for addressing slave chips (the total number of communication lines is 3+n, where n is the number of slave chips). Cascade switching is free from this drawback, because here from

several chips form one large shift register. To do this, the transmit data output of one IC is connected to the data receive input of the other, as shown in Figure 3. The chip select inputs here are connected in parallel and, thus, the total number of communication lines is kept equal to 4. However, the use of cascade connection is possible only if its support is indicated in the documentation for the chips used. To find out, it is important to know that such a connection is called "daisy-chaining" in English.

2. Transfer protocol

The transmission protocol over the SPI interface is extremely simple and, in fact, is identical to the logic of the shift register, which consists in performing a shift operation and, accordingly, bit input and output of data on certain edges of the synchronization signal. Data setting during transmission and sampling during reception are always performed on opposite clock edges. This is necessary to ensure that the data is sampled once it has been reliably established. If we take into account that the first edge in the transmission cycle can be a rising or falling edge, then there are four possible logic options for the operation of the SPI interface. These options are called SPI modes and are described by two parameters:

CPOL - the initial level of the synchronization signal (if CPOL=0, then the synchronization line before the start of the transmission cycle and after its end has a low level (i.e. the first edge is rising, and the last is falling), otherwise, if CPOL=1, it is high (i.e. the first front is falling, and the last one is rising));

CPHA - synchronization phase; this parameter determines the sequence in which the setting and sampling of data is performed (if CPHA = 0, then on the rising edge in the synchronization cycle the data will be sampled, and then, on the falling edge, the setting

data; if CPHA=1, then data installation will be performed on the rising edge in the synchronization cycle, and sampling will be performed on the falling edge).

Master and slave chips operating in different SPI modes are incompatible, therefore, before choosing slave chips, it is important to clarify which modes are supported by the bus master. Hardware SPI modules integrated into microcontrollers, in most cases, support the ability to select any SPI mode and, therefore, it is possible to connect any slave SPI chips to them (applies only to an independent connection option). In addition, the SPI protocol in any of the modes is easily implemented in software.

Table 1. SPI modes

Temporary

diagram

synchronization

3. Comparison with I2 C bus

As already mentioned, the 2-wire I2 C serial bus is no less popular for connecting microcircuits. Below you can see the advantages that this or that serial bus provides.

Advantages of the SPI bus

Advantages of the I2C bus

Extreme simplicity of the protocol

physical layer transmissions

provides high reliability and

transmission speed. Limit

SPI bus performance is measured

The I2 C bus remains two-wire,

tens of megahertz and, therefore, it

regardless of quantity

ideal for streaming

microcircuits connected to it.

large volumes of data and widely

used in high speed

DAC/ADC, LED drivers

displays and memory chips

All SPI bus lines are

unidirectional, which is essential

Possibility of multi-master

simplifies the solution of the problem

operation when connected to the bus

level conversions and

several leading microcircuits.

galvanic isolation of microcircuits

The I2C protocol is more

standardized, therefore

Simplicity of software implementation

user of I2C chips more than

SPI protocol.

protected from problems

incompatibility of selected

components.

4. Derivative and compatible protocols

MICROWIRE.

National Semiconductor's MICROWIRE protocol is completely identical to the SPI protocol in mode 0 (CPOL = 0, CPHA = 0).

Maxim 3-wire interface

The difference with this interface is that instead of full-duplex transmission over two unidirectional lines, it performs half-duplex transmission over one bidirectional DQ line.

QSPI

A higher-level protocol than SPI, allowing automated data transfer without CPU involvement.

In addition, the SPI interface is the basis for building a number of specialized interfaces, incl. JTAG debugging interface and Flash memory card interfaces, incl. SD and MMC.

Transfer interfaces.

Many data transfer interfaces have been developed to transfer data from one device to another or from one chip to another. Each interface has both positive and negative sides, so you need to know what interfaces there are, their pros and cons, and use the right interface to transfer data in a given situation.

Interfaces come with asynchronous and synchronous data transfer. With synchronous data transmission, a clock signal is transmitted simultaneously with the data, allowing the receiver and transmitter to synchronize. An example of such a protocol is the SPI interface.

In asynchronous data transmission there is no clock signal. In such lines there is a danger of mismatch between the receiver and transmitter, as a result of which further data will not be received correctly. To prevent this, asynchronous interfaces perform periodic synchronization along data lines. The advantage of such interfaces is the smaller number of conductors required for transmission.

Let's take a closer look at several of the most popular interfaces.

USART interface.

USART interface is a serial universal synchronous-asynchronous transceiver. Data is transferred to the USART at regular intervals. This time period is determined by the specified USART speed and is specified in baud (For characters that can only take values ​​equal to zero or one, baud is equivalent to bits per second). There is a generally accepted range of standard speeds: 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 baud.

In addition to the data bits, the USART automatically inserts synchronization marks into the stream, the so-called start and stop bits. Upon reception, these extra bits are removed. Typically, the start and stop bits separate one byte of information (8 bits), but there are USART implementations that allow 5, 6, 7, 8, or 9 bits to be transmitted. The bits separated by the start and stop signals are the minimum sending. USART allows you to insert two stop bits during transmission to reduce the likelihood of receiver and transmitter desynchronization in heavy traffic. The receiver ignores the second stop bit, treating it as a short pause on the line.

The convention is that the passive (in the absence of data) state of the USART input and output is a logical “1”. The start bit is always a logical “0”, so the USART receiver waits for a transition from “1” to “0” and counts from it a time interval of half the duration of the bit (the middle of the start bit transmission). If at this moment the input is still “0”, then the process of receiving the minimum parcel starts. To do this, the receiver counts 9 bit durations in a row (for 8-bit data) and records the input state at each moment. The first 8 values ​​are received data, the last value is a test value (stop bit). The stop bit value is always “1”; if the actual received value is different, the USART records an error.

To form time intervals, the transmitting and receiving USARTs have a source of precise time (clocking). The accuracy of this source must be such that the sum of the errors (receiver and transmitter) in setting the time interval from the beginning of the start pulse to the middle of the stop pulse does not exceed half (or better yet, at least a quarter) of the bit interval. For an 8-bit message 0.5/9.5 = 5% (in reality no more than 3%). Since this is the sum of the receiver and transmitter errors plus possible signal distortion on the line, the recommended tolerance for USART clocking accuracy is no more than 1.5%.

Since the clock bits occupy part of the bitstream, the resulting UART throughput is not equal to the connection speed. For example, for 8-bit 8-N-1 format transmissions, the clock bits occupy 20% of the stream, which for a physical speed of 115,200 baud gives a data bit rate of 92,160 bps or 11,520 bytes/s.

Parity

The USART protocol has the ability to automatically monitor data integrity using the bit parity method. When this feature is enabled, the last bit of data (the "parity bit") is always 1 or 0, so that the number of ones in a byte is always even.

Flow control

In the old days, USART devices could be so slow that they could not keep up with the incoming data stream. To solve this problem, USART modules were provided with separate flow control outputs and inputs. When the input buffer was full, the logic of the receiving USART set the inhibiting level at the corresponding output, and the transmitting USART suspended transmission. Later, flow control was assigned to communication protocols, and the need for separate flow control lines gradually disappeared.

Physical implementation.

USART is an exchange protocol, i.e. it determines the method of bit formation, byte transmission parameters, transmission speed, etc.

But the physical implementation of USART may be different. For example, to transmit data within one board, signals are transmitted at +5V and 0V levels. To transfer data over long distances and between devices, other physical voltage levels and standards are used, such as: current loop (4-20 mA), RS-232 (COM port), RS-485 and the like.

To convert “controller” levels of 0-5V into “standard” levels, there are a huge number of specialized microcircuits, for example ADM202 for RS-232.

Serial interface SPI

The name SPI is an abbreviation for "Serial Peripheral Bus", which reflects its purpose - a bus for connecting external devices. The SPI bus is organized according to the master-slave principle. The bus master is usually a microcontroller, but it can also be programmable logic, a DSP controller, or an ASIC. Devices connected to the master are slaves. Their role is played by various kinds of microcircuits, incl. storage devices (EEPROM, Flash memory, SRAM), real time clock (RTC), ADC/DAC, digital potentiometers, specialized controllers, etc.

The main building block of the SPI interface is a conventional shift register, whose synchronization and bitstream input/output signals form the interface signals. Thus, it is more correct to call the SPI protocol not a data transfer protocol, but a data exchange protocol between two shift registers, each of which simultaneously performs both the function of a receiver and a transmitter. A prerequisite for data transmission on the SPI bus is the generation of a bus synchronization signal. Only the leader has the right to generate this signal and the work of the slave completely depends on it.

Connection.

There are three types of connection to the SPI bus, each of which involves four signals. The purpose of SPI signals is described in Table 7.1.

The simplest connection, which involves only two microcircuits, is shown in Figure 7.2. Here, the bus master transmits data along the MOSI line synchronously with the SCLK signal generated by it, and the slave captures the transmitted data bits on certain edges of the received synchronization signal. At the same time, the slave sends its data package. The presented circuit can be simplified by eliminating the MISO line if the slave IC used does not provide for response data transmission or there is no need for it. One-way data transfer can be found in such chips as DACs, digital potentiometers, programmable amplifiers and drivers. Thus, the considered option for connecting a slave IC requires 3 or 4 communication lines.

In order for the slave IC to receive and transmit data, in addition to having a clock signal, the SS line must also be driven low. Otherwise, the slave IC will be inactive. When only one external IC is used, it may be tempting to eliminate the SS line by driving the slave IC's select input hard low. This solution is extremely undesirable and can lead to failures or even the impossibility of data transfer, because The chip select input serves to reset the IC to its initial state and sometimes initiates the output of the first bit of data.

If it is necessary to connect several microcircuits to the SPI bus, either an independent (parallel) connection is used (Fig. 7.3) or a cascade (serial) connection (Fig. 7.4). Independent connection is more common, because achieved when using any SPI-compatible chips. Here, all signals, except for the selection of microcircuits, are connected in parallel, and the bus master, by transferring one or another SS signal to a low state, specifies with which slave IC it will exchange data. The main disadvantage of this connection is the need for additional lines for addressing slave chips (the total number of communication lines is 3+n, where n is the number of slave chips).

If there are not enough microcontroller legs, you can use a demultiplexer chip. The demultiplexer connects a single input signal to one of the output signals, depending on the code on the control pins. Figure 7.4 shows the connection diagram for the demultiplexer. The SS signal is supplied to its input, which takes a value equal to 0 if it is necessary to select one of the microcircuits. The number of the required microcircuit in binary code is supplied to the Am-A0 legs. This allows you to reduce the number of legs used in the microcontroller to m=log 2 n. Where n is the number of slave chips. Those. to connect 128 devices, 8 microcontroller pins are required. One for setting the enabling signal and 7 for setting the number of the chip to be turned on. It should be noted that there must be a logical one on the unconnected legs of the demultiplexer. Otherwise, a signal inverter is used, converting a logical zero into a logical one.

Cascade switching is free from this drawback, because here, several chips form one large shift register. To do this, the transmit data output of one IC is connected to the data receive input of the other, as shown in Figure 3. The chip select inputs here are connected in parallel and, thus, the total number of communication lines is kept equal to 4. However, the use of cascade connection is possible only if its support is indicated in the documentation for the chips used. To find out, it is important to know that such a connection is called "daisy-chaining" in English.

Transfer protocol

The transmission protocol over the SPI interface is essentially identical to the logic of the shift register (Figure 7.6), which consists of performing a shift operation and, accordingly, bit input and output of data on certain edges of the synchronization signal. Data setting during transmission and sampling during reception are always performed on opposite clock edges. This is necessary to ensure that the data is sampled once it has been reliably established. If we take into account that the first edge in the transmission cycle can be a rising or falling edge, then there are four possible logic options for the operation of the SPI interface. These options are called SPI modes and are described by two parameters:

· CPOL - initial level of the synchronization signal (if CPOL=0, then the synchronization line before the start of the transmission cycle and after its end has a low level (i.e. the first edge is rising, and the last one is falling), otherwise, if CPOL=1, - high (i.e. the first front is falling, and the last one is rising));

· CPHA - synchronization phase; This parameter determines the sequence in which data is installed and retrieved. If CPHA=0, then on the rising edge of the clock cycle the data will be sampled, and then on the falling edge the data will be set. If CPHA=1, then data installation will be performed on the rising edge in the synchronization cycle, and sampling will be performed on the falling edge.

Information on SPI modes is presented in Figures 7.7 and 7.8.

Master and slave chips operating in different SPI modes are incompatible, therefore, before choosing slave chips, it is important to clarify which modes are supported by the bus master. Hardware SPI modules integrated into microcontrollers, in most cases, support the ability to select any mode and, therefore, any slave SPI chips can be connected to them (applies only to an independent connection option). In addition, the SPI protocol in any of the modes is easily implemented in software.

RS-485 interface

The RS-485 interface (another name is EIA/TIA-485) is one of the most common physical communication layer standards. The physical layer is a communication channel and a signal transmission method (layer 1 of the OSI open systems interconnection model).

A network built on the RS-485 interface consists of transceivers connected using a twisted pair - two twisted wires. The RS-485 interface is based on the principle of differential (balanced) data transmission. Its essence is to transmit one signal over two wires. Moreover, one wire (conditionally A) carries the original signal, and the other (conditionally B) carries its inverse copy. In other words, if there is a “1” on one wire, then a “0” on the other and vice versa. Thus, there is always a potential difference between the two wires of a twisted pair: at “1” it is positive, at “0” it is negative (Figure 7.9).

It is this potential difference that transmits the signal. This transmission method provides high immunity to common mode interference. Common-mode interference is an interference that affects both wires of the line equally. For example, an electromagnetic wave passing through a section of a communication line induces potential in both wires. If the signal is transmitted by potential in one wire relative to the common, as in RS-232, then interference on this wire can distort the signal relative to the common (ground) that absorbs interference well. In addition, the ground potential difference will drop across the resistance of a long common wire - an additional source of distortion. And with differential transmission, distortion does not occur. In fact, if two wires lie close to each other, and are even intertwined, then the pickup on both wires is the same. The potential in both equally loaded wires changes equally, while the informative potential difference remains unchanged.

Hardware implementation of the RS485 interface.

Hardware implementation of the interface - transceiver chips with differential inputs/outputs (to the line) and digital ports (to the UART ports of the controller). There are two options for this interface: RS-422 and RS-485.

RS-422 is a full duplex interface. Reception and transmission occur over two separate pairs of wires. There can only be one transmitter on each pair of wires.

RS-485 is a half-duplex interface. Reception and transmission occur over one pair of wires with a time separation. There can be many transmitters in a network, since they can be turned off in receive mode (Figure 7.10).

Explanation of symbols in Fig. 7.10

D (driver) - transmitter;
R (receiver) - receiver;
DI (driver input) - digital input of the transmitter;
RO (receiver output) - digital output of the receiver;
DE (driver enable) - permission to operate the transmitter;
RE (receiver enable) - permission to operate the receiver;
A - direct differential input/output;
B - inverse differential input/output;
Y - direct differential output (RS-422);
Z - inverse differential output (RS-422).

Let's take a closer look at the RS-485 transceiver. The digital output of the receiver (RO) is connected to the receiver UART port (RX). Transmitter digital input (DI) to UART transmitter port (TX). Since the receiver and transmitter are connected on the differential side, the transmitter must be turned off during reception, and the receiver must be turned off during transmission. For this purpose, control inputs are used - receiver permission (RE) and transmitter permission (DE). Since the RE input is inverse, it can be connected to DE and switch the receiver and transmitter with one signal from any port of the controller. At level "0" - work for reception, at "1" - for transmission (Fig. 7.11).

The receiver, receiving the potential difference (UAB) at the differential inputs (AB), converts them into a digital signal at the output RO. The sensitivity of the receiver may be different, but the manufacturers of transceiver chips write in the documentation the guaranteed threshold range for signal recognition. Typically these thresholds are ±200 mV. That is, when UAB > +200 mV - the receiver detects "1" when UAB< -200 мВ - приемник определяет "0". Если разность потенциалов в линии настолько мала, что не выходит за пороговые значения - правильное распознавание сигнала не гарантируется. Кроме того, в линии могут быть и не синфазные помехи, которые исказят столь слабый сигнал.

All devices are connected to one twisted pair cable in the same way: direct outputs (A) to one wire, inverted outputs (B) to the other.

The line side (RAB) receiver input impedance is typically 12KΩ. Since the transmitter power is not unlimited, this creates a limit on the number of receivers connected to the line. According to the RS-485 specification, taking into account the terminating resistors, the transmitter can drive up to 32 receivers. However, there are a number of microcircuits with increased input impedance, which allows you to connect significantly more than 32 devices to the line.

The maximum communication speed according to the RS-485 specification can reach 10 Mbaud/sec. The maximum distance is 1200 meters. If it is necessary to organize communication at a distance of more than 1200 meters or connect more devices than the load capacity of the transmitter allows, special repeaters are used.

I2C interface.

This interface was proposed by Philips, which used it to organize communication between chips in its televisions. I 2 C (an abbreviation for Inter-Integrated Circuit) is a bidirectional asynchronous serial bus. Physically, the I 2 C bus consists of two signal lines, one of which (SCL) is intended for transmitting a clock signal, and the second (SDA) for data exchange. To control the lines, output stages with an open collector are used, so the bus lines must be connected to a +5 V power source through resistors with a resistance of 1...10 kOhm, depending on the physical length of the lines and the data transfer rate. The length of connecting lines in standard mode can reach 2 meters, the data transfer rate is 100 kbit/s.

All bus subscribers are divided into two classes - “Leader” and “Slave”. The master device generates a clock signal (SCL). It can independently access the bus and address any slave device for the purpose of transmitting or receiving information. All slave devices “listen” to the bus to detect their own address and, having recognized it, perform the prescribed operation. In addition, the so-called “MultiMaster” mode is possible, when several master devices are installed on the bus, which either jointly share common slave devices, or alternately act as masters when they themselves initiate the exchange of information, or as slaves when they are waiting for access from another master device. The "MultiMaster" mode requires constant monitoring and recognition of conflicts. In this regard, this mode is more difficult to implement (meaning software implementation) and, as a result, is less often used in real products.

At the initial moment of time - in standby mode - both lines SCL and SDA are in a logical one state (the transistor of the open collector output stage is closed). In transmit mode (Figure 7.12), the SDA data bit is clocked by the rising edge of SCL. The information on the SDA line is changed when the SCL line is in zero state. The slave device can "hold" the SCL line in the zero state, for example, while processing the next received byte, while the master device must wait until the SCL line is freed before continuing to transmit information.

To synchronize I 2 C bus packets, two conditions are distinguished - “START” and “STOP”, limiting the beginning and end of the information packet (Figure 7.13). To encode these conditions, a change in the state of the SDA line with a single state of the SCL line is used, which is unacceptable when transmitting data. The "START" condition is formed when a descending edge appears on the SDA line, when the SCL line is in a single state, and vice versa, the "STOP" condition is formed when a rising edge appears on the SDA line when the SCL line is in a single state.

Data transmission begins on the first rising edge on the SCL line, which clocks the most significant bit of the first information byte. Each information byte (8 bits) contains 9 clock periods of the SCL line. In the ninth cycle, the receiving device issues an acknowledgment (ACK) - a falling edge indicating the reception of data. It should be noted that any bus subscriber, both master and slave, can at different times be both a transmitter and a receiver and, in accordance with the mode, is required to either receive or issue an ACK signal, the absence of which is interpreted as an error.

To start a data exchange operation, the master device issues a "START" condition on the bus. The “START” condition is followed by a byte with the address of the slave device (Figure 7.14), consisting of a seven-bit device address (bits 1...7) and a one-bit read-write operation flag - “R/W” (bit 0). The R/W bit determines the direction of exchange, with 0 meaning data transfer from master to slave (Figure 7.14a), and 1 meaning reading from slave (Figure 7.14b). All bits on the I 2 C bus are transmitted in order from high to low, that is, the 7th bit is transmitted first, the 0th last. The address may be followed by one or more information bytes (in the direction specified by the R/W flag), the bits of which are clocked by the master on the SCL bus.

When performing a read operation, the host must ACK the byte read if it wants to read the next byte, and not issue an ACK if it is about to finish reading the packet (see Figure 7.14b).

It is allowed to resume the address of the slave device multiple times in one transmission cycle, that is, transmitting a repeated “START” condition without a prior “STOP” condition (Figure 7.14c).

It is necessary to note some features of memory chips operating via the I 2 C interface and the procedures for exchanging data with them. Firstly, the non-volatile data memory of these microcircuits is divided into memory pages, so when a byte is written, the entire page is first copied into the internal RAM of the microcircuit, where the desired cell is changed. After this, the old page is erased and a new one is written in its place. Another feature is that the most significant four bits of the slave address must always be equal to 1010. This requirement is regulated by Philips itself.

The 1-Wire bus uses only one conductor for communication and power. The communication mode is asynchronous and half-duplex, which strictly follows the master-slave pattern. One or more slave devices can be connected to the same bus at the same time. Only one master device can be connected to one bus.

The idle state of the bus corresponds to a high level, which is generated by a pull-up resistor. The value of the pull-up resistor is given in the documentation for the slave IC. All chips connected to the bus must be able to produce a low level. If the microcontroller output does not support three states, then it is necessary to provide a driver that has an open collector or open drain output

Signal transmission over the 1-Wire bus is divided into time slots of 60 µs duration. Only one bit of data is transmitted per time slot. Slave devices are allowed to have significant differences from the rated time delays. However, this requires more accurate timing by the leader to ensure correct communication with subordinates who have different time bases.

Basic bus signals.

The master initiates each communication at the bit level. This means that the transmission of every bit, regardless of direction, must be initiated by the master. This is achieved by setting the bus low, which synchronizes the logic of all other devices. There are 5 main commands for communication via the 1-Wire bus: “Write log. 1”, “Write log. 0”, “Read”, “Reset” and “Presence”.

Signal “Write log. 1"

Signal “Write log. 1” is shown in Fig. 7.15. The master sets the low level for 1...15 µs. After this, it frees the bus for the remainder of the time slot.

Rice. 7.15 – Signal “Write log. 1"

Signal “Write log. 0"

Signal “Write log. 0” is shown in Figure 7.16. The master generates a low level for at least 60 µs, but no longer than 120 µs.

Fig 7.16 – Signal “Write log. 0"

Read signal

The “Read” signal is shown in Fig. 7.17. The master sets the low level for 1...15 µs. The slave then holds the bus low if it wishes to transmit a log. 0. If it is necessary to transfer the log. 1, then it simply releases the line. The bus scan must be performed within 15 µs of the bus going low. When viewed from the master's side, the “Read” signal is, in essence, a “Write log” signal. 1". The actual internal state of the slave will be determined by the “Record log” signal. 1" or "Reading".

Figure 7.17 – “Read” signal

Reset/Presence Signal

The “Reset” and “Presence” signals are shown in Figure 7.18. Please note that the pulse time intervals are different. The master pulls low for 8 time slots (480 µs) and then releases the bus. This long period of low condition is called a "Reset" signal.

If a slave is present on the bus, it must, within 60 µs after the master releases the bus, set a low level for at least 60 µs. This response is called “Presence”. If such a signal is not detected, then the master must assume that there are no devices connected to the bus and no further communication is possible.

USB (Universal serial bus) was developed for quickly connecting external devices to a personal computer and then finding and installing the necessary software. Low-power devices are powered directly through the interface.

The USB standard implies the presence of only one Master (Host) device on the network. Moreover, the standard supports up to 127 slave devices on the network. To distinguish between master and slave devices, different types of connectors have been developed (Figure 7.19): Type A for the master and Type B for the slave. It is accepted that the 5V voltage is present only at the type A connector, which is the master connector. The rest of the devices are powered directly from it.

The USB standard uses 4 shielded wires, two of which transmit power (+5v & GND) (Figure 7.19 and Table 7.2). The other two represent twisted pair differential data signals. Encoding scheme used NRZI(Non Return to Zero Invert) for data transmission with a synchronization field to synchronize the master and slave clocks.

The USB 2.0 standard introduced the On-The-Go (OTG) standard, which introduced the Host Negotiation Protocol, which allows two USB devices to agree on who will act as the master. This is intended and limited to single point-to-point connections, such as a mobile phone to a personal computer.

USB supports “hot” (plug’n’play) connection with dynamically loaded and unloaded drivers. The user simply plugs in the device, thereby connecting it to the bus. The host detects the connection, polls the newly inserted device and loads the appropriate driver, indicating the moment of loading with an hourglass on the screen (if the driver for the USB device is already installed on the system). The end user does not care about termination or IRQ(interrupts) and port addresses, nor about rebooting the computer (no reboot required). When the user is done with the USB device, they simply remove it (or unplug the cable), the host will detect the absence of the device and automatically unload the driver.

SB version 1.1 supports two speeds - full speed mode with a speed of 12 Mbits/s and low speed mode with a speed of 1.5 Mbits/s. The 1.5 Mbits/s mode is slower and less sensitive to EMI (interference), which reduces the cost of ferrite beads and reduces the requirements for component quality.

The full-speed bus cable is a twisted-pair cable, protected by a shield, and can also be used for low-speed operation. A cable for operation only at minimum speed (for example, to connect a mouse) can be any and unshielded.

The USB 2.0 standard introduces a High Speed ​​mode with a data transfer rate of 480Mbits/s.

Data transfer.

All data transfers over the interface are initiated by the host. Data is transmitted in the form of packets. The USB interface uses several types of packets:

A) sign package (token package) describes the type and direction of data transfer, the device address and the serial number of the end point (CT is the addressable part of the USB device); There are several types of feature packages: IN, OUT, SOF, SETUP;

B) data package (data packet) contains the transmitted data;

B) approval package (handshake packet) is intended to report the results of data transfer; There are several types of coordination packages: ACK, N.A.K., STALL.

Data transfer via USB is carried out as follows:

The first packet, the so-called token, is generated by the master device to describe the type of data being transferred, the transfer operation (read or write), the device address and the endpoint. The next usually transmitted is a data packet carrying useful information, followed by a handshaking packet indicating that the data or token was received successfully, or the endpoint is stalled or unavailable to accept data.

Endpoints in the USB standard are called data sources and receivers. All devices must support endpoint 0. This is the endpoint that accepts all control and status requests during enumeration (a handle request to determine the type of device attached) and for as long as the device remains operational on the bus.

Endpoints numbered from 1 are used to transmit user information. Let's look at a couple of examples.

The device driver transmits to the master device endpoint EP1. Because This device is the master, then the data goes into the OUT buffer EP1. In this case, an OUT token is sent, indicating that the data is ready to be sent. Having received this token, the slave device can read data from the OUT buffer.

If the slave device needs to transfer data to the master, it places it in the IN buffer. This buffer will hold data until the master device sends an IN token requesting data from the endpoint. All endpoint buffers are named relative to the master, i.e. The output buffer of the slave device is called IN because it is the input buffer for the master device.

Data transfer from one endpoint to another is done through streams. Flow – A logical connection between a host and an endpoint(s).

Streams also have a set of parameters such as transmission type (Control, Bulk, Iso or Interrupt), data flow direction and maximum packet/buffer sizes.

For example, the default stream is a bidirectional stream composed of IN endpoint 0 and OUT endpoint 0 with transfer type control.

USB defines two types of pipes

A) Stream Pipes do not have a predefined USB format, so you can send any type of data through the stream pipe and recover the data at the other end. Data streams are sequential and have a predetermined direction - IN or OUT. Stream pipes support bulk, isochronous and interrupt transfer types. Stream pipes can be controlled either from the host or from the device.

B) Message Pipes have a predefined USB format. They are host-controlled, initiated by a request sent from the host. The data is sent in the desired direction specified in the request. Thus, message pipes allow data to be transferred in both directions, but only support control transfers.

The USB standard describes four types of data transfer:

A) Control forwarding (control transfer) is used for device configuration as well as other device-specific purposes.

B) Streaming (bulk transfer) is used to transmit a relatively large amount of information.

B) Interrupt forwarding (iterrupt transfer) is used to transmit a relatively small amount of information, for which its timely transmission is important. It has a limited duration and higher priority compared to other types of transfers.

D) Isochronous forwarding (isochronous transfer) is also called real-time streaming. Information transmitted in such a transfer requires a real time scale during its creation, transmission and reception.

Streaming transfers characterized by guaranteed error-free data transfer between the host and the function by detecting errors during transmission and re-requesting information. When the host becomes ready to receive data from a function, it sends a flag packet to the function IN-plastic bag. In response to this, the function in the data transfer phase transmits a data packet to the host or, if it

In this article, I want to give a brief overview of the SPI bus (an interface widely used in embedded technology, used to connect various devices) and try to describe the process of creating an SPI device protocol level driver for Linux. This document is not intended to be a complete guide, but rather aims to point in the right direction. Since the article did not fit into one topic, I had to split it into two parts.

0. Instead of introduction

What kind of article is this?
This article is a compilation of information from various sources, a free translation of some parts of the documentation, as well as my own comments, additions and descriptions of problems that have arisen.

Who is this article for?
First of all, for beginners, which I am. On embedded Linux forums you can often come across the question: “How can I work with SPI on this board?” This is exactly what I will try to answer. As an example, I will give the code written to work with my test SPI device.

Article structure
Due to the fact that there was quite a lot of information, the article is divided into several subsections:

  1. What is SPI?
  2. Overview of the SPI subsystem in Linux
  3. Development of a userspace protocol SPI driver using spidev
  4. Development of a kernel level SPI protocol driver
  5. Documentation
The first two points will be included in the first part of the article, the remaining ones will be included in the second.

The first subsection describes the operation of the SPI bus; this part of the article is not specifically tied to Linux, so it can be read by those who are not interested in Linux, but only need to get information about this interface.

The second subsection describes the structures and mechanisms underlying working with SPI in Linux; it must be read to understand what will be discussed in the third and fourth parts.

If you are not interested in my translations and additions, you can safely skip straight to the fifth part, where you can find information on where to get all the necessary information on this issue.

Errors
I'm not a magician, I'm just learning. If you find any errors or inaccuracies, please let me know.

1. What is SPI?

The abbreviation SPI means “Serial Peripheral Interface” or in the Russian version “serial peripheral interface”. The name speaks for itself; this interface is used to work with various peripheral devices. For example, these could be various DACs/ADCs, potentiometers, sensors, input/output port (GPIO) expanders, various memories, and even more complex peripherals such as audio codecs and Ethernet controllers.

From a technical point of view, SPI is a synchronous four-wire bus. It is a connection of two synchronous shift registers, which is the central element of any SPI device. The connection uses a master/slave configuration. Only the master can generate synchronization pulses. There is always only one master in the circuit (unlike the same I2C bus, where an option with more than one master is possible), the number of slaves can be different. In general, the master output is connected to the slave input, and vice versa, the slave output is connected to the master input. When clock pulses are applied to the SCK output, data is pushed out by the master from the MOSI output, and captured by the slave at the MISO input. Thus, if you apply the number of synchronization pulses corresponding to the bit size of the shift register, then the data in the registers will exchange places. It follows that SPI always operates in full duplex mode. But whether we need the data received from the device when recording any parameter is another question. It often happens that the data received from the device when writing data to it is garbage, in which case they are simply ignored, but we will receive them regardless of our desire.

The SPI controller is typically implemented as a peripheral unit in an MCU or eMPU. In most chips it can operate in either master or slave mode. But at the moment, Linux only supports Master mode.

There are several ways to enable SPI devices.

The simplest of them you can see in the picture above (thanks to Wikipedia for the pictures under the free GFDL license). In this case, all slaves are connected to the master in parallel, with the exception of the slave select signal (~CS). Each slave requires a separate slave select signal (labeled SSx in the figure). For slave selection signals, either dedicated outputs of the SPI controller or general purpose input/output (GPIO) ports of the microcontroller can be used.

Two wires are used for data transmission, one for supplying clock pulses and one slave select signal for each of the slaves.
Description of the signals used:

  • MOSI - Master Output, Slave Input (master output, slave input). This signal is intended for serial data transmission from master to slave. May also be called SDO, DO, etc.
  • MISO - Master Input, Slave Output (master input, slave output). This signal is intended for serial data transmission from slave to master. May be called SDI, DI, etc.
  • SCK - Serial Clock (synchronization signal). Used for synchronization during data transfer. It may also be called SCLK, CLK, etc.
  • ~CS - Chip Select (chip selection). This signal activates the slave device. Usually it is inverse, that is, a low level is considered active. Sometimes it is called ~SS (Slave Select, Russian “slave choice”).

A special case of independent connection is the option with one single slave. In this case, you may want to pull the ~CS signal to ground so that the device is always in the active state. But this is highly not recommended, since the slave device can use the CS signal for initialization or for other service purposes.

The main disadvantage of connecting slaves independently is that each slave requires a separate ~CS signal. The cascade connection scheme, called “daisy-chain” in foreign literature (can be translated as “garland”), has no such drawback.

As you can see from the figure above, this uses a common slave select signal for all slaves. The output of each slave is connected to the input of the next one. The output of the last slave is connected to the input of the master, thus forming a closed circuit. With this connection, we can consider that the devices connected in series form one large shift register. Accordingly, data can be written to all devices “in one sitting”, having previously collected the necessary package that combines the data for each of the devices in the order corresponding to the physical order of the connection. But there is one subtle point here. Firstly, all chips must support this type of connection; secondly, the Linux kernel does not support this type of connection, so if you still want to use it, you will have to modify existing drivers or write your own.

There are four operating modes for SPI devices. As a rule, they are the ones that cause the most confusion among beginners. These four modes are a combination of two bits:

  • CPOL (Clock Polarity) - determines the initial level (polarity) of the clock signal.
    CPOL=0 indicates that the clock signal starts low, so that the leading edge is rising and the trailing edge is falling.
    CPOL=1, the clock signal starts high, so the leading edge is falling and the trailing edge is rising.
  • CPHA (Clock Phase) - the synchronization phase determines which edge of the clock signal is used to sample data.
    CPHA=0 indicates that it is necessary to sample on the leading edge, and
    CPHA=1 indicates that data must be sampled on a falling edge.
These two bits form the mode number. CPOL is the most significant bit and CPHA is the least significant bit. Sometimes the device documentation does not explicitly indicate the mode number, but it can always be easily determined from timing diagrams. It is also important to understand that data sampling and setting always occur on opposite edges of the clock signal. For example, let our device operate in mode 0 (the most common option), in this case the slave device will read a data bit from the MOSI input on the leading rising edge of the clock signal, and the master device will read data from the slave at the MISO input also on the leading rising edge . For greater clarity, I will provide oscillograms for all four operating modes:

This figure shows the MOSI (blue line) and SCK (yellow line) signals. In all cases, the number 0x64 is transmitted. Light vertical lines indicate when the data was sampled. Let's consider mode 2, for which, as we remember, CPOL=1 and CPHA=0. Thus, we see that the synchronizing signal initially has a high level, and sampling is performed along the leading edge (in this case, the falling edge). Since my oscilloscope only has two channels, the ~CS and MISO signals are not shown. But in this case they are not so interesting, for example, the ~CS signal is simply a “failure” throughout the entire data transmission.

2. Overview of the SPI subsystem in Linux

SPI drivers in Linux are divided into two parts. The first is SPI controller drivers that work directly with the hardware of a particular controller. Such drivers determine how to configure the controller, what actions to take when entering low-power mode (suspend) and exiting it (resume), selecting the next transfer (spi_transfer) from the transfer queue in a message (spi_message, about queues below) and sending it directly to a port, is also defined as activating/deactivating a specific device via CS (cs_activate/cs_deactivate functions). In this article I will not describe this type of driver. As a rule, they are already implemented for those MCU/eMPUs for which there is a Linux port, and you only need to get into them if you need some specific function, like Chip Select Decoding, to be able to activate the desired slave device via an external logic. Sometimes this is useful, for example in case of GPIO deficiency.

The second part is the protocol drivers used to work with various slave devices that are connected to the SPI bus. These drivers are called "protocol" drivers because they only send and receive various data from slave devices, without directly working with any hardware. It is this type of driver that is most interesting to us, since it allows us to add support for the slave device of interest to the system, which is what we will consider.

Most protocol drivers are kernel modules. For example, if the device is an audio codec connected via SPI, then the driver will also use the functions provided by ALSA, and programs (for example, madplay) will be able to work with it through the /dev/audio character device, without having the slightest idea of ​​how it is built in hardware and which bus it is connected to.

The kernel also provides a general-purpose protocol driver called spidev with a character device interface. It allows you to make half-duplex calls to the SPI slave device using standard read() and write() system calls, set the operating mode, and also perform full-duplex data exchange using ioctl() calls.

Thus, protocol drivers for SPI devices can be divided into two types:

  • userspace drivers that work in user space and are ordinary programs in any language that work with an SPI device by reading/writing the corresponding spidev character device.
  • Drivers that run in kernel space and provide an interface to userspace through device files in the /dev directory, or through attributes in the device directory in sysfs.
Linux queues all calls to SPI devices. SPI protocol drivers operate explicitly or implicitly with messages represented by the struct spi_message structure, which is a multi-segment SPI transaction.
struct spi_message ( struct list_head transfers; struct spi_device *spi; unsigned is_dma_mapped:1; void (*complete)(void *context); void *context; unsigned actual_length; int status; struct list_head queue; void *state; );
transfers - linked list of transferred segments in a transaction (transfers);
spi - pointer to the spi device in whose queue this message is located;
is_dma_maped - if this flag is true, then both dma and cpu virtual addresses are provided for each transmit buffer;
complete - a callback called to indicate the end of a transaction;
context - argument for the complete() callback;
actual_length - the total number of bytes that were transmitted in all successful transfers;
status - 0 in case of success, or a negative value with errno in case of error;

Tags:

  • linux
  • spi
  • spidev
  • embedded
  • kernel module
Add tags

With ratings from 10 Ohm to 1 MOhm);

  • connecting wires (for example, this is a good set);
  • personal computer with Arduino IDE development environment.
  • 1 Description of serial SPI interface

    SPI - Serial Peripheral Interface or “Serial Peripheral Interface” is a synchronous data transfer protocol for pairing master device With peripheral devices (Slave). The master device is often a microcontroller. Communication between devices occurs over four wires, which is why SPI is sometimes called a “four-wire interface.” These are the tires:

    There are four data transfer modes ( SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3), caused by the combination of the polarity of clock pulses (we work at the HIGH or LOW level), Clock Polarity,CPOL, and the phase of the clock pulses (synchronization on the rising or falling edge of the clock pulse), Clock Phase, CPHA.

    The figure explains this table.

    The SPI interface provides several options for connecting slave devices: independent And cascade. When connected independently to the SPI bus, the master device accesses each slave device individually. With a cascade connection, the slave devices operate one by one, as if in a cascade.


    Types of device connection for operation via the SPI interface: independent and cascade

    2 Implementation of the SPI interface on Arduino family boards

    In Arduino, SPI interface buses are located on specific ports. Each board has its own pin assignment. For convenience, the conclusions are duplicated and also placed on a separate ICSP connector(In Circuit Serial Programming, programming a device included in a circuit using a serial protocol). Please note that the ICSP connector does not have a slave selection pin - SS, because it is assumed that the Arduino will be used as a master device in the network. But if necessary, you can assign any digital pin of Arduino as SS.

    The figure shows the standard correspondence of pins to SPI buses for Arduino UNO and Nano.


    3 Library for work with SPI interface

    A special library has been written for Arduino that implements the SPI protocol. It connects like this: at the beginning of the program we add #include SPI.h.

    To get started using the SPI protocol, you need to set the settings and then initialize the protocol using the procedure SPI.beginTransaction(). You can do this with one instruction: SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))

    This means that we initialize the SPI protocol at a frequency of 14 MHz, data transmission occurs starting from MSB (most significant bit), in SPI_MODE0 mode.

    After initialization, select the slave device by moving the corresponding SS pin to the state LOW.

    Then we transfer the data to the slave device with the command SPI.transfer().

    After the transfer we return SS to the state HIGH.


    Work with the protocol is completed with the command SPI.endTransaction().

    It is advisable to minimize the transfer time between the SPI.beginTransaction() and SPI.endTransaction() instructions to avoid problems if another device tries to initiate a data transfer using different settings.

    4 Connecting a shift register to Arduino

    Let's consider the practical application of the SPI interface. We will light the LEDs by controlling an 8-bit shift register via the SPI bus. Let's connect to Arduino shift register 74HC595. We will connect an LED with a nominal value of 220 Ohms to each of the 8 register outputs through a limiting resistor. The diagram is shown in the figure.


    5 Sketch for controlling a shift register via SPI interface

    Let's write a sketch like this.

    #include const int pinSelect = 8; // register select pin void setup() ( SPI.begin(); // initializing the SPI interface pinMode(pinSelect, OUTPUT); // digitalWrite(pinSelect, LOW); // select slave devices (register) SPI.transfer(0); // clear the contents of the register digitalWrite(pinSelect, HIGH); // end of transmission Serial.begin(9600); } void loop() ( for (int i=0; i )

    First, let's connect the SPI library and initialize the SPI interface. Let's define pin 8 as the SS slave selection pin. Let's clear the shift register by sending the value "0" to it. Initialize the serial port.

    To light a specific LED using a shift register, you need to apply an 8-bit number to its input. For example, in order for the first LED to light up, we supply the binary number 00000001, for the second - 00000010, for the third - 00000100, etc. These binary numbers, when converted to the decimal number system, form the following sequence: 1, 2, 4, 8, 16, 32, 64, 128 and are powers of two from 0 to 7.

    Accordingly, in the cycle loop() Based on the number of LEDs, we recalculate from 0 to 7. Function pow(base, degree) Raises 2 to the power of the loop counter. Microcontrollers do not work very accurately with numbers of the "double" type, so we use the rounding function to convert the result to an integer round(). And we transfer the resulting number to the shift register. For clarity, the serial port monitor displays the values ​​obtained during this operation: The unit “runs” through the discharges - the LEDs light up in a wave.

    6 "Running Wave" from LEDs

    The LEDs light up one by one, and we observe a running “wave” of lights. The LEDs are controlled using a shift register, to which we connected via the SPI interface. As a result, only 3 Arduino pins are used to control 8 LEDs. If we were connecting the LEDs directly to the Arduino's digital ports, we would need to use a separate port for each LED.

    We studied the simplest example of Arduino working with the SPI bus. We will consider in more detail the operation of several shift registers with independent and cascade connections in a separate article.