In the sketch example, we have used an industrial controller Arduino M-Duino 21+, but all of the industrial Arduino PLCs range of Industrial Shields can also be used to perform the same example:
The SPI (Serial Peripheral Interface) bus was developed by Motorola in 1980. It is currently a standard in the world of electronics and automation.
The SPI bus has a master-slave architecture.
- MOSI (Master-out, slave-in) Master to Slave communication
- MISO (Master-in, slave-out) Slave to Master communication.
- SCK (Clock) Clock signal generated by the master
- SS (Slave Select) It selects the device with which communication is to be made
Typical SPI wiring
Advantages and Disadvantages
Full Duplex Communication.
Higher transmission speed than with I²C or SMBus.
Flexible protocol in which you can have absolute control over the transmitted bits.
It is not limited to 8-bit block transfer.
Choice of bit frame size, its meaning and purpose.
Its hardware implementation is extremely simple.
It consumes less energy than I²C or SMBus because it has fewer circuits (including pull-up resistors) and these are simpler.
No arbitration or failure response mechanism is necessary.
Client devices use the clock sent, therefore they do not need their own clock.
It is not mandatory to implement a transceiver (transmitter and receiver): a connected device can be configured to only send, only receive or both options at the same time.
It uses much less terminals on each chip / connector than an equivalent parallel interface.
At most, a single specific signal is required for each user (SS signal); the other signals can be shared.
It consumes more pins of each chip than I²C, even in the 3-wire variant.
The addressing is done through specific lines (out-of-band signaling) unlike what happens in I²C where each chip is selected by a 7-bit address that is sent by the same bus lines.
There is no hardware flow control.
There is no sign of assent. The server could be sending information without no customers connected and would not notice anything.
It does not easily allow having multiple servers connected to the bus.
It only works over short distances unlike, for example, RS-232 or RS-485.
Typical SPI connections
Option 1) If it is a connection where few slaves have to be connected, the following connection scheme is used:
An additional SS (Slave Select) line is required for each slave device connected, to select the device with which communication have to be made.
Option 2) This previous connection has the disadvantage of requiring a line for each slave device. In case of having many slave devices, this may not be practical, so it is possible to adopt a cascade connection, where each slave transmits data to the next one:
On the other hand, in this configuration the information must reach all the slaves so that the communication is terminated, that is why, in general, the bus response speed is lower than in the first configuration.
Every Industrial Shields programmable logic controller has the SO, SI and SCK pins. Check the User Manual of your industrial PLC version to see where this pins are located. Also check the Pinout chapter of the User Manual to see how many pins can be used as SS (Slave Select). Here you have the M-Duino 21+ PLC controller example:
To use the SPI port on Arduino the IDE Standard provides the library "SPI.h" that contains the functions needed to control the integrated SPI hardware.
Basic SPI functions:
SPI.begin(); // Starts the SPI busTo change the order of the sent bits, we have the setBitOrder function:
SPI.transfer(c); // Send a byte
SPI.attachInterrupt(); // Activate the interrupt to receive data
setBitOrder (LSBFIRST); //Least Significant bit first
setBitOrder (MSBFIRST); //Most Significant bit first
To change the polarity and the phase of the clock, we have the SPI.setDataMode function:
setDataMode (SPI_MODE0); // clock normally LOW, rising edge sampling
setDataMode (SPI_MODE1); // clock normally LOW, flank sampling lowered
setDataMode (SPI_MODE2); // clock normally HIGH, rising edge sampling
setDataMode (SPI_MODE3); // clock normally HIGH, flank sampling lowered
Finally, we can change the bus speed with the SPI.setClockDivider () function divisors from 2 to 128. The bus frequency will be the clock speed divided by the chosen divisor.
setClockDivider (SPI_CLOCK_DIV2); // 8 MHz (considering a 16 MHz model) setClockDivider (SPI_CLOCK_DIV4); // 4 MHz setClockDivider (SPI_CLOCK_DIV8); // 2 MHz setClockDivider (SPI_CLOCK_DIV16); // 1 MHz setClockDivider (SPI_CLOCK_DIV32); // 500 KHz setClockDivider (SPI_CLOCK_DIV64); // 250 KHz setClockDivider (SPI_CLOCK_DIV128); // 125 KHz
However, these functions are obsolete since the Arduino version 1.6.0., The beginTransaction function is preferred, as the following example shows.
SPI.beginTransaction (SPISettings (2000000, MSBFIRST, SPI_MODE0)); // 2 MHz clock, MSB first, mode 0
However, being the specific data frame of each device, more often than not, we do not use these functions directly, and our use of the SPI bus is carried out indirectly through the library of the component.
You can find SPI communication examples on the Arduino IDE as you can see in the following image: