AVR training course. Working with SPI module. Reading and writing data. Ch2. How to work with SPI - Theory Spi input

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 check

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, which converts 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, inverse 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); Feature packages come in several types: 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.

The endpoints in the USB standard are the sources and sinks of data. 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 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 from either the host or 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

SPI in Arduino, it is one of the main protocols for exchanging data between the Arduino board and connected devices. Together with I2C and UART, this protocol is often used for many types of peripheral devices, so knowledge of the principles of SPI operation is necessary for any Arduino engineer. In this article we will briefly look at the basic principles, interaction scheme and method of connecting SPI sensors and screens to Arduino.

SPI is a widely used data transfer protocol between a microcontroller (Master) and peripheral devices (Slave). In our projects, an Arduino board is most often used as a Master. The SPI interface was invented and used by Motorola, but over time it became an industry standard. The main advantage of working with this interface is its high speed and the ability to connect several devices on one data bus.

SPI pins and pins

Communication via the SPI arduino interface occurs between several devices that are located close to each other. Arduino boards are equipped with separate pins for SPI. Pairing occurs using four contacts:

  • MOSI – information is transmitted via this line to the Slave from the Master.
  • MISO – used to transfer information to the Master from the Slave.
  • SCLK – creation of clock pulses for synchronous data transmission.
  • SS – slave device selection.

Interaction of SPI devices

Device interaction begins when the SS output goes low.

Before starting work you need to determine:

  • Which bit should the shift start from - high or low? The order is adjusted using the PI.setBitOrder() function.
  • Determine the level at which the SCK line should be in the absence of a clock pulse. Adjustable by SPI.setDataMode() function.
  • Select the data transfer rate. Determined by the SPI.setClockDivider() function.

The next step is to determine in what mode the information will be transferred. The choice of mode is determined by such indicators as the polarity and phase of the clock pulse. If the level is low, 0 is recorded, high - 1. There are 4 modes in total:

  • Mode 0 – SPI_MODE0: polarity (CPOL) 0, phase (CPHA) 0.
  • Mode 1: polarity 0, phase 1.
  • Mode 2: polarity 1, phase 0.
  • Mode 3: polarity 1, phase 1.

Initially, Arduino was designed to transmit data with the most significant bit first, but before starting, you need to clarify this in the documentation. You can demonstrate the modes in the picture.

There are two types of connections possible in the SPI interface: independent and cascaded. In the first case, when connecting, the Master addresses each Slave individually, in the second case, the connection occurs one by one, i.e. cascade.

Connecting SPI to Arduino

Each Arduino model has its own SPI pins. These conclusions:

  • Uno: MOSI corresponds to pin 11 or ICSP-4, MISO – 12 or ICSP-1, SCK – 13 or ICSP-3, SS (slave) – 10.
  • Mega1280 or Mega2560: MOSI – 51 or ICSP-4, MISO – 50 or ICSP-1, SCK – 52 or ICSP-3, SS (slave) – 53.
  • Leonardo: MOSI – ICSP-4, MISO – ICSP-1, SCK – ICSP-3.
  • Due: MOSI – ICSP-4, MISO –ICSP-1, SCK –ICSP-3, SS (master) – 4, 10, 52.

The latest Arduino Due controller expands user capabilities and allows you to implement more tasks than other microcontrollers. For example, it is possible to automatically control the slave device and automatically select different configurations (clock speed, mode, etc.).

Arduino SPI Library

To work on Arduino, a separate library has been created that implements SPI. Before starting the code you need to add #include to enable the library.

