Fundamentos · 13 min de lectura

¿Qué es SPI? Pines MOSI, MISO, SCK y CS en Arduino, paso a paso

Qué es SPI y cómo funciona: pines MOSI, MISO, SCK y CS, modos y velocidad, varios dispositivos, pines de Uno, Mega, ESP32 y Pico, y el choque entre SD y RFID.

SPI (Serial Peripheral Interface, interfaz periférica serie) es un método de comunicación que permite a un microcontrolador intercambiar datos muy rápido con dispositivos como tarjetas SD, lectores RFID, pantallas TFT a color o módulos inalámbricos a través de cuatro cables. Hay una línea de reloj (SCK), dos líneas separadas para los datos en cada sentido (MOSI y MISO) y una línea CS que elige con qué dispositivo se habla. Como puede ser decenas de veces más rápido que I2C, es el bus preferido por los módulos que mueven muchos datos.

En este artículo aprenderás cómo funciona SPI, los nombres de los pines y la nueva nomenclatura, los cuatro modos SPI, los límites de velocidad, los pines de Arduino Uno, Mega, ESP32 (VSPI y HSPI) y Raspberry Pi Pico, cómo conectar varios dispositivos al mismo bus y por qué una tarjeta SD y un lector RFID RC522 dan problemas juntos. En la última sección comparamos SPI con I2C y UART.

¿Qué es SPI y cómo funciona?

En SPI siempre hay un controlador (antes llamado maestro) y uno o más periféricos (antes llamados esclavos). Solo el controlador genera el reloj; es decir, el Arduino inicia la conversación, fija la velocidad y la termina. En cada pulso de reloj el controlador envía un bit por MOSI y, al mismo tiempo, el periférico devuelve un bit por MISO. Los registros de desplazamiento de los dos lados forman una especie de anillo: tras 8 pulsos, el byte del controlador ha pasado al periférico y el del periférico al controlador. Por eso SPI es full duplex: leer y escribir ocurre a la vez.

LíneaNombre antiguoNombre nuevoSentidoFunción
SCK / SCLKSerial ClockSCKControlador → periféricoSeñal de reloj; en cada pulso viaja un bit
MOSIMaster Out Slave InCOPI / SDOControlador → periféricoDatos del Arduino al módulo
MISOMaster In Slave OutCIPO / SDIPeriférico → controladorDatos del módulo de vuelta al Arduino
CS / SSSlave SelectCS (Chip Select)Controlador → periféricoMientras está en LOW, ese módulo escucha; cada dispositivo tiene su propio CS

Las serigrafías de los módulos no siempre coinciden y esa es la mayor fuente de confusión. En el módulo RFID RC522 la línea CS se llama SDA (no tiene nada que ver con el SDA de I2C), en el nRF24L01 CSN, en el MCP3008 CS/SHDN, y en algunas pantallas verás nombres como DIN (MOSI), CLK (SCK) y DOUT (MISO). La regla es sencilla: la entrada de datos (DIN, SDI, MOSI) va al MOSI del Arduino y la salida de datos (DOUT, SDO, MISO) va al MISO del Arduino.

  1. El controlador pone en LOW la línea CS del dispositivo con el que quiere hablar. Todos los demás dejan su CS en HIGH y liberan la línea MISO.
  2. El controlador empieza a generar pulsos de reloj en SCK.
  3. En cada pulso sale un bit por MOSI y entra un bit por MISO. El orden suele ser primero el bit más significativo (MSB first).
  4. Cuando se han transferido los bytes necesarios (comando, dirección, datos), el controlador vuelve a poner CS en HIGH y el dispositivo completa la operación.

Modos SPI: CPOL y CPHA

SPI no tiene un estándar único; los dispositivos se diferencian en el nivel en que reposa el reloj (CPOL, polaridad del reloj) y en el flanco del reloj en el que se leen los datos (CPHA, fase del reloj). Las cuatro combinaciones de estos dos ajustes forman los cuatro modos SPI. Si el controlador y el dispositivo no están en el mismo modo, los datos se desplazan un bit y lees valores sin sentido. Por suerte, la gran mayoría de los módulos usa el modo 0.

ModoCPOLCPHAReloj en reposoFlanco de lecturaDispositivos de ejemplo
SPI_MODE000LOWSubidaTarjeta SD, RC522, nRF24L01, MAX7219, MCP3008, 74HC595
SPI_MODE101LOWBajadaAlgunos ADC e integrados de control
SPI_MODE210HIGHBajadaPoco habitual
SPI_MODE311HIGHSubidaAcelerómetro ADXL345, algunas pantallas ST7789 sin pin CS
Si un módulo te devuelve siempre 0xFF, 0x00 o valores absurdos distintos cada vez, comprueba primero en la hoja de datos el modo SPI y la velocidad máxima de reloj. Bajar la velocidad a 1 MHz y volver a probar muestra enseguida si el problema es el cableado o la configuración.

Velocidad SPI y longitud de los cables

En SPI la velocidad la fija el controlador y el límite suele ponerlo el propio dispositivo. El Arduino Uno puede llegar a 8 MHz, la mitad de su reloj de 16 MHz; el valor por defecto de la librería SPI es 4 MHz. El ESP32 puede generar hasta 80 MHz en sus pines SPI propios (IO_MUX), y el límite baja si la señal se lleva a otros pines a través de la matriz GPIO. La Raspberry Pi Pico llega a unos 62,5 MHz con un reloj de sistema de 125 MHz. Las señales SPI rápidas necesitan cables cortos: con una protoboard y cables dupont de 10–20 cm, unos pocos MHz no dan problemas; a partir de 20–30 MHz mantén los cables cortos y, si puedes, usa conexiones soldadas. Varios metros de cable no son adecuados para SPI.

DispositivoFunciónReloj SPI máximo (hoja de datos)Modo SPI
Tarjeta microSDRegistro de datos400 kHz al iniciar, luego hasta 25 MHzModo 0
RC522 (MFRC522)Lector RFID10 MHzModo 0
nRF24L01Radio de 2,4 GHz10 MHzModo 0
MAX7219Matriz LED / 7 segmentos10 MHzModo 0
MCP3008ADC de 8 canales y 10 bits3,6 MHz a 5 V, 1,35 MHz a 2,7 VModo 0 o 3
ILI9341TFT a color de 2,4–3,2 pulgadas10 MHz en escritura (en la práctica se usa mucho más rápido)Modo 0

Pines SPI: Arduino Uno, Mega, ESP32 y Raspberry Pi Pico

LíneaArduino Uno / NanoArduino MegaESP32 VSPI (por defecto)ESP32 HSPIRaspberry Pi Pico SPI0
SCKD13D52GPIO 18GPIO 14GP18
MOSID11D51GPIO 23GPIO 13GP19 (TX)
MISOD12D50GPIO 19GPIO 12GP16 (RX)
CS (por defecto)D10D53GPIO 5GPIO 15GP17
Nivel lógico5 V5 V3,3 V3,3 V3,3 V

En el Uno las mismas líneas SPI también están en el conector ICSP de 6 pines del borde de la placa; en placas como Leonardo y Micro, SPI solo está en el ICSP. Para CS no es obligatorio usar D10: sirve cualquier pin digital. Pero en el Uno no dejes D10 como entrada: si el hardware SPI lee LOW en D10 mientras es entrada, sale del modo controlador. SPI.begin() configura este pin como salida automáticamente, y no deberías convertirlo en entrada para otra tarea. En el ESP32 el objeto SPI de Arduino usa VSPI por defecto; gracias a la matriz GPIO también puedes mover SPI a casi cualquier pin. En la Pico, SPI0 y SPI1 pueden asignarse a varios grupos de pines (p. ej. GP10, GP11, GP12 para SPI1); tienes los detalles en la herramienta Pinout.

El RC522, el nRF24L01 y las propias tarjetas SD son dispositivos de 3,3 V. Conectarlos directamente a las señales de 5 V del Uno puede dañarlos con el tiempo. La mayoría de los módulos SD ya hechos llevan un conversor de nivel; alimenta el RC522 y el nRF24L01 desde el pin 3V3 y plantéate usar un conversor de nivel lógico en las líneas de señal. El ESP32 y la Pico ya funcionan a 3,3 V, así que son compatibles directamente con estos dispositivos.

La librería SPI de Arduino: funciones básicas

