ESP32 Multiple Buses - как использовать несколько различных устройств на одной из шин

ну они все на одни и теже miso/mosi/clk вешаются. Только чип-селект разный.

Выбор устройства чип-селектом (LOW).

SPI обычный же.

Карточку SD ты на каком esp пытаешься оживлять? На ESP32 базовом или на новых, esp32s2, s3? На ESP32 обычно подключают по MMC интерфейсу.

Правда, оно там сделано через IO_MUX т.е. номера пинов для MMC - фиксированные. Зато быстро, потому, что IO_MUX а не GPIO Matrix

class SPIClass spi_bus2(VSPI);
class SPIClass spi_bus3(HSPI);

Собственно, все. Вызывай методы, дергай CS чтобы выбрать нужное устройство. CS = GPIO любой.

Дальше - если тебе нужна большая скорость, то используй пины, которые по умолчанию роутятся через IO_MUX. Но если ты там за наносекунды не бьешся, то можешь на любых пинах это сделать. Будет чуть помедленнее.

begin() без параметров инициализирует SPI шину так, чтобы она работала через IO_MUX. Из-за этого есть т.н. дефолтные SPI пины. Но ты их использовать не обязан.

Собрал для пробы, пока не понимаю как SD привязать к vspi1, по умолчанию конечно и считывается и дальше всё работает и экран и 4-ре канала на vspi

Спойлер
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <FS.h>
#include "SD.h"
#include "SPIFFS.h"
#include <LittleFS.h>

#define SD_MISO 19
#define SD_MOSI 23
#define SD_SCK  18

#define  SD_CS          5
#define  AD9833_CS     15
#define  MCP41x1_CS    16  // Define chipselect pin for MCP41010 (CS for Volume)
#define  MCP41x1_ALC   17  // Define chipselect pin for MCP41010 (CS for ALC)

// Define ALTERNATE_PINS to use non-standard GPIO pins for SPI bus

#ifdef ALTERNATE_PINS
#define VSPI_MISO   2
#define VSPI_MOSI   4
#define VSPI_SCLK   0
#define VSPI_SS     33

#define HSPI_MISO   26
#define HSPI_MOSI   27
#define HSPI_SCLK   25
#define HSPI_SS     32
#else
#define VSPI_MISO   MISO
#define VSPI_MOSI   MOSI
#define VSPI_SCLK   SCK
#define VSPI_SS     SS

#define HSPI_MISO   12
#define HSPI_MOSI   13
#define HSPI_SCLK   14
#define HSPI_SS     15
#endif

#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define VSPI FSPI
#endif

static const int spiClk = 1000000; // 1 MHz

//uninitalised pointers to SPI objects
SPIClass * vspi1 = NULL;
SPIClass * vspi2 = NULL;
SPIClass * vspi3 = NULL;
SPIClass * vspi4 = NULL;
SPIClass * hspi = NULL;


#define TFT_GREY 0x5AEB

TFT_eSPI tft = TFT_eSPI();       // Invoke custom library

float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0;    // Saved H, M, S x & y multipliers
float sdeg = 0, mdeg = 0, hdeg = 0;
uint16_t osx = 120, osy = 120, omx = 120, omy = 120, ohx = 120, ohy = 120; // Saved H, M, S x & y coords
uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0;
uint32_t targetTime = 0;                    // for next 1 second timeout

static uint8_t conv2d(const char* p); // Forward declaration needed for IDE 1.6.x
uint8_t hh = conv2d(__TIME__), mm = conv2d(__TIME__ + 3), ss = conv2d(__TIME__ + 6); // Get H, M, S from compile time

bool initial = 1;


void spiCommand(SPIClass *spi, byte data, int spiclk) {
  //use it as you would the regular arduino SPI API
  spi->beginTransaction(SPISettings(spiclk, MSBFIRST, SPI_MODE0));
  digitalWrite(spi->pinSS(), LOW); //pull SS slow to prep other end for transfer
  spi->transfer(data);
  digitalWrite(spi->pinSS(), HIGH); //pull ss high to signify end of data transfer
  spi->endTransaction();
}

void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
  Serial.printf("Listing directory: %s\n", dirname);

  File root = fs.open(dirname);
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }
  if (!root.isDirectory()) {
    Serial.println("Not a directory");
    return;
  }

  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.print("  DIR : ");
      Serial.println(file.name());
      if (levels) {
        listDir(fs, file.path(), levels - 1);
      }
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}


void setup(void) {
  Serial.begin(115200);
  delay(3000);
  
  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  listDir(SD, "/", 0);

  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));

  vspi1 = new SPIClass(VSPI);
  vspi2 = new SPIClass(VSPI);
  vspi3 = new SPIClass(VSPI);
  vspi4 = new SPIClass(VSPI);

  vspi1->begin();
  vspi2->begin(SCK, MISO, MOSI, AD9833_CS);
  vspi3->begin(SCK, MISO, MOSI, MCP41x1_CS);
  vspi4->begin(SCK, MISO, MOSI, MCP41x1_ALC);

  pinMode(vspi1->pinSS(), OUTPUT);   // VSPI SS - SD_CS       (SD CARD)
  pinMode(vspi2->pinSS(), OUTPUT);   // VSPI SS - AD9833_CS   (AD9833)
  pinMode(vspi3->pinSS(), OUTPUT);   // VSPI SS - MCP41x1_CS  (Potenciometr)
  pinMode(vspi4->pinSS(), OUTPUT);   // VSPI SS - MCP41x1_ALS (Als)

  
  tft.init();
  tft.setRotation(0);

  //tft.fillScreen(TFT_BLACK);
  //tft.fillScreen(TFT_RED);
  //tft.fillScreen(TFT_GREEN);
  //tft.fillScreen(TFT_BLUE);
  //tft.fillScreen(TFT_BLACK);
  tft.fillScreen(TFT_GREY);

  tft.setTextColor(TFT_WHITE, TFT_GREY);  // Adding a background colour erases previous text automatically

  // Draw clock face
  tft.fillCircle(120, 120, 118, TFT_GREEN);
  tft.fillCircle(120, 120, 110, TFT_BLACK);

  // Draw 12 lines
  for (int i = 0; i < 360; i += 30) {
    sx = cos((i - 90) * 0.0174532925);
    sy = sin((i - 90) * 0.0174532925);
    x0 = sx * 114 + 120;
    yy0 = sy * 114 + 120;
    x1 = sx * 100 + 120;
    yy1 = sy * 100 + 120;

    tft.drawLine(x0, yy0, x1, yy1, TFT_GREEN);
  }

  // Draw 60 dots
  for (int i = 0; i < 360; i += 6) {
    sx = cos((i - 90) * 0.0174532925);
    sy = sin((i - 90) * 0.0174532925);
    x0 = sx * 102 + 120;
    yy0 = sy * 102 + 120;
    // Draw minute markers
    tft.drawPixel(x0, yy0, TFT_WHITE);

    // Draw main quadrant dots
    if (i == 0 || i == 180) tft.fillCircle(x0, yy0, 2, TFT_WHITE);
    if (i == 90 || i == 270) tft.fillCircle(x0, yy0, 2, TFT_WHITE);
  }

  tft.fillCircle(120, 121, 3, TFT_WHITE);

  // Draw text at position 120,260 using fonts 4
  // Only font numbers 2,4,6,7 are valid. Font 6 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : . - a p m
  // Font 7 is a 7 segment font and only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : .
  tft.drawCentreString("Time flies", 120, 260, 4);

  targetTime = millis() + 1000;
}

