Skip to content

ESP32-S3 “SPIClass spi(HSPI)” but with pin definitions? #9588

Closed
@Rob58329

Description

@Rob58329

Board

"NodeMCU-32s" & "Firebeetle2 ESP32-3"

Device Description

Board connected to "Adafruit_ST7796S_kbv" tft (although not really relevant) using the HSPI .

Hardware Configuration

#define SD_CS 15
#define TFT_CS 33
#define TFT_DC 17
#define SPI_MISO 12 // default pin
#define SPI_MOSI 13 // default pin
#define SPI_CLK 14 // default pin
#define TFT_RST -1

Version

latest master (checkout manually)

IDE Name

Arduino IDE v1.8.19

Operating System

Windows 10

Flash frequency

n/a

PSRAM enabled

no

Upload speed

n/a

Description

The 1st below sketch works fine, but only with the default HSPI pin definitions.

#if CONFIG_IDF_TARGET_ESP32S3
    #define SD_CS    9 
    #define TFT_CS   18 
    #define TFT_DC   3 
    #define SPI_MOSI 15
    #define SPI_MISO 16
    #define SPI_CLK  17
    #define TFT_RST -1
#else
  #define SD_CS    15
  #define TFT_CS   33 
  #define TFT_DC   17 
  #define SPI_MISO 12 // default pin
  #define SPI_MOSI 13 // default pin
  #define SPI_CLK  14 // default pin
  #define TFT_RST -1
#endif
#define use_TFT true

#include <SPI.h>
#include <Adafruit_GFX.h>  // https://github.com/adafruit/Adafruit-GFX-Library 
#include <Adafruit_ST7796S_kbv.h> // https://github.com/prenticedavid/Adafruit_ST7796S_kbv1 

SPIClass MySPI(HSPI); // Declare an HSPI bus object (to use or BOTH TFT and SD-card)
Adafruit_ST7796S_kbv tft=Adafruit_ST7796S_kbv(&MySPI, TFT_DC, TFT_CS, TFT_RST);

#if (use_TFT)
  #define SerialD tft
#else
 #define SerialD Serial
#endif

void setup() {
  SerialD.begin();
  #if (use_TFT)
    tft.setRotation(3);
    tft.setTextSize(1); 
    tft.fillScreen(ST7796S_BLACK); tft.setCursor(0,0);
    tft.setTextColor(ST7796S_WHITE);
  #endif
} 

void loop() {
  SerialD.println("Loop");
  delay(1000);
}

The 2nd below sketch with new HSPI pin definitions compiles OK, but crashes at the line “SerialD.begin();” [aka tft.begin()]

#define SD_CS    15
#define TFT_CS   33 
#define TFT_DC   17 
#define SPI_MISO 12 // default pin
#define SPI_MOSI 13 // default pin
#define SPI_CLK  14 // default pin
#define TFT_RST -1

#define use_TFT true

#include <SPI.h>
#include <Adafruit_GFX.h>  // https://github.com/adafruit/Adafruit-GFX-Library 
#include <Adafruit_ST7796S_kbv.h> // https://github.com/prenticedavid/Adafruit_ST7796S_kbv1 

SPIClass *spi = NULL;
Adafruit_ST7796S_kbv tft=Adafruit_ST7796S_kbv(spi, TFT_DC, TFT_CS, TFT_RST);

#if (use_TFT)
  #define SerialD tft
#else
 #define SerialD Serial
#endif

void setup() {
  #if (use_TFT)
    spi = new SPIClass(HSPI);
    spi->begin(SPI_CLK, SPI_MISO, SPI_MOSI, TFT_CS);
  #endif
  SerialD.begin(); // crashes here
  #if (use_TFT)
    tft.setRotation(3);
    tft.setTextSize(1); 
    tft.fillScreen(ST7796S_BLACK); tft.setCursor(0,0);
    tft.setTextColor(ST7796S_WHITE);
  #endif
} 

void loop() {
  SerialD.println("Loop");
  delay(1000);
}