Función¿Qué hace?
SPI.begin()Inicia el hardware SPI; pone como salidas los pines SCK, MOSI y SS.
SPISettings(velocidad, MSBFIRST, SPI_MODE0)Guarda en un objeto la velocidad, el orden de bits y el modo de un dispositivo.
SPI.beginTransaction(ajustes)Aplica los ajustes y reserva el bus para ese dispositivo; hace seguro el paso entre dispositivos con ajustes distintos.
SPI.transfer(byte)Envía un byte y devuelve el byte recibido al mismo tiempo.
SPI.transfer16(valor)Envía y recibe un valor de 16 bits de una vez.
SPI.transfer(búfer, longitud)Envía un array; los bytes recibidos sobrescriben el mismo array.
SPI.endTransaction()Libera el bus; se llama después de poner CS en HIGH.

Primer ejemplo: enviar datos a un 74HC595 por SPI

La forma más fácil de entender SPI es con un registro de desplazamiento 74HC595, porque el 595 es en realidad el periférico SPI más simple, uno sin MISO. El pin MOSI del Arduino va a la entrada DS del 595, SCK a SH_CP y D10 a ST_CP, que hace de latch. A diferencia de la función shiftOut(), el SPI por hardware envía el byte en pocos microsegundos:

C++ (Arduino IDE)
1// Donanım SPI ile 74HC595: 8 LED'i iki kabloyla sürmek / 74HC595 over hardware SPI: 8 LEDs from two data wires
2// D11 (MOSI) -> DS (14), D13 (SCK) -> SH_CP (11), D10 -> ST_CP / latch (12)
3#include <SPI.h>
4
5const int LATCH_PIN = 10;     // 595'te CS gibi davranır / acts like CS on the 595
6
7void write595(byte value) {
8  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));  // 4 MHz, mod 0 / 4 MHz, mode 0
9  digitalWrite(LATCH_PIN, LOW);
10  SPI.transfer(value);                 // 8 biti gönder / shift out 8 bits
11  digitalWrite(LATCH_PIN, HIGH);       // yükselen kenarda çıkışlara aktar / latch on the rising edge
12  SPI.endTransaction();
13}
14
15void setup() {
16  pinMode(LATCH_PIN, OUTPUT);
17  digitalWrite(LATCH_PIN, HIGH);
18  SPI.begin();
19}
20
21void loop() {
22  for (int i = 0; i < 8; i++) {        // yürüyen ışık / running light
23    write595(1 << i);
24    delay(100);
25  }
26}

Leer datos por SPI: el ADC MCP3008

Para ver la comunicación full duplex usaremos el MCP3008. Este integrado añade al Arduino 8 entradas analógicas más de 10 bits; es una buena alternativa al ADC poco lineal del ESP32 o a las solo 3 entradas analógicas de la Pico. Explicamos los fundamentos de la lectura analógica en el artículo ¿Qué es un ADC?. Conexión: CLK → D13, DOUT → D12, DIN → D11, CS → D10, VDD y VREF → 5V, AGND y DGND → GND.

C++ (Arduino IDE)
1// MCP3008 (8 kanal, 10 bit ADC) okuma / Reading an MCP3008 (8-channel 10-bit ADC)
2// D13 -> CLK, D12 <- DOUT, D11 -> DIN, D10 -> CS/SHDN
3#include <SPI.h>
4
5const int CS_PIN = 10;
6SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0);   // 1 MHz, mod 0 / 1 MHz, mode 0
7
8int readMCP3008(byte channel) {
9  SPI.beginTransaction(mcpSettings);
10  digitalWrite(CS_PIN, LOW);                   // cihazı seç / select the chip
11  SPI.transfer(0x01);                          // başlangıç biti / start bit
12  byte high = SPI.transfer(0x80 | (channel << 4));   // tek uçlu + kanal / single-ended + channel
13  byte low = SPI.transfer(0x00);               // kalan 8 bit / remaining 8 bits
14  digitalWrite(CS_PIN, HIGH);                  // seçimi bırak / release the chip
15  SPI.endTransaction();
16  return ((high & 0x03) << 8) | low;           // 10 bitlik sonuç / 10-bit result
17}
18
19void setup() {
20  Serial.begin(9600);
21  pinMode(CS_PIN, OUTPUT);
22  digitalWrite(CS_PIN, HIGH);                  // başta seçili değil / not selected at start
23  SPI.begin();
24}
25
26void loop() {
27  int raw = readMCP3008(0);
28  float volts = raw * 5.0 / 1023.0;
29  Serial.print("CH0: ");
30  Serial.print(raw);
31  Serial.print("  ");
32  Serial.print(volts, 2);
33  Serial.println(" V");
34  delay(500);
35}