void loop() {

  spiCommand(vspi1, 0b01010101, 1000000); // junk data to illustrate usage
  delay(10);
  spiCommand(vspi2, 0b01110111, 1000000); // junk data to illustrate usage
  delay(10);
  spiCommand(vspi3, 0b00110011, 1000000); // junk data to illustrate usage
  delay(10);
  spiCommand(vspi4, 0b01000100, 1000000); // junk data to illustrate usage
  delay(10);

  if (targetTime < millis()) {
    targetTime += 1000;
    ss++;              // Advance second
    if (ss == 60) {
      ss = 0;
      mm++;            // Advance minute
      if (mm > 59) {
        mm = 0;
        hh++;          // Advance hour
        if (hh > 23) {
          hh = 0;
        }
      }
    }

    // Pre-compute hand degrees, x & y coords for a fast screen update
    sdeg = ss * 6;                // 0-59 -> 0-354
    mdeg = mm * 6 + sdeg * 0.01666667; // 0-59 -> 0-360 - includes seconds
    hdeg = hh * 30 + mdeg * 0.0833333; // 0-11 -> 0-360 - includes minutes and seconds
    hx = cos((hdeg - 90) * 0.0174532925);
    hy = sin((hdeg - 90) * 0.0174532925);
    mx = cos((mdeg - 90) * 0.0174532925);
    my = sin((mdeg - 90) * 0.0174532925);
    sx = cos((sdeg - 90) * 0.0174532925);
    sy = sin((sdeg - 90) * 0.0174532925);

    if (ss == 0 || initial) {
      initial = 0;
      // Erase hour and minute hand positions every minute
      tft.drawLine(ohx, ohy, 120, 121, TFT_BLACK);
      ohx = hx * 62 + 121;
      ohy = hy * 62 + 121;
      tft.drawLine(omx, omy, 120, 121, TFT_BLACK);
      omx = mx * 84 + 120;
      omy = my * 84 + 121;
    }

    // Redraw new hand positions, hour and minute hands not erased here to avoid flicker
    tft.drawLine(osx, osy, 120, 121, TFT_BLACK);
    osx = sx * 90 + 121;
    osy = sy * 90 + 121;
    tft.drawLine(osx, osy, 120, 121, TFT_RED);
    tft.drawLine(ohx, ohy, 120, 121, TFT_WHITE);
    tft.drawLine(omx, omy, 120, 121, TFT_WHITE);
    tft.drawLine(osx, osy, 120, 121, TFT_RED);

    tft.fillCircle(120, 121, 3, TFT_RED);
  }
}

static uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}

и вывод в сериал:

SD Card Type: SDHC
SD Card Size: 30145MB
Listing directory: /
  FILE: foo.txt  SIZE: 13
  FILE: std.db  SIZE: 11264
  FILE: vesta-new.db  SIZE: 24576
  FILE: zepper.db  SIZE: 24576
  FILE: fobos-new.db  SIZE: 24576
  FILE: standard.db  SIZE: 11264
  FILE: standard1.db  SIZE: 11264
  DIR : .Trash-1000
  DIR : System Volume Information
Total space: 30128MB
Used space: 0MB

копал копал но так и не нашёл как использовать с библиотекой TFT_eSPI

Ну поправь в библиотеке, там где инициализируется spi шина. Там наверняка по умолчанию VSPI используется. Исправь на HSPI да и все.

да, в файле настроек библиотеки надо было расскомментировать

#define USE_HSPI_PORT

ещё вчера всё решил, но что-то здесь не отметился )))

1 лайк

Кстати, VSPI доступен только на “родительской” esp32, на потомках с разными буквенными индексами вместо нее используется FSPI. А вот HSPI не доступен на esp32c3/c6/h2. Однако ничего не мешает инициализировать второй экземпляр FSPI (про третий и далее - не знаю, не пробовал). Пример можно глянуть тут - shMAX72xxMini/examples/TwoSPIAtOnce/TwoTickersForESP32/TwoTickersForESP32.ino at main · VAleSh-Soft/shMAX72xxMini · GitHub

у меня сейчас 4-ре экземпляра vspi трудятся, картинка на осциллографе - идеальная, пробовал каждому экземпляру свои установки частоты, работает без замечаний, дисплей у меня с тачскрином, попробую на hspi его в параллель с TFT посадить на отдельный экземпляр, хотя может быть в библиотеке и так это всё реализовано, надо пробовать

Кое-где есть еще и SPI3, который не назван как VSPI :slight_smile:

// Some low-end Espressif SoCs do not have VSPI. 
// ESP32S2 choose SPI3 as the name for 3rd SPI
//
#ifndef VSPI
#  ifdef SPI3
#    define VSPI SPI3
#  else
#    define VSPI FSPI
#  endif
#endif

Это откуда код?

Так-то VSPI там определяется безо всяких SPI3

esp32-hal-spi.h

