SPI (Synchronous Peripheral Interface) is another popular communication protocol used in embedded systems. SPI is a 4-wire master/slave synchronous serial interface. It is used to connect devices over a short distance. The signals are:

·         SCLK (synchronous clock) is the clock source from the master

·         MOSI (master output slave input) is the data from the master to the slave device

·         MISO (master input slave output) is the data from the slave to master device

·         NSS (Negative Slave Select) is the chip select of the slave


An SPI chain can have a single master and multiple slaves, and the NSS signal selects the intended slave device. You can also have a multi-master, multi-slave SPI bus. In an embedded system, the microcontroller is usually the SPI master.

For each byte sent from the master to a slave through the MOSI wire, a response byte is sent back from the slave to the master through the MISO wire. This is the only method by which a slave sends data to the master.

SPI is relatively fast, able to run from a few kHz up to a 10 MHz bit rate. SPI is commonly used for connecting to external modules such as EEPROM, Wifi chip, Bluetooth chip, etc. including ImageCraft’s Smart.IO module.


1.       Only SPI master mode is supported.

2.       For flexibility reasons, software NSS instead of hardware NSS is used.

3.       Some slave devices may require some amount of delay (e.g. one millisecond) between chip select and using the SPI bus.

4.       All SPI devices support 8-bit data. Some ST MCUs also support 16-bit transfers. 16-bit transfers should be used if available, for faster communication.

Whenever the master writes to a SPI slave, data is always returned. For example, if the ST MCU writes 4 bytes to a slave, then 4 bytes are read from the slave, with each byte available as soon as a byte is transferred from the master to slave. As the slave may not have time to return actual data based on the first set of input, the initial returned data may be preset handshaking or some other predefined data.

An SPI slave cannot send data to the master without the master writing to it. Therefore, to read from an SPI slave when the master does not have anything to send, it still has to send bogus bytes such as 0x00 or 0xFF so that data can be read back.

To demonstrate the SPI features, you need to attach additional hardware to the ST-Nucleo. Therefore, no example is provided here.


extern JSAPI_SPI spi1, spi2, spi3, spi4;

Set the pins used for SPI.

void SetPins(

    JSAPI_GPIO *sck_port,

    unsigned sck_pin_no,

    unsigned sck_af,

    JSAPI_GPIO *mosi_port,

    unsigned mosi_pin_no,

    unsigned mosi_af,

    JSAPI_GPIO *miso_port,

    unsigned miso_pin_no,

    unsigned miso_af,

    JSAPI_GPIO *cs_port,

    unsigned cs_pin_no,

    bool active_low


Create a SPI

bool MakeSPI(

    unsigned bits,

    unsigned spi_mode,

    unsigned hz


Enable Chip Select

void ChipSelect(void);

Disable Chip Select

void ChipDeselect(void);

Enable SPI

void Enable(void);

Disable SPI

void Disable(void);

Write value out to the SPI Port

unsigned Write(unsigned data);

Read value of the SPI port.

unsigned Read(void);

Write a sequence of bytes in an array

int WriteByteArray(

    unsigned char *readbuf,

    unsigned char *buf,

    int numbytes


Write a sequence of bytes specified as variable arguments

int WriteBytes(

    unsigned char *readbuf,

    int numbytes,



Read a sequence of bytes

int ReadBytes(

    unsigned char *readbuf,

    int numbytes


Write a sequence of 16-bit words

int WriteWordArray(

    unsigned short *readbuf,

    unsigned short *buf,

    int numwords


Write a sequence of words specified as variable arguments

int WriteWords(

    unsigned short *readbuf,

    int numwords,



Read a sequence of words

int ReadWords(

    unsigned short *readbuf,

    int numwords



In theory, we could devise a scheme similar to the JSAPI_I2C_WIRE and JSAPI_I2C separation, so that multiple SPI devices with different SPI attributes can use the same SPI bus. This can be added as a future enhancement if customer demand warrants it.

How to Use

To use the JumpStart SPI API, with a JSAPI_SPI object (e.g. sp1):

1.       Call SetPins to associate GPIO pins with the SPI unit.

2.       Call MakeSPI to specify the SPI parameters. 1 to 2 MHz SPI works well with most peripherals.

3.       Enable chip select with the ChipSelect call.

4.       Use Read and Write, or ReadBytes/WriteBytes etc. calls to read from and write to the SPI device.

5.       Disable chip select with the ChipDeselect call.