Aquí enviamos tres bytes y recibimos tres bytes a la vez. El primer byte (0x01) es solo el bit de inicio; en el segundo van el modo de entrada simple y el número de canal, mientras el MCP3008 devuelve los 2 bits altos del resultado. El tercer byte es 0x00; su contenido da igual, solo se envía para generar pulsos de reloj y recibir los 8 bits restantes del resultado. En SPI, "leer" siempre significa enviar algo. El resultado está entre 0 y 1023 y se convierte a voltios respecto a VREF (aquí 5 V).

Varios dispositivos SPI: líneas CS separadas

La mayor diferencia de SPI con I2C es que no usa direcciones. Los dispositivos comparten las líneas SCK, MOSI y MISO, y cada uno recibe su propio cable CS desde el Arduino. Solo escucha el dispositivo cuyo CS está en LOW, y solo ese escribe datos en MISO. Tres dispositivos necesitan 3 + 3 = 6 cables, cinco dispositivos 3 + 5 = 8; el número de pines crece con el de dispositivos. Algunos integrados como el 74HC595 y el MAX7219 pueden encadenarse (daisy chain): la salida de uno va a la entrada del siguiente y todos se controlan con un solo CS.

  • Solo un CS en LOW a la vez. Si se seleccionan dos dispositivos juntos, chocan en la línea MISO y lees datos corruptos de los dos.
  • En setup(), pon primero todos los pines CS como salida y en HIGH, y después inicia las librerías. Un pin CS al aire puede verse en LOW al azar y ocupar el bus.
  • Usa beginTransaction para cada dispositivo. Una tarjeta SD puede querer 25 MHz y un MCP3008 1 MHz; las transacciones aplican la velocidad y el modo correctos en cada cambio.
  • Si usas SPI dentro de interrupciones, avisa a la librería con SPI.usingInterrupt() o no hagas operaciones SPI dentro de la interrupción.
  • Una pull-up de 10 kΩ en la línea CS de cada dispositivo evita que los dispositivos se seleccionen solos mientras el Arduino arranca o se reinicia.

Tarjeta SD y RFID en el mismo bus: ¿por qué no funciona?

Una pregunta clásica de los foros de Arduino: el RFID RC522 funciona solo, el módulo de tarjeta SD funciona solo, pero al conectarlos al mismo bus SPI uno de ellos o los dos se callan. Aunque los pines CS estén bien en el software, el problema suele estar en el hardware. Muchos módulos SD baratos llevan un búfer 74LVC125 que convierte las señales de 5 V a 3,3 V, y el canal de ese integrado que maneja la línea MISO está siempre activado. Así que, aunque el CS de la tarjeta SD esté en HIGH, el módulo no suelta MISO; cuando el RC522 intenta responder, dos salidas se pelean por la línea.

  • Elige el módulo adecuado: los módulos que ponen MISO en alta impedancia cuando CS está en HIGH comparten el bus sin problemas. Puedes saber si un módulo libera la línea tirando de MISO con 10 kΩ primero a GND y luego a 5 V, con CS en HIGH, y midiendo con el multímetro.
  • Conecta el pin de habilitación del búfer a CS: si sabes soldar, separar de GND el pin OE del canal MISO del 74LVC125 y llevarlo a la línea CS del módulo soluciona el problema de raíz.
  • Pon una resistencia en serie en MISO: una resistencia de unos 1 kΩ en serie con la salida MISO del módulo SD permite que el RC522 imponga su señal. Es un apaño fácil, pero limita la velocidad.
  • Usa un bus SPI separado: en el ESP32, si conectas la tarjeta SD a VSPI y el RC522 a HSPI, los dos dispositivos nunca coinciden. El Uno no tiene un segundo SPI por hardware, así que allí no existe esta opción.
  • Cuida el orden de arranque: pon primero todos los CS en HIGH, luego llama a SPI.begin() y después a SD.begin() y PCD_Init(). El ejemplo de abajo sigue este orden.
