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博客