ESP32 SPI Tutorial Part 1

The ESP32 has 4 SPI interfaces. SPI0 is used as a cache controller for accessing the EMIF and SPI1 is used in master mode only. These two SPI interfaces may be treated as a part of the core system and not be used for general purpose applications. However, SPI2 (called the HSPI from now on) and SPI3 (called the VSPI now onwards) are the interface ports of preference for interfacing to SPI devices.

The register bit maps and descriptions are identical for both the HSPI and VSPI ports.

Essential Registers and Bit Descriptions

In this section, we cover some of the most important registers for the functioning and configuration of SPI master mode. DMA and slave mode is not covered now and may be covered in future parts of this tutorial series.

To configure the ESP32 HSPI or VSPI ports to master mode, not all SPI registers need to be accessed or modified. The registers that are responsible for SPI master mode without DMA capabilities, not in any specific order, are as follows:

Unlike other peripherals that access physical pads via the GPIO matrix, SPI peripheral block does NOT need to be turned on by accessing the DPORT registers.

A typical initialization sequence for SPI will look like this:

  1. Configure GPIO MUX to allow SPI to access GPIO pads
  2. Configure SPI_PIN_REG to set clock peroperties
  3. Configure SPI_USER_REG to enable data output, input, duplex mode and other related configuration options
  4. Program SPI_CTRL_REG to support a specific data transfer order
  5. Enable/disable address feature of data transmission in SPI_USER1_REG
  6. Configure SPI_CTRL2_REG to set timing properties of the SPI bus (very important at high clock speeds!)
  7. Set clock divisor and pre divisor in SPI_CLOCK_REG
    Note that wrong config options in step 7 and 8 may cause communication issues!
  8. SPI_MOSI_DLEN_REG and SPI_MISO_DLEN_REG determine length of outbound and inbound data respectively. In full-duplex mode, both may be kept equal to perform receive-while-transmit (useful in SD card related programs!)
  9. SPI_W0_REG through SPI_W15_REG contain data to be sent
  10. Set the transmission enable bit, SPI_USR, in SPI_CMD_REG to begin operation. SPI_USR bit is cleared automatically by hardware when operation is completed.

Sample VSPI transmission

A successful byte transfer will look something like this:

esp32-spi-tutorial-example-screenshot

Note that if you are using a very high speed configuration, trying to suppress overshoots/undershoots may actually cause the clock signal to lose hard rising/falling edges. Capacitance for the traces must be kept minimum for >20MHz clock.

Sample Source Code

ESP32 SPI sample source code based on Espressif ESP-IDF will be posted soon! To stay updated with latest articles on ESP32 programming and development, please scroll down to the bottom of this page and SUBSCRIBE to us!

3 thoughts on “ESP32 SPI Tutorial Part 1”

Leave a Reply