C++ (Arduino IDE)
1// Aynı SPI hattında SD kart ve RC522 RFID / SD card and RC522 RFID on the same SPI bus
2// Ortak / shared: D11 MOSI, D12 MISO, D13 SCK. CS: SD -> D4, RC522 SDA(SS) -> D10, RC522 RST -> D9
3#include <SPI.h>
4#include <SD.h>
5#include <MFRC522.h>
6
7const int SD_CS = 4;
8const int RFID_CS = 10;
9const int RFID_RST = 9;
10
11MFRC522 rfid(RFID_CS, RFID_RST);
12
13void setup() {
14  Serial.begin(9600);
15  // Önce TÜM CS pinlerini HIGH yap: hiçbir cihaz hattı meşgul etmesin
16  // First drive ALL CS pins HIGH so no device grabs the bus
17  pinMode(SD_CS, OUTPUT);
18  digitalWrite(SD_CS, HIGH);
19  pinMode(RFID_CS, OUTPUT);
20  digitalWrite(RFID_CS, HIGH);
21
22  SPI.begin();
23  if (!SD.begin(SD_CS)) {
24    Serial.println(F("SD bulunamadi / SD not found"));
25  }
26  rfid.PCD_Init();
27  Serial.println(F("Karti okut / Scan a card"));
28}
29
30void loop() {
31  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
32
33  String uid = "";
34  for (byte i = 0; i < rfid.uid.size; i++) {
35    if (rfid.uid.uidByte[i] < 0x10) uid += "0";
36    uid += String(rfid.uid.uidByte[i], HEX);
37  }
38  rfid.PICC_HaltA();
39
40  File f = SD.open("kartlar.txt", FILE_WRITE);   // kütüphane CS'yi kendisi yönetir / the library handles CS itself
41  if (f) {
42    f.print(millis());
43    f.print(";");
44    f.println(uid);
45    f.close();
46    Serial.println("Kaydedildi / Saved: " + uid);
47  } else {
48    Serial.println(F("Dosya acilamadi / File open failed"));
49  }
50}

En este código la librería SD y la librería MFRC522 ponen sus propios pines CS en LOW y HIGH; lo único que tienes que hacer es dejar los dos en HIGH al principio y asegurarte de que el hardware comparte MISO correctamente. El código escribe el UID de cada tarjeta leída, junto con una marca de tiempo, en el archivo kartlar.txt. En el Uno estas dos librerías usan juntas cerca de la mitad de la RAM; la macro F() libera espacio guardando los textos fijos en la flash.

VSPI y HSPI en el ESP32: dos buses SPI separados

El ESP32 tiene cuatro unidades SPI; SPI0 y SPI1 están reservadas para la flash interna, así que te quedan VSPI (SPI3) y HSPI (SPI2). Usar las dos es la forma más limpia de separar dispositivos con velocidades y modos muy distintos o de librarte del choque en MISO que hemos visto. En el núcleo de Arduino creas un objeto SPIClass para el segundo bus y le das sus pines con begin(). El código de abajo usa la tarjeta SD en el VSPI por defecto y el MCP3008 en HSPI, y añade cada segundo una medida a un archivo CSV:

C++ (Arduino IDE)
1// ESP32: iki ayrı SPI hattı / two separate SPI buses
2// VSPI (varsayılan SPI / default SPI): SD kart / SD card -> SCK 18, MISO 19, MOSI 23, CS 5
3// HSPI: MCP3008 -> SCK 14, MISO 12, MOSI 13, CS 15
4#include <SPI.h>
5#include <SD.h>
6
7const int SD_CS = 5;
8const int ADC_CS = 15;
9
10SPIClass hspi(HSPI);                              // ikinci donanım SPI / second hardware SPI
11SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0);
12
13int readMCP3008(byte channel) {
14  hspi.beginTransaction(mcpSettings);
15  digitalWrite(ADC_CS, LOW);
16  hspi.transfer(0x01);
17  byte high = hspi.transfer(0x80 | (channel << 4));
18  byte low = hspi.transfer(0x00);
19  digitalWrite(ADC_CS, HIGH);
20  hspi.endTransaction();
21  return ((high & 0x03) << 8) | low;
22}
23
24void setup() {
25  Serial.begin(115200);
26  pinMode(ADC_CS, OUTPUT);
27  digitalWrite(ADC_CS, HIGH);
28  hspi.begin(14, 12, 13, ADC_CS);                 // SCK, MISO, MOSI, SS
29
30  if (!SD.begin(SD_CS)) {                         // SD varsayılan VSPI'yi kullanır / SD uses the default VSPI
31    Serial.println("SD bulunamadi / SD not found");
32  }
33}
34
35void loop() {
36  int raw = readMCP3008(0);
37  File f = SD.open("/olcum.csv", FILE_APPEND);    // ekle kipinde aç / open in append mode
38  if (f) {
39    f.printf("%lu,%d\n", millis(), raw);
40    f.close();
41  }
42  Serial.printf("CH0: %d\n", raw);
43  delay(1000);
44}
GPIO 12, el pin MISO de HSPI, es uno de los pines de arranque (strapping) del ESP32: si está en HIGH al arrancar, la placa cree que la flash es de 1,8 V y no arranca. No conectes a HSPI módulos con resistencia pull-up en MISO (como la mayoría de los módulos SD), o lleva MISO a otro pin. Por eso en este ejemplo la tarjeta SD está en VSPI.