#if CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32S3
#define FSPI 0
#define HSPI 1
#elif CONFIG_IDF_TARGET_ESP32S2
#define FSPI 1  //SPI 1 bus. ESP32S2: for external memory only (can use the same data lines but different SS)
#define HSPI 2  //SPI 2 bus. ESP32S2: external memory or device  - it can be matrixed to any pins
#define SPI2 2  // Another name for ESP32S2 SPI 2
#define SPI3 3  //SPI 3 bus. ESP32S2: device only - it can be matrixed to any pins
#elif CONFIG_IDF_TARGET_ESP32
#define FSPI 1  //SPI 1 bus attached to the flash (can use the same data lines but different SS)
#define HSPI 2  //SPI 2 bus normally mapped to pins 12 - 15, but can be matrixed to any pins
#define VSPI 3  //SPI 3 bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins
#endif

зырь острее. для s2 не определяется.
код мой, для удобства

Именно как VSPI не определяется, но SPI3 таки имеется ))

Ну, каждому - свое ))

ну вот о том и речь. На старших моделях надо использовать FSPI, на оригинальном ESP32 FSPI подключена к флешпамять и трогать ее тоже как бы нежелательно. С вышепреведенными #define я всегда просто пишу или HSPI или VSPI - будут всегда определены, вне зависимости от модели.

чтобы вот такое не городить:

// создаем два экземпляра SPI
#if CONFIG_IDF_TARGET_ESP32
SPIClass _spi0(VSPI); // VSPI доступен только на esp32
#else
SPIClass _spi0(FSPI);
#endif

#if CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
SPIClass _spi1(FSPI); // HSPI не доступен на esp32c3, esp32c6 и esp32h2, поэтому создаем второй FSPI-интерфейс
#else
SPIClass _spi1(HSPI);
#endif
1 лайк

в основном народ использует ESP32 DEV Module и ESP32S3, последний на подходе, посмотрим, что в нём не так


