El Bus SPI es un protocolo de comunicación síncrona utilizado para transferir datos entre un microcontrolador y otros dispositivos, como sensores, pantallas, memorias y periféricos.
A diferencia de otros protocolos, el bus SPI utiliza múltiples líneas de comunicación, permitiendo una alta velocidad de transferencia y una flexibilidad excepcional.
El puerto SPI es principalmente usado por alta capacidad de transmitir datos. Por este motivo lo encontraréis en dispositivos que requieran gran cantidad de datos por segundo, como dispositivos de almacenamiento (memorias, SD) y pantallas.
Si no sabes lo que es el bus SPI o necesitas más ayuda consulta estas entradas:
El bus SPI en el ESP32
El ESP32, ESP32-S2 y ESP32-S3 tienen cuatro controladores SPI, mientras que el ESP32-C3 tiene tres.
Su uso en el entorno de Arduino es muy similar al que encontraríamos en un Arduino convencional. Las funcionalidades están definidas en la biblioteca SPI.h
, bajo el objeto SPIClass
.
void setup() {
// Inicializar comunicación SPI
SPI.begin();
}
El mayor lio lo vamos a tener con los pines y sus denominaciones. Pero, tenemos la ventaja de que en el caso del ESP32, podemos reasignar los pines.
Si miramos el ESP32, ESP32-S2 y ESP32-S3 tienen cuatro controladores, llamados SPI0, SPI1, SPI2 y SPI3.
- SPI0 y SPI1 se usan para la comunicación con la memoria Flash. Así que no se tocan.
- SPI2 y SPI3 quedan libres para el usuario.
Esto deja dos controladores SPI libres para poderlos usar (uno en el ESP32-C3).
Por otro lado, al SPI2 se le denomina HSPI y al SPI3 se le denomina VSPI. ¿Qué significan la H y la V? Absolutamente nada, son iguales en características.
De hecho buscad en internet, que hay preguntas y respuestas graciosas sobre que significa H y V (me gusta la de Henry y Victor).
En el caso del ESP32
SPI | MOSI | MISO | SCK | CS |
---|---|---|---|---|
HSPI | GPIO 13 | GPIO 12 | GPIO 14 | GPIO 15 |
VSPI | GPIO 23 | GPIO 19 | GPIO 18 | GPIO 5 |
En el caso del ESP32-S3
SPI | MOSI | MISO | SCK | CS |
---|---|---|---|---|
HSPI | GPIO 35 | GPIO 37 | GPIO 37 | GPIO - |
VSPI | GPIO 11 | GPIO 13 | GPIO 12 | GPIO 10 |
Pero lo mismo, yo me encargaría de definirlos a manopla
SPIClass vspi = SPIClass(VSPI);
MySPI.begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);
Las constantes VSPI y HSPI son integer que están definidas en el Core de Arduino. Son diferentes para cada variante del ESP32, así que usad la constante en lugar de un número.
Modelo | HSPI | VSPI |
---|---|---|
ESP32 | 1 | 3 |
ESP32-S2 | 2 | 3 |
ESP32-S3 | 2 | 3 |
ESP32-C3 | 1 | 3 |
Cómo usar SPI en ESP32 en el entorno de Arduino
El uso del bus I2C en el ESP32 en el entorno de Arduino es muy similar a hacerlo en un Arduino convencional. Ahí van unos ejemplos.
Enviar Datos
byte dataToSend = 0xAA;
byte receivedData;
digitalWrite(SS, LOW); // Bajar línea CS/SS para seleccionar el dispositivo
receivedData = SPI.transfer(dataToSend); // Enviar y recibir datos
digitalWrite(SS, HIGH); // Subir línea CS/SS para finalizar la comunicación
Usando múltiples SPI en el ESP32
Como hemos dicho, el ESP32, ESP32-S2 y ESP32-S3 tienen dos controladores de I2C, por lo que podemos crear dos redes de dispositivos simultáneas.
#include <SPI.h>
#define HSPI 2 // 2 para S2 y S3, 1 para S1
#define VSPI 3
// reemplazar por los pines que queráis usar
const int HSPI_MISO = 0;
const int HSPI_MOSI = 0;
const int HSPI_SCLK = 0;
const int HSPI_SS = 0;
const int VSPI_MISO = 0;
const int VSPI_MOSI = 0;
const int VSPI_SCLK = 0;
const int VSPI_SS = 0;
SPIClass vspi = SPIClass(VSPI);
SPIClass hspi = SPIClass(HSPI);
void setup()
{
vspi.begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);
hspi.begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS);
}
void loop()
{
delay(1000); // do nothing
}