SPI con la Raspberry Pi Pico (MicroPython)

La Pico tiene dos unidades SPI por hardware (SPI0 y SPI1), que en MicroPython se usan con la clase machine.SPI. Los parámetros polarity y phase corresponden a CPOL y CPHA; si los dos valen 0, es el modo 0. El CS lo manejas tú como un pin de salida normal. La función write_readinto() es la que mejor muestra el carácter full duplex de SPI: mientras envía un array, escribe los bytes que llegan en otro. Leamos el mismo MCP3008, esta vez alimentado a 3,3 V:

MicroPython
1# Raspberry Pi Pico: SPI0 ile MCP3008 okuma / reading an MCP3008 on SPI0
2# GP18 -> CLK, GP19 -> DIN (MOSI), GP16 <- DOUT (MISO), GP17 -> CS. MCP3008 VDD ve VREF 3V3 / VDD and VREF on 3V3
3from machine import Pin, SPI
4import time
5
6spi = SPI(0, baudrate=1_000_000, polarity=0, phase=0,   # mod 0 / mode 0
7          sck=Pin(18), mosi=Pin(19), miso=Pin(16))
8cs = Pin(17, Pin.OUT, value=1)                          # başta seçili değil / not selected at start
9
10def read_mcp3008(channel):
11    tx = bytearray([0x01, 0x80 | (channel << 4), 0x00])
12    rx = bytearray(3)
13    cs.value(0)                                          # cihazı seç / select the chip
14    spi.write_readinto(tx, rx)                           # aynı anda gönder ve al / send and receive at once
15    cs.value(1)
16    return ((rx[1] & 0x03) << 8) | rx[2]
17
18while True:
19    raw = read_mcp3008(0)
20    print("CH0:", raw, "{:.2f} V".format(raw * 3.3 / 1023))
21    time.sleep(0.5)

SPI, I2C y UART: comparación

CaracterísticaSPII2CUART
Número de cables4 (+1 CS por cada dispositivo extra)2 (SDA, SCL)2 (TX, RX)
Velocidad típica1–80 MHz100 kHz, 400 kHz, 1 MHz9600–115200 baudios (hasta unos pocos Mbit/s)
RelojSí (lo genera el controlador)Sí (lo genera el controlador)No; los dos lados acuerdan la misma velocidad en baudios
SentidoFull duplexHalf duplexFull duplex
Selección de dispositivoCable CS propioDirección de 7 bitsSolo dos dispositivos (punto a punto)
Componentes extraNo hacen faltaResistencias pull-upNo hacen falta
DistanciaCorta (en la placa, unas decenas de cm)Corta (alrededor de 1 m)Unos metros; mucho más con RS-485
Módulos típicosTarjeta SD, RC522, TFT, nRF24L01, MAX7219OLED, adaptador I2C para LCD, RTC, BME280, MPU6050GPS, HC-05, SIM800L, ESP-01, ordenador

Normalmente la elección la hace el módulo, pero en tus propios diseños esta regla ayuda: si importan la velocidad y la cantidad de datos (imágenes en pantalla, archivos, audio), usa SPI; si necesitas pocos cables y muchos sensores lentos, usa I2C; si quieres un enlace sencillo basado en texto entre dos dispositivos, usa UART. Tienes UART en detalle en el artículo Comunicación serie UART. También es muy habitual usar los tres en el mismo proyecto: por ejemplo, un registrador de datos que lee sensores por I2C, escribe en una tarjeta SD por SPI y recibe la posición de un GPS por UART.

Módulos que usan SPI e ideas de proyectos

  • Cerradura con tarjeta y registro de accesos: lee la tarjeta con un RC522 y escribe la fecha y el UID en una tarjeta SD.
  • Registrador de temperatura: guarda datos de sensores en una microSD en formato CSV y haz gráficas en Excel.
  • Panel de texto deslizante: muestra la hora y mensajes en módulos de matriz LED MAX7219 encadenados.
  • Interfaz a color: dibuja gráficos y menús en una pantalla TFT ILI9341; conecta también el panel táctil al mismo bus SPI.
  • Mando inalámbrico: envía órdenes a tu coche robot con dos módulos nRF24L01.
  • Medida multicanal: monta con un MCP3008 un controlador MIDI de 8 potenciómetros o un sistema de riego con 8 sensores de humedad del suelo.

Errores frecuentes y soluciones

SíntomaCausa probableSolución
Siempre se lee 0xFF o 0x00MISO sin conectar, MOSI y MISO intercambiados o el dispositivo sin alimentaciónConecta DIN a MOSI y DOUT a MISO; mide el VCC del dispositivo
Valores sin sentido o desplazados un bitModo SPI incorrecto o reloj demasiado rápido para el dispositivoUsa el modo de la hoja de datos, baja la velocidad a 1 MHz y vuelve a probar
Dos dispositivos que funcionan solos no funcionan juntosUn módulo no libera MISO o los pines CS no están en HIGH al inicioPon todos los CS en HIGH primero; cambia el módulo que no libera MISO o usa un bus SPI separado
El SPI se detiene de repente en el UnoD10 se ha usado como entrada y se ha puesto en LOWDeja D10 como salida; puedes usarlo como CS
El ESP32 no arranca con HSPI conectadoGPIO 12 queda en HIGH al arrancarLleva el MISO con pull-up a VSPI o elige otro pin para MISO
Errores aleatorios con cables largosReflexiones y ruido en una señal rápidaAcorta los cables, baja la velocidad, lleva un cable de GND junto a las señales
Un analizador lógico barato de 8 canales es muy útil para ver lo que pasa en SPI: graba SCK, MOSI, MISO y CS a la vez y decodifica qué byte salió y cuál volvió. En el momento en que dices "el código está bien pero no funciona", te muestra en segundos si el problema es el cableado o la configuración.

SPI es el idioma común de los módulos rápidos del mundo Arduino, desde tarjetas SD hasta pantallas a color: cuando conoces los cuatro cables, la lógica del CS y los cuatro modos, conectar un módulo SPI nuevo es cuestión de minutos. En la app BlueGrays encontrarás los proyectos de lectura de tarjetas RFID y cerradura, registrador de temperatura en microSD y reloj de matriz de puntos MAX7219, paso a paso con esquemas de circuito y código.

Preguntas frecuentes

¿Qué significa SPI?

SPI son las siglas de Serial Peripheral Interface (interfaz periférica serie). Permite que un controlador intercambie datos de forma rápida y síncrona con periféricos a través de cuatro líneas: SCK, MOSI, MISO y CS.

¿Qué son MOSI y MISO?

MOSI (Master Out Slave In) es la línea de datos del controlador al periférico; MISO (Master In Slave Out) es la línea de datos del periférico de vuelta al controlador. En la nomenclatura nueva también se llaman COPI y CIPO. En los módulos, DIN suele ir a MOSI y DOUT a MISO.

¿Cuáles son los pines SPI del Arduino Uno?

En el Arduino Uno y el Nano, SCK es D13, MISO es D12, MOSI es D11 y el CS por defecto es D10. Las mismas líneas están también en el conector ICSP de 6 pines de la placa. En el Arduino Mega son SCK D52, MISO D50, MOSI D51 y CS D53.

¿Qué diferencia hay entre SPI e I2C?

SPI usa cuatro cables, es full duplex y puede funcionar a decenas de MHz; cada dispositivo necesita su propio cable CS. I2C usa solo dos cables y selecciona los dispositivos por dirección, pero funciona a velocidades mucho menores, como 100–400 kHz, y necesita resistencias pull-up.

¿Cuántos dispositivos se pueden conectar a un bus SPI?

No hay un límite teórico; basta con tener un pin CS libre en el controlador por cada dispositivo. En la práctica aparecen problemas a altas velocidades cuando crecen la capacidad del bus y la longitud de los cables. Si te faltan pines, puedes multiplicar las líneas CS con un decodificador 74HC138 o usar dispositivos encadenables.

¿Por qué una tarjeta SD y un RFID no funcionan en el mismo bus SPI?

El conversor de nivel de muchos módulos SD baratos no suelta la línea MISO aunque CS esté en HIGH y estropea la respuesta del RC522. Se soluciona usando un módulo que libere bien MISO, conectando el pin de habilitación del búfer a CS o, en el ESP32, poniendo los dos dispositivos en buses SPI separados.

Ver todos los proyectos
Lectura de valores RFID
#53Principiante
Premium

Lectura de valores RFID

El llavero del portal o la tarjeta de acceso guardan un número de identificación secreto, y este proyecto lo lee. Acerca la tarjeta al lector RFID y el Arduino escribe su número en la pantalla del ord

4.7(47)
61
Autenticación RFID
#54Intermedio
Premium

Autenticación RFID

Como el acceso con tarjeta del portal de un edificio: acercas tu tarjeta al lector RFID y el Arduino compara su número con el que tiene guardado. Con la tarjeta correcta se enciende el LED verde duran

4.8(64)
83
Lector de tarjetas RFID RC522 para ESP32 (con LCD)
#123Intermedio

Lector de tarjetas RFID RC522 para ESP32 (con LCD)

En este proyecto, conectaremos el módulo RFID RC522 basado en MFRC522 al ESP32 a través de SPI y leeremos el UID de la tarjeta o etiqueta. Esto constituye la base de aplicaciones como cerraduras, sistemas de afiliación y control de acceso. Mostraremos el UID leído en la pantalla LCD; esta versión no lo compara con una lista de tarjetas autorizadas. ATENCIÓN: El RC522 solo funciona a 3,3 V; si le aplicas 5 V, ¡el módulo se quemará!

4.8(21)
39
Cerradura RFID ESP32 (RC522 + servo + OLED + zumbador + LED)
#137Avanzado
Premium

Cerradura RFID ESP32 (RC522 + servo + OLED + zumbador + LED)

Vamos a construir una cerradura inteligente utilizando un ESP32, un módulo RFID RC522, un servomotor SG90, una pantalla OLED SSD1306, un zumbador activo y 2 LED. Cuando se lee una tarjeta, su código UID se compara con la lista de tarjetas autorizadas definida en el sistema; si es autorizada, el servomotor gira y se desbloquea la cerradura (LED verde + 2 pitidos cortos), y se vuelve a bloquear automáticamente tras 5 segundos. Si la tarjeta no está autorizada, se enciende el LED rojo, se emite una

4.8(9)
15
Registrador de Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Avanzado
Premium

Registrador de Temperatura ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

¡Construye un registrador de temperatura con marca de tiempo con ESP32! Lee temperatura/humedad del DHT22 cada minuto, obtén la hora real del DS1307 RTC y registra en tarjeta microSD como CSV. El OLED muestra en vivo la temperatura (fuente grande), porcentaje de humedad, marca de tiempo y contador de registros. El archivo /temp_log.csv en la tarjeta SD se abre en Excel, Google Sheets o Python pandas para análisis — perfecto para monitoreo de invernadero, seguimiento de temperatura del hog

4.7(7)
12
Reloj y calendario de matriz de puntos (MAX7219, DS1307)
#84Intermedio
Premium

Reloj y calendario de matriz de puntos (MAX7219, DS1307)

Un panel luminoso para tu mesa o tu pared que muestra la hora y la fecha con texto en movimiento. En la pantalla LED de 8x32 se ve un reloj de números grandes cuyos dos puntos parpadean cada segundo;

5.0(37)
59
4x 32x8 Matriz LED Animación Y Texto
#90Intermedio
Premium

4x 32x8 Matriz LED Animación Y Texto

Si apilas cuatro módulos largos de matriz LED, obtienes una pantalla cuadrada con más de mil puntos de luz. Primero caen letras desde arriba como una lluvia de película, luego se abre un telón y en do

4.6(40)
66
Serpiente de píxeles Matriz 8x8
#88Avanzado
Premium

Serpiente de píxeles Matriz 8x8

Monta con tus propias manos el clásico juego de la serpiente y juega. En una matriz de luces de colores de 8x8 guías una serpiente verde con un joystick y te comes manzanas rojas; con cada manzana la

4.7(39)
57