// This is the command sequence that rotates the ST7735 driver coordinate frame

  rotation = m % 4; // Limit the range of values to 0-3

  writecommand(TFT_MADCTL);
  switch (rotation) {
    case 0:
     if (tabcolor == INITR_BLACKTAB) {
       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
     } else if(tabcolor == INITR_GREENTAB2) {
       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
       colstart = 2;
       rowstart = 1;
     } else if(tabcolor == INITR_GREENTAB3) {
       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
       colstart = 2;
       rowstart = 3;
     } else if(tabcolor == INITR_GREENTAB128) {
       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_COLOR_ORDER);
       colstart = 0;
       rowstart = 32;
     } else if(tabcolor == INITR_GREENTAB160x80) {
       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_COLOR_ORDER);
       colstart = 26;
       rowstart = 1;
	 } else if(tabcolor == INITR_GREENTAB096) {
   	   writedata(!TFT_MAD_MV |!TFT_MAD_COLOR_ORDER | !TFT_MAD_MX | TFT_MAD_MY );		 // 0.96" R0 Разъём со стороны левой руки
       colstart = 24;
       rowstart = 0;
     } else if(tabcolor == INITR_REDTAB160x80) {
       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_COLOR_ORDER);
       colstart = 24;
       rowstart = 0;
     } else if(tabcolor == INITB) {
       writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER);
     } else {
       writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
     }
      _width  = _init_width;
      _height = _init_height;
      break;
    case 1:
     if (tabcolor == INITR_BLACKTAB) {
       writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
     } else if(tabcolor == INITR_GREENTAB2) {
       writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
       colstart = 1;
       rowstart = 2;
     } else if(tabcolor == INITR_GREENTAB3) {
       writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
       colstart = 3;
       rowstart = 2;
     } else if(tabcolor == INITR_GREENTAB128) {
       writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
       colstart = 32;
       rowstart = 0;
     } else if(tabcolor == INITR_GREENTAB160x80) {
       writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
       colstart = 1;
       rowstart = 26;
	 } else if(tabcolor == INITR_GREENTAB096) {
   	// writedata(!TFT_MAD_MV |!TFT_MAD_COLOR_ORDER | !TFT_MAD_MX | TFT_MAD_MY );	 // 0.96" R0 Разъём со стороны левой руки
	   writedata(TFT_MAD_MV |!TFT_MAD_COLOR_ORDER | TFT_MAD_MX | TFT_MAD_MY );		 // 0.96" R1 Разъём снизу
	// writedata(!TFT_MAD_MV |!TFT_MAD_COLOR_ORDER | TFT_MAD_MX | !TFT_MAD_MY );	 // 0.96" R2 Разъём со стороны правой руки
 	// writedata(TFT_MAD_MV |!TFT_MAD_COLOR_ORDER | !TFT_MAD_MX | !TFT_MAD_MY );	 // 0.96" R3 Разъём сверху	
       colstart = 0;
       rowstart = 24;
     } else if(tabcolor == INITR_REDTAB160x80) {
       writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
       colstart = 0;
       rowstart = 24;
     } else if(tabcolor == INITB) {
       writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
     } else {
       writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
     }
      _width  = _init_height;
      _height = _init_width;
      break;
    case 2:
     if (tabcolor == INITR_BLACKTAB) {
       writedata(TFT_MAD_COLOR_ORDER);
     } else if(tabcolor == INITR_GREENTAB2) {
       writedata(TFT_MAD_COLOR_ORDER);
       colstart = 2;
       rowstart = 1;
     } else if(tabcolor == INITR_GREENTAB3) {
       writedata(TFT_MAD_COLOR_ORDER);
       colstart = 2;
       rowstart = 1;
     } else if(tabcolor == INITR_GREENTAB128) {
       writedata(TFT_MAD_COLOR_ORDER);
       colstart = 0;
       rowstart = 0;
     } else if(tabcolor == INITR_GREENTAB160x80) {
       writedata(TFT_MAD_COLOR_ORDER);
       colstart = 26;
       rowstart = 1;
	 } else if(tabcolor == INITR_GREENTAB096) {
	   writedata(!TFT_MAD_MV |!TFT_MAD_COLOR_ORDER | TFT_MAD_MX | !TFT_MAD_MY );		 // 0.96" R2 Разъём со стороны правой руки
       colstart = 24;
       rowstart = 0;
     } else if(tabcolor == INITR_REDTAB160x80) {
       writedata(TFT_MAD_COLOR_ORDER);
       colstart = 24;
       rowstart = 0;
     } else if(tabcolor == INITB) {
       writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER);
     } else {
       writedata(TFT_MAD_COLOR_ORDER);
     }
      _width  = _init_width;
      _height = _init_height;
      break;
    case 3:
     if (tabcolor == INITR_BLACKTAB) {
       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
     } else if(tabcolor == INITR_GREENTAB2) {
       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
       colstart = 1;
       rowstart = 2;
     } else if(tabcolor == INITR_GREENTAB3) {
       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
       colstart = 1;
       rowstart = 2;
     } else if(tabcolor == INITR_GREENTAB128) {
       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
       colstart = 0;
       rowstart = 0;
     } else if(tabcolor == INITR_GREENTAB160x80) {
       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
       colstart = 1;
       rowstart = 26;
	 } else if(tabcolor == INITR_GREENTAB096) {
 	   writedata(TFT_MAD_MV |!TFT_MAD_COLOR_ORDER | !TFT_MAD_MX | !TFT_MAD_MY );		 // 0.96" R3 Разъём сверху
       colstart = 0;
	   rowstart = 24;
     } else if(tabcolor == INITR_REDTAB160x80) {
       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
       colstart = 0;
       rowstart = 24;
     } else if(tabcolor == INITB) {
       writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
     } else {
       writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER);
     }
      _width  = _init_height;
      _height = _init_width;
      break;
  }

мне другое интересно, ESP32C3, в версии ядра <= 2.0.13 мой проект компилируется нормально и дисплей работает, в версии > 2.0.15 дисплей не работает, склоняюсь, что что-то с SPI не так, что-то поменяли в ядре, хотелось бы знать что…

Как бы и не проблема ни разу

https://docs.espressif.com/projects/arduino-esp32/en/latest/migration_guides/2.x_to_3.0.html

Так у меня еще на 2-й версии началось, надо поискать в чём косяк или забить и компилировать на версии не более 2.0.13
Есть свободная ESP32C3 залью и посмотрю осциллографом, что у нас там на SPI