I am working on a project where I am integrating BME688 ,CAN, LoRa, SD card, ePaper display and WiFi module. I am using the board Heltec LoRa V2. And I have found this pin diagram. What I don't understand is why did they use different pins for SPI (with LoRa) instead of the predefined ones. Based on the ESP32 data sheet the 2 SPI pins that are available are assigned to these pins: enter image description here


So my question is whats the benefit of changing the SPI pins (and how is that even possible)? While reading the official documentation from espressif it mentions something about GPIO matrix and IOMUX . Where it states the following

Most peripheral signals in ESP32 can connect directly to a specific GPIO, which is called its IOMUX pin. When a peripheral signal is routed to a pin other than its IOMUX pin, ESP32 uses the less direct GPIO matrix to make this connection.

If the driver is configured with all SPI signals set to their specific IOMUX pins (or left unconnected), it will bypass the GPIO matrix. If any SPI signal is configured to a pin other than its IOMUx pin, the driver will automatically route all the signals via the GPIO Matrix. The GPIO matrix samples all signals at 80MHz and sends them between the GPIO and the peripheral.

When the GPIO matrix is used, signals faster than 40MHz cannot propagate and the setup time of MISO is more easily violated, since the input delay of MISO signal is increased. The maximum clock frequency with GPIO Matrix is 40MHz or less, whereas using all IOMUX pins allows 80MHz.

To me this is something new, I never heard about it. If somebody can explain whats going on and knows the reason behind this pin-choice, I would appreciate it. Additionally, can somebody help me define the pins for the free SPI (since one is being used by the LoRa module). I want to drop the oled screen that comes with the module and use an ePaper display instead.


2 Answers 2


The short story of the SPI pins is:

  • If you use the pins shown in the table in your questions, you can achieve SPI speeds of up to 80 MHz.
  • If you use other pins, then you are limited 40 MHz.

As most peripherals have a maximum SPI speed of considerably less than 40 MHz, it's often not relevant. So you can take any GPIO pins you like.

Given the Heltec board, the choice has already been made for you. I have no idea why they have chosen this particular set of pins. Possibly, it has simplified the PCB.

I don't know the details of your peripherals. But let's assume you have devices connected both by SPI and I2C.

I2C and SPI are buses. So several devices can be connected to the same bus. Therefore, there is no need to use a separate SPI or I2C bus. You can simply reuse the SPI buses choses by Heltec:

  • SPI: pins 5 / 19 / 27 for SCK / MISO / MOSI
  • I2C: pis 15 / 4 of SCL / SDA

Each SPI device will requires a seprate CS line. You can choose from the remaining GPIOs: 0, 2, 12, 13, 17, 22, 23.

Pins from 32 upwards are also available as GPIOs but can only work as input pins. So they are not suitable as a CS signal.

Pin 16 can be used if the OLED is not used. I can't tell you whether the same is true for 4 and 15 as they might be wired to a pull up resistors. So it's probably better to use those pins for I2C as designed and connect your I2C devices to it.

  • \$\begingroup\$ Thank you for the answer. I think we are in the same page. The thing that I want to do is drop the oled screen and use an ePaper one which uses SPI. My main problem comes from the syntax in the code, I tried contacting the person who wrote the libary for the epaper display which can be found here (github.com/ZinggJM/GxEPD2). Since I am using ESP32 with AVS architecture I do not know if this supports to change the SPI peripheral. \$\endgroup\$
    – Ra'w
    Aug 7, 2019 at 6:56
  • \$\begingroup\$ I am thinking I am making a syntax mistake my code for initializing the screen: SPIClass hspi(HSPI); GxIO_Class io(hspi, /*CS=5*/ 14, /*DC=*/ 17, /*RST=*/ 16); GxEPD_Class display(io, /*RST=*/ 16, /*BUSY=*/ 4); (Sorry for the terrible code format do not know how to format it in the comment section) \$\endgroup\$
    – Ra'w
    Aug 7, 2019 at 6:57
  • \$\begingroup\$ Do I correctly understand: your code does not compile? If so, better start a new question with all the relevant code and the full error message. \$\endgroup\$
    – Codo
    Aug 7, 2019 at 10:50
  • \$\begingroup\$ The code was compiling but I made a silly mistake, used MISO instead of MOSI. So now it works, but there another problem. The LoRa_RST pin is connected to the HSPI_CLK pin. So now I have to use this IOMUX feature to change the default HSPI_CLK pin, but I do not know how to do that. Do you have any suggestions? You can see the pin diagram in the first post. \$\endgroup\$
    – Ra'w
    Aug 7, 2019 at 11:00
  • \$\begingroup\$ Something along the lines of hspi.begin(2, 12, 13);... \$\endgroup\$
    – Codo
    Aug 7, 2019 at 11:05

For Arduino IDE,

You can change the pins from pins_arduino.h

Make sure you are changing it for right board. Below was the path for me C:\Users\USER\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\variants\doitESP32devkitV1

  • \$\begingroup\$ Sorry that link is only good on your Windows computer and maybe a few like it. Try adding a link on the internet that shows how to do it or explain in detail. \$\endgroup\$
    – Gil
    Jul 16, 2021 at 17:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.