Main functions:

  • begin() and end() – turn work on and off. During initialization, the SCLK, MOSI and SS lines are configured at the output, sending a low level to SCLK, MOSI and a high level to SS. The end() function does not change the line levels; it is needed to turn off the block associated with the interface on the Arduino board.
  • setBitOrder(order) – setting the order of sending information bits (MSBFIRST – priority of the most significant bit, LSBFIRST – priority of the least significant bit).
  • setClockDivider(divider) – setting the main frequency clock dividers. You can set divisors of 2, 4, 8, 16, 32, 64 and 128. It is written as follows - SPI_CLOCK_DIVn, where n is the selected divisor.
  • setDataMode(mode) – select one of four operating modes.
  • transfer(value) – transfers a byte from the master device and returns the byte that is received from the slave device.
  • shiftIn(miso_pin, sclk_pin, bit_order) and shiftOut(mosi_pin, sclk_pin, order, value) – accepting and sending data, can be connected to any digital pins, but before that you need to configure them yourself.

Advantages and Disadvantages of SPI

Advantages of the SPI interface:

  • Ability to transmit large data, not limited to 8 bits.
  • Easy to implement software.
  • Simplicity of hardware implementation.
  • Fewer pins are needed than for parallel interfaces.
  • Only the speed of the devices limits the maximum clock frequency.

Flaws:

  • Large number of pins compared to I2C.
  • Slave cannot control the flow of information.
  • Lack of a standard error detection protocol.
  • A large number of ways to implement the interface.
  • Lack of confirmation of receipt of information.

An example of using Arduino SPI in a project with a pressure sensor

To implement the project we need an Arduino, a pressure sensor, a breadboard and wires. An example of sensor connection is shown in the figure.

Using the SCP1000 sensor, it is possible to recognize parameters such as pressure and temperature and transmit these values ​​via SPI.

Basic elements of a program sketch

First of all, the sensor registers are registered in the code using setup(). Several values ​​are returned from the device - one in 19 bits for the received pressure, another in 16 bits for the temperature. After this, two temperature bytes are read and pressure is read in two stages. First, the program takes the three most significant bits, then the next 16 bits, after which, using a bit shift, these two values ​​are combined into one. Real pressure is the 19-digit value divided by 4.

const int PRESSURE = 0x1F; // first stage of pressure determination (three most significant bits are detected)

const int PRESSURE_LSB = 0x20; // second stage, which defines 16 bits for pressure

const int TEMPERATURE = 0x21; //16 bits for temperature

To read the temperature data and convert it to Celsius, the following code element is used:

int tempData = readRegister(0x21, 2);

float realTemp = (float)tempData / 20.0; // to determine the real temperature value in Celsius, you need to divide the resulting number by 20