Is there any way to change the used HSPI pins outside of “setup()” and “loop()” so my above “#define SerialD tft” will work with “SerialD.print” etc?

Edit2:
@lbernstone - many thanks for below info! Interestingly the default "SPI" object "SPI.begin();" appears to use the pre-defined (SCK,MOSI, MISO,SS) variables, which on my board (nodeMCU-32S) are GPIO 18,23,19 & 5 which I understand to be the VSPI interface. But this still works fine.

The 3rd below sketch DOES work, and it a little more complex than sketch 1 above, but not too bad!

#define SD_CS    15
#define TFT_CS   33 
#define TFT_DC   17 
#define SPI_MISO 12 // default pin but can be changed
#define SPI_MOSI 13 // default pin but can be changed
#define SPI_CLK  14 // default pin but can be changed
#define TFT_RST -1

#define use_TFT true

#include <SPI.h>
#include <Adafruit_GFX.h>  // https://github.com/adafruit/Adafruit-GFX-Library 
#include <Adafruit_ST7796S_kbv.h> // https://github.com/prenticedavid/Adafruit_ST7796S_kbv1 

Adafruit_ST7796S_kbv *tft= NULL; 

#if (use_TFT)
  #define SerialD (*tft) // synonym for ->
#else
 #define SerialD Serial
#endif

void setup() {
  Serial.begin(115200);
  #if (use_TFT)
    // SPIClass *spi = new SPIClass(HSPI);  // not required as we can use the already existing "SPI"
    SPI.begin(SPI_CLK, SPI_MISO, SPI_MOSI, TFT_CS); // NB. SPI appears to use VSPI not HSPI, but this is ok.
    tft = new Adafruit_ST7796S_kbv(&SPI, TFT_DC, TFT_CS, TFT_RST); 
  #endif
  SerialD.begin(); 
  #if (use_TFT)
    tft->setRotation(3);
    tft->setTextSize(1); 
    tft->fillScreen(ST7796S_BLACK); tft->setCursor(0,0);
    tft->setTextColor(ST7796S_WHITE);
  #endif
} 

void loop() {
  SerialD.println("Loop");
  delay(1000);
}

Edit 3: re. ESP32-S3

Note that the ESP32-S3 has 2 available/user SPI controllers named:

  • SPIClass(HSPI); or SPIClass(1); = GP-SPI2 (or perhaps GP-SPI3)
  • SPIClass(FSPI); or SPIClass(0); = GP-SPI3 (or perhaps GP-SPI2)
    (each has slightly different capabilities).

Also note that although both above SPI controllers can be routed to any GPIO, for the fastest performance you can only use GPIOs 0-21 & 26-48 (which use the IO MUX to connect to the pins). Other pins use the GPIO MATRIX to connect to the pins and is slower.

Finally note that the SPI/TFT/SD (Arduino-ID) spi-frequency settings seem to work a bit differently on the ESP32-S3 (github.com/espressif/arduino-esp32 as at 16Jan24) compared with the ESP32-original. Specifically on the ESP32-original the following code works:

SPIClass *myspi = NULL;
Adafruit_ST7796S_kbv *tft = NULL;
myspi = new SPIClass(HSPI);
myspi->begin(SPI_CLK, SPI_MISO, SPI_MOSI, TFT_CS);
tft = new Adafruit_ST7796S_kbv(myspi, TFT_DC, TFT_CS, TFT_RST);
tft->begin();
boolean sd_OK = SD.begin(SD_CS, *myspi);

BUT on the ESP32-S3 the SD card gives the error message “sdCommand(): no token received” (I think because the SPI has ignored the default 10MHz setting for the SD card and is still using the default 40MHz setting of the TFT.)

To fix you need to specifically set the spi-frequency to the SD-cards default 10MHz frequency by changing the last couple of lines as follows:

#define SPI_freq 10000000 // 10MHz
tft->begin(SPI_freq);
boolean sd_OK =  SD.begin(SD_CS, MY_SPI, SPI_freq);

Sketch

See above

Debug Message

Sketch 2 crashes at the "SerialD.begin();"

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions