SPI 概述
SPI(Serial Peripheral Interface)协议,即串行外围设备接口,采用一主多从的全双工通信总线。被广泛使用在要求通讯速率较高的场合。
SPI 通信需要四条信号线:
- MISO: 主器件数据输入,从器件数据输出。
- MOSI:主器件数据输出,从器件数据输入。
- SCK: 时钟信号,由主设备控制发出。
- NSS(CS): 从设备选择信号,由主设备控制,当NSS为低电平则选中从器件。
三线 SPI 通信没有 “MIOS”,或 “MISO” 与 “MOSI” 共线。

ESP32 SPI
ESP32 共有 4 个 SPI,但是用户能够使用的只有 2 个,分为 VSPI 和 HSPI,注意这两个 SPI 默认的引脚中都有作为 Strapping 管脚的引脚,上电瞬间 Strapping 管脚电平不对,就没法正常启动。

使用注意:

官方例程更改 SPI 引脚:
#include <Arduino.h>
#include <SPI.h>// #define ALTERNATE_PINS#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
#endifstatic const int spiClk = 1000000;  // 1 MHz// SPI 对象指针
SPIClass * vspi = NULL;
SPIClass * hspi = NULL;void setup()
{// SPI 实例vspi = new SPIClass(VSPI);hspi = new SPIClass(HSPI);#ifndef ALTERNATE_PINS// 使用默认的引脚 SCLK = 18, MISO = 19, MOSI = 23, SS = 5vspi->begin();
#elsevspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);  // SCLK, MISO, MOSI, SS
#endif#ifndef ALTERNATE_PINS// 使用默认的引脚 SCLK = 14, MISO = 12, MOSI = 13, SS = 15hspi->begin();
#elsehspi->begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS);  //SCLK, MISO, MOSI, SS
#endif// 拉低 SSpinMode(vspi->pinSS(), OUTPUT);     //VSPI SSpinMode(hspi->pinSS(), OUTPUT);     //HSPI SS
}void loop()
{// 使用 SPI 总线spiCommand(vspi, 0b01010101);   // junk data to illustrate usagespiCommand(hspi, 0b11001100);delay(100);
}void spiCommand(SPIClass *spi, byte data)
{spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));digitalWrite(spi->pinSS(), LOW);    // 拉低 SS 传输数据spi->transfer(data);digitalWrite(spi->pinSS(), HIGH);   // 结束传输拉高spi->endTransaction();
}ESP32 作为主机通信:
#include <Arduino.h>
#include <SPI.h>const int csPin = 5;void setup()
{Serial.begin(115200);SPI.begin();pinMode(csPin, OUTPUT);
}void loop()
{digitalWrite(csPin, LOW);   // 拉低 CS 通信SPI.transfer(0x01);         // 发送一字节digitalWrite(csPin, HIGH);  // 拉高结束通信delay(1000);digitalWrite(csPin, LOW);byte result = SPI.transfer(0x00);   // 读取一字节digitalWrite(csPin, HIGH);Serial.println(result);
}参考:
ESP32的VSPI和HSPI-CSDN博客