The Serial Peripheral Interface (SPI) interface was to begin with standardized by Motorola in 1979 for short-distance communication in embedded units. In its most common four-wire configuration, total-duplex details transfer is probable on the two knowledge (MOSI, MISO) lines with knowledge prices very well exceeding 10 Mb/s. This tends to make SPI suited for large-bandwidth, comprehensive-duplex purposes like SD storage cards and massive resolution, high-refresh shows.
STM32 gadgets appear with a variable quantity of SPI peripherals, two in the F042 at 18 Mb/s and five in the F411. Across the STM32 family members, the SPI peripheral is comparatively very similar, with quite insignificant variations in the register structure. In this post we’ll glimpse at configuring an SPI peripheral in master mode.
Defining SPI
Just one fascinating and maybe annoying factoid with SPI is that even though it can assist a number of units, it does not have an addressing bus, but instead needs that a specified pin is pulled lower on the system, typically called slave select (SS) or chip select (CS). With SS significant, the slave device puts its other pins into significant impedance manner, successfully disconnecting from the SPI traces. The STM32 SPI peripherals have a provision for a committed SS pin (NSS) that can streamline this course of action if only one unit is linked. Normally you want to use GPIO pins to toggle these SS pins, with one GPIO pin for each unit.
For 4-wire SPI the learn and slave units are thus linked with the adhering to lines, with the SS line duplicated for each additional slave:
- SCLK (serial clock, from grasp)
- MOSI (learn out, slave in)
- MISO (master in, slave out)
- SS (slave find)
Environment up the SPI peripheral is reasonably clear-cut, demanding the configuration of the clock and parameters these types of as 8- or 16-bit transfers. Much less apparent are the SPI clock polarity (CPOL) and section (CPHA) parameters. In this article the default (Manner ) is generally CPOL and CPHA , which interprets to the clock line idling lower and new info staying pushed onto the details line on the trailing edge of the latest clock cycle. CPOL 1 and CPHA 1 result in the reverse conduct. Slaves could aid modes other than mode , but the datasheet for every single slave has to be consulted on a situation-by-situation foundation.
With all of this in mind, we can look at configuring SPI on each the F411 and F042 microcontrollers. Due to the aforementioned similarity between the SPI peripherals throughout the STM32 households it is comparatively clear-cut to adapt the initialization plan. The info transfer routines by themselves keep on being unchanged.
Setting Things Up
Environment up an SPI grasp commences with configuring the GPIO pins that we’ll be making use of. This involves location the proper Alternate Functionality (AF) method and pin parameters, for illustration AF5 on the F411 MCU’s pins 4 via 6 on port A. The SPI pins themselves are assigned the adhering to attributes:
- SCLK: floating, force-pull, large speed.
- MOSI: floating, press-pull, substantial velocity.
- MISO: pull-up, drive-pull, large pace.
- SS: pull-up, force-pull, large velocity.
Considering that SPI depends on a push-pull configuration instead than the open up-drain of I2C, we have to established all pins to match this, along with the speedy GPIO pace solution to maintain up with the SPI signaling. The conclusion to leave a pin floating versus activating its pull-up is established mostly by the function of these pins. In the situation of a pick out pin it is crucial to hold it in a large condition in order to reduce accidental activation of a machine just before the method has finished initializing.
Activating the MISO pin’s pull-up is carried out to retain this line in a identified state when no equipment are selected and therefore none of them are driving the MISO line. Even however the master is not looking at the incoming data sign up, the intermediate voltages can potentially bring about concerns like too much ability draw.
With the GPIO pins thus configured, the goal SPI peripheral is enabled in the applicable Reset and Clock Command (RCC) empower sign-up. For example, the SPI 1 peripheral is enabled in the RCC_APB2ENR
sign up, though SPI 2 and SPI 3 are typically discovered on the APB1 bus and so enabled in the corresponding sign-up in RCC. Upcoming up is configuring the SPI peripheral by itself.
The initially merchandise to configure in this article is the SPI clock divider (baud rate, BR
) in the SPI_CR1
sign-up. This takes advantage of the APB frequency (the peripheral bus frequency, or fPCLK) as the input for the SPI clock, which can be set to among fPCLK/2 and fPCLK/256 using three bits of resolution. The divider should be picked to accomplish a realistic clock and thus transfer speed for the software.
When on both of those the F0 and F4 people the default transfer sizing is 8-little bit, the latter’s peripheral only enables for environment the knowledge body format to either 8- 16-little bit in the SPI_CR1
DFF
(Knowledge Body Structure) sign-up. With the F0’s SPI peripheral the assortment of options is significantly larger when configuring its DS (Information Dimensions) worth in the SPI_CR2
register. This is a 4-little bit benefit that will allow for the data size to be configured to any place among 4- and 16-bits, with e.g. 8-little bit corresponding to b0111.
Except if there are particular requirements, the default 8-bit data dimension, default Manner configuration and default MSB-first placing are superior default options that need to work with most SPI equipment. This then implies that only the clock divisor has to be configured in all scenarios, just after which learn mode can be enabled in SPI_CR1
(MSTR
). The SS pin can then be enabled and established as output by placing SSOE
in SPI_CR2
.
Eventually, the SPI peripheral can be enabled by environment SPE
(SPI Peripheral Empower) in SPI_CR1
.
Info Transfers
As described earlier, SPI enables for full-duplex transfers. The complication this provides arrives from the totally synchronous character of SPI: for each byte place on the MOSI line by the grasp, the slave will set a byte on the MISO line, and vice versa. Considering the fact that the clock line is driven by bytes despatched by the grasp, the consequence is that in purchase to get information from a slave, the master has to set data (e.g. null bytes) on MOSI for each byte on MISO.
A way about this is by modifying the SPI bus from a 4-wire to a three-wire (fifty percent-duplex) configuration employing BIDIMODE
in SPI_CR1
, which does call for cumbersome reconfiguring of the peripheral in amongst transfers. Typically you would want to just place null bytes on MOSI to help you save your self this hassle.
In order to send out bytes to a slave we therefore stick to this sequence following pulling the target’s SS line minimal:
- Wait for
SPI_SR_TXE
(status sign up: transmit sign up vacant) to turn into genuine. - Publish knowledge (8-16 bits) into
SPI_DR
. Repeat from (1) if extra facts has to be written. - Hold out for
SPI_SR_TXE
to become genuine all over again. - Wait for
SPI_SR_BSY
(standing sign-up: bus hectic) to turn out to be false.
The sequence is finished by pulling SS substantial all over again, though noting that some SPI slaves assistance many writes in a solitary sequence. Just one gotcha in this sequence is when we generate information to SPI_DR
that is <16 bits: even if we write an 8-bit uint8_t
variable or similar to this register, it’ll always end up writing 16 bits into the register, with our data plus this padding put onto MOSI and ruining the data transfer. To get around this, we must cast the SPI_DR register to the intended size, e.g. for an 8-bit data array:
*((volatile uint8_t*) &(SPI1->DR)) = data[i]
In purchase to obtain from a slave we both pull SS low, or still left it lower just after a preceding transmission sequence and abide by this sequence:
- Hold out for
SPI_SR_BSY
to turn into phony. - Publish dummy information (e.g. 0x00) into
SPI_DR
to create a clock sign. - Wait around for
SPI_SR_RXNE
(position sign up: obtain knowledge sign up not vacant) to grow to be correct. - Go through details from
SPI_DR
into nearby buffer. Return to (1) to acquire supplemental knowledge. - Hold out for
SPI_SR_BSY
to come phony.
Here far too the sequence is ended by pulling SS substantial once again. Take note that creating the dummy details faces the exact same gotcha as with sending information. Make sure that the SPI_DR
sign up is solid appropriately right before creating the knowledge. As for why we’re each looking at and composing SPI_DR
is because it is a shared sign up, connected to the SPI peripheral’s TX and RX FIFOs.
Lastly, in order to conduct a complete duplex transceive procedure, we can mix these two sequences, distributing details as an alternative of dummy bytes when at the same time receiving info from a slave. This is of system an operation that has to be supported by the slave system in question. For lots of widespread SPI devices and sensors most operations will most likely be performed in a fifty percent-duplex method.
Wrapping Up
There is nonetheless a whole lot much more to SPI as hinted at earlier, nevertheless many of the configuration choices are somewhat obscure and almost never employed, like LSB-first as properly as 16-little bit transfers, TI manner and the numerous clock phase and polarity settings. A far more frequently used part of SPI peripherals which we will tackle in an future short article is the I2S mode that is found on most STM32 MCUs. This is a connection interface for exterior audio codecs, usually discovered as secondary mode on SPI peripherals.
SPI itself sees major use with more substantial-resolution shows and facts storage, but a lot of sensors like Bosch’s BME280 and linked MEMS sensors also put into action an SPI interface in addition to the I2C 1. Depending on the program, putting some of these gadgets on SPI alternatively than I2C might make a ton of feeling due to routing or other constraints.