Serial.print(“Temp

Serial.print(realTemp);

Reading pressure bits and combining them:

byte pressure_data_high = readRegister(0x1F, 1);

pressure_data_high &= 0b00000111;

unsigned int pressure_data_low = readRegister(0x20, 2);

long pressure = ((pressure_data_high<< 16) | pressure_data_low) / 4; //определение давления в Паскалях.

Brief conclusions about SPI

SPI shields and sensors are often found in Arduino projects, so you need to know how this protocol works. In principle, there is nothing complicated about connecting SPI devices. The main thing is to connect the wires correctly and use the standard library methods in the right sequence. For some devices, for example, SD cards or OLED screens, there are, in principle, no alternatives.

Good day! Today’s article is a small theoretical digression that will help us in mastering the Arduino Programming course. We will talk about the SPI interface. What it is and what it is eaten with, we will try to figure it out in this article.

To begin with, the definition. SPI(Serial Peripheral Interface - serial peripheral interface) is a serial synchronous data transmission standard, which is designed to communicate the controller with various peripherals. This interface is simple and convenient. A special library for working with SPI was written for Arduino.

Communication is based on the “master-slave” principle. The controller is usually the master device. All other devices that are connected to the system are slaves. Data from the master device is transmitted via the data bus to one of the selected slaves or vice versa from the slave device to the master synchronously, using the master clock signal.

SPI data bus pinout consists of 4 lines: MOSI, MISO, CS and SCLK:

  • MOSI(Master Out Slave In - Master-output, Slave-input) or simply S.I.– data transfer occurs from the master device to the slave device.
  • MISO(Master In Slave Out - Master-input, Slave-output) or simply SO– data transfer occurs from the slave device to the master device.
  • C.S.(Chip Select - Chip selection) or SS(Slave Select — Slave selection) – selection of a slave device.
  • SCLK(Serial CLOCK) or simply SCK– transmission of a clock signal from the master to the slave.

In order to transfer data from a master to a slave, it is necessary for the master to set the signal level low on the CS line of the slave with which it is going to establish communication. The bits are then transferred over the MOSI line. To stop data transmission, the leader “releases” the CS line, as it were, setting a high signal level on it.

To connect several slave devices to the SPI data bus, each of them needs to have its own individual CS line. Once this is done, the master device can alternately “pull” the lines, switching between the slave devices. Multiple slaves can be connected in different ways: in parallel or in series.

Parallel connection of slave devices via SPI data bus

The peculiarity of parallel connection of several slave devices is that common lines SCLK, MOSI and MISO are used to create communication. In this case, each slave device has its own SS(CS) line. The master device determines which “current slave” to establish data exchange with by generating a low signal level on the corresponding SSn line (where n – 1,2...).

To connect n-numbers of slave devices to the controller via the SPI interface, you need to allocate them for this purpose n+3 microcontroller pins.

Serial connection of slave devices to the SPI bus

As for the serial connection of slave devices, they use common lines SCLK and SS, and the output of one is connected to the input of the other. The MOSI line of the master is connected to the first slave, and the MISO line is connected to the last. If you look at this connection from the point of view of the master device, then one slave device is connected via the SPI data bus.

It should be noted the advantage of this type of connection: you can connect the nth number of devices using only 4 pins of the microcontroller for this purpose.

That's all for now, to be continued...

Today we begin our acquaintance with the tire SPI (Serial Peripheral Interface).

This bus is very widely used in electronics. It is very convenient, being synchronous and full duplex, therefore, it is used in many circuits for communication between various digital devices - sensors, controllers, drivers and other devices.

Another important factor in the need for our acquaintance with it is that this bus is organized in hardware in controllers AVR.

Moreover, whether we want it or not, we have been communicating with the SPI interface for a long time, as soon as we started flashing our controller for the first time, since it is flashed through this interface.

Therefore, I would like to get to know this tire better.

Let's open the technical documentation for the Atmega8 controller, open the page where the pinout of this controller is shown and see that pins 16 to 19 are where the SPI bus pins are located

Now a little more about these findings

SS (chip select)— this is the device selection leg. If the slave device on this pin is set to a low level, then this device will respond and exchange information via the SPI bus; if it is high, it will not.

MOSI (master output slave input)- This is the output pin of the master device and the input of the slave device.

MISO (master input slave output)- on the contrary, the output of the slave, the input of the master.

SCK— synchronization leg. All devices participating in the exchange of information on this bus are supplied with clock pulses at a certain frequency.

Here is a diagram of the implementation of the SPI bus in the Atmega8 controller

Like any bus, there are a number of registers that store certain information.

We are interested in SHIFT REGISTER, information is exchanged through it. As soon as there is a certain edge on the synchronization pin, either descending or ascending, depending on the settings, these registers of the slave and master devices will exchange information, and not all the information, but only one bit. These registers will shift to the left and the most significant bits from each register will go to the least significant bits of the same register of the associated device. That is, the slave will transmit its most significant bit through the MOSI pin to the leader, who will write it into the vacated low-order bit due to the left shift, and the slave will transfer its displaced high-order bit through the MISO pin to the low-order bit of the leader. This is how the exchange goes, that is, in 8 full clock cycles they will completely exchange bytes

As soon as all 8 bits of one byte of information are transmitted, a certain register will signal to us that this process is completed. Or rather, a certain bit of a certain register.

Also in the block diagram we see a divider, the input of which receives clock pulses and then, divided by a certain value, they are sent through a chain to the SCK pin and from there they are fed to the slave device on the pin of the same name. This ensures synchronized operation of the devices. The clock frequency is selected from the lowest one supported by all devices participating in the exchange.

I say plural because there can be more than just two devices on a given circuit. How this is ensured, provided that the devices do not have any addresses, I will now tell you.

There are several ways to exchange information between several devices, that is, when there are several slaves per one master device. We will look at the two most common of them.

The first method is radial (click on the picture to enlarge the image)

Here the master directs data to a specific device, turning on logical 0 on the SS pin. With this method, it is possible to select only one device; you will also need several free pins of the controller ports.

There is another interesting method - ring or cascade (click on the picture to enlarge the image)

Here we see that the selection legs are all parallel and the exchange goes in a circle. Thus, the speed decreases due to the fact that the transmission circle increases, but the port legs are saved.

We will study all this in more detail in the next lessons, when we use certain devices in our projects.

Well, it seems with the circuitry of data transmission via the bus SPI we figured it out.

Now let’s figure out how to control this process at the level of hardware registers of the AVR controller.

We see these registers in the block diagram above on the page.

Atmega8 has the following registers for servicing the SPI bus.

SPDR (SPI Data Register)- data register, in the block diagram it is DATA BUFFER. We will enter a byte into this register for its subsequent transmission to the slave device, and from it we will read the byte of information that came from the slave device. It is also not necessary that our controller will be the master device. Subsequently, we will assemble a circuit of two controllers, one of which will be a slave. So it is in this register that the byte for both sending and receiving will be located.

SPCR (SPI Control Register)- control register

This register includes the following bits:

SPIE (SPI Interrupt Enable)- a bit that enables interrupts.

SPE (SPI Enable)— a bit that enables the SPI bus.

DORD (Data Order)— a bit that sets the order in which bits are sent. If it is set to 1, then the least significant bit is sent first, if it is set to 0, the most significant bit is sent.

MSTR (Master/Slave Select)— a bit that designates a device as a master or slave. When this bit is set to 1, the device will be the master.

CPOL (Clock Polarity)— synchronization polarity, determines at what edge of the synchronizing pulse the standby mode will be initiated

If this bit is 1, then we will have a standby mode with an ascending edge, and if it is 0, then with a descending edge.

CPHA (Clock Phase)— a bit responsible for the clock phase, that is, on which edge the bit will be transmitted.

Let's look at the data transfer diagrams depending on the installation of CPOL and CPHA

This is such an interesting dependence. Sometimes we sometimes see in the technical characteristics of a device that it, for example, can operate in SPI 0:0 and SPI 1:1 mode, and this is exactly what concerns setting these bits.

SPR1, SPR0 (SPI Clock Rate Select)- these are the bits responsible for the value of the synchronization frequency divider; they work together with the bit SPI2X located in the status register. It is also a control one, since eight bits in the control register were not enough for all the settings, and there are many free ones in the status register.

SPSR (SPI Status Register)- status register

SPI2X (Double SPI Speed ​​Bit)- a bit that doubles the speed, working in conjunction with the SPR1 and SPR0 bits of the control register.

Let's see the dependence of the frequency on these three bits

SPIF (SPI Interrupt Flag)— Interrupt flag. We are waiting for this bit to be set to one. when we receive a byte. As soon as the byte from another device appears completely in our buffer, this flag will be set. This flag only works if the bit that enables interrupts is set, as well as global interrupts are enabled.

WCOL (Write COLlision Flag)— the conflict or collision flag will be set if there is a bit conflict during data transfer, if during data transfer an attempt is made to write to the data register.

Well, now we can say that we have become a little familiar with the SPI interface.

Watch VIDEO TUTORIAL(click on the picture)

Post Views: 6,294

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 cascaded connections in a separate article.