← Índice del curso

Microcontroladores · Tema 34

Bus SPI

Si I2C es el bus de los sensores lentos, SPI es el de las pantallas, las memorias, las tarjetas SD y los conversores rápidos. Usa más cables, pero a cambio no tiene direcciones, ni confirmaciones, ni resistencias de pull-up: dos registros de desplazamiento conectados en anillo intercambian bytes a megahertz de velocidad.

01 · Punto de partida

Velocidad a cambio de cables

I2C ahorra cables, pero paga con velocidad: las resistencias de pull-up limitan los flancos y cada byte lleva un bit de confirmación. SPI (Serial Peripheral Interface, de Motorola) elige el camino opuesto. Cada línea tiene una sola función, las salidas son activas (empujan tanto a alto como a bajo) y no hay direcciones ni ACK. Eso lo hace sencillo en hardware y capaz de llegar a decenas de megahertz.

Sus usos típicos son los que necesitan ancho de banda: pantallas gráficas TFT y OLED rápidas, tarjetas SD, memorias Flash y EEPROM, conversores analógico-digitales y DAC como el MCP4921 del tema 29, módulos de radio, y cadenas de registros de desplazamiento para sacar muchos pines de salida. A cambio, hay que dedicar pines: tres compartidos más uno por cada dispositivo.

No existe un estándar oficial de SPI: cada fabricante lo describe a su manera y los detalles (modo, orden de bits, longitud de palabra) están en cada hoja de datos. Por eso saber leer un diagrama de tiempos importa más que memorizar valores.

02 · El principio

Cuatro líneas y un anillo

Conexión SPI entre un maestro y un esclavo El registro de desplazamiento del maestro y el del esclavo forman un anillo. La línea MOSI lleva el bit saliente del maestro a la entrada del esclavo, y MISO lleva el bit saliente del esclavo a la entrada del maestro. El maestro genera SCK y la línea de selección CS. Maestro (microcontrolador) registro de desplazamiento (SPDR) Esclavo (dispositivo) registro de desplazamiento MOSIMISO (maestro sale, esclavo entra) SCK (lo genera el maestro) CS o SS (activa en bajo) en cada pulso: sale un bit y entra otro tras 8 pulsos los bytes se intercambiaron

El bus tiene cuatro líneas:

  • SCK (reloj): lo genera el maestro. Un pulso por cada bit.
  • MOSI (master out, slave in): del maestro al esclavo.
  • MISO (master in, slave out): del esclavo al maestro.
  • CS o SS (chip select, selección de chip): el maestro la baja para elegir al esclavo. Con CS en alto, el esclavo ignora el bus y deja su salida MISO en alta impedancia.

La idea central: el maestro y el esclavo tienen cada uno un registro de desplazamiento de 8 bits, y los dos forman un anillo. En cada pulso de SCK, el bit más significativo del maestro sale por MOSI y entra por el extremo bajo del registro del esclavo, mientras el bit más significativo del esclavo sale por MISO y entra en el del maestro. Después de 8 pulsos, ambos registros han intercambiado su contenido. Por eso SPI es dúplex completo: siempre que se envía un byte, se recibe otro, aunque uno de los dos sea irrelevante.

Si querés leer del esclavo, el maestro envía un byte «de relleno» (por ejemplo 0x00) solo para generar los 8 pulsos; si querés escribir y no te interesa la respuesta, descartás el byte recibido. Esa simetría explica por qué la función básica de SPI se llama transferir y no enviar o recibir.

03 · Cuándo se lee

Los cuatro modos de reloj

Como no hay un estándar, los dispositivos difieren en cuándo cambian y cuándo leen los datos. Se describe con dos parámetros:

  • CPOL (polaridad del reloj): nivel de SCK en reposo. 0 = bajo, 1 = alto.
  • CPHA (fase del reloj): en cuál de los dos flancos de cada pulso se lee el dato. 0 = en el primero (el de salida del reposo); 1 = en el segundo.
Los cuatro modos.
ModoCPOLCPHASCK en reposoSe lee enEl dato cambia en
000BajoSubidaBajada
101BajoBajadaSubida
210AltoBajadaSubida
311AltoSubidaBajada

Un truco para no memorizarlo: si CPOL ⊕ CPHA = 0 (modos 0 y 3), se lee en el flanco de subida; si es 1 (modos 1 y 2), en el de bajada. Los modos 0 y 3 son los más comunes. La primera herramienta del laboratorio dibuja los cuatro.

Las dos puntas deben usar el mismo modo. Si no, el maestro lee los bits en el momento en que el esclavo los está cambiando, y el resultado son datos corridos un bit o basura. La hoja de datos de un dispositivo dice cosas como «el reloj es alto en reposo y los datos se capturan en el flanco de subida» (modo 3) o simplemente «modo 0».

Otros dos parámetros importan: el orden de los bits (casi siempre el más significativo primero, MSB; algunos pocos chips usan LSB primero) y la longitud de la palabra (8 bits en el ATmega328P; muchos dispositivos usan 16, y se envían como dos bytes seguidos).

04 · Varios dispositivos

Selección de chip y varios esclavos

SPI no tiene direcciones: el maestro elige al esclavo con una línea dedicada. Con CS en alto, el esclavo está desconectado: ignora SCK y MOSI y deja MISO en alta impedancia (Hi-Z), de modo que no interfiere con los demás. Al bajar CS, empieza una transacción, y al subirla, termina. La mayoría de los dispositivos reinician su estado interno con el flanco de CS: subir CS en medio de un comando lo aborta.

Hay dos formas de conectar varios esclavos:

  • Independientes (estrella): SCK, MOSI y MISO se comparten y cada esclavo tiene su CS. Es lo habitual. Necesita 3 + n pines. Cuando faltan pines, se usa un decodificador (un 74HC138 maneja 8 esclavos con 3 pines) o un expansor.
  • En cadena (daisy chain): la salida del primer esclavo (MISO) se conecta a la entrada del siguiente, y todos comparten un único CS. El maestro envía n bytes seguidos y cada uno queda en el esclavo que le corresponde (el primero que se envía acaba en el último de la cadena). Es la conexión de los registros de desplazamiento 74HC595 y de ciertos controladores de LED. Usa 4 pines sin importar la cantidad.

Una advertencia clásica: solo un esclavo debe tener CS en bajo a la vez. Si dos están seleccionados, ambos manejan MISO y se pelean por la línea. Y al iniciar el programa, todas las líneas CS deben ponerse en alto antes de configurar el bus, para que ningún dispositivo reciba basura mientras los pines están indefinidos.

05 · Periférico

El módulo SPI del ATmega328P

Pines del SPI.
SeñalPin del chipArduino Uno
SCKPB513 (también el LED integrado)
MISOPB412
MOSIPB311
SSPB210

El módulo se controla con tres registros. SPDR es el registro de datos: escribirlo inicia la transferencia de ese byte y, al terminar, contiene el byte recibido. SPSR tiene la bandera SPIF (transferencia completa, se borra al leer SPSR y luego SPDR), la bandera de colisión de escritura WCOL y el bit de doble velocidad SPI2X. SPCR configura el resto:

SPCR (0x4C).
BitNombreFunción
7SPIEHabilita la interrupción de fin de transferencia
6SPEHabilita el módulo SPI
5DORDOrden de datos: 0 = MSB primero; 1 = LSB primero
4MSTR1 = maestro; 0 = esclavo
3CPOLPolaridad del reloj
2CPHAFase del reloj
1:0SPR1:SPR0Divisor del reloj (con SPI2X)
Velocidad de SCK = fosc / divisor; con 16 MHz.
SPI2XSPR1:0DivisorSCK con 16 MHz
10028 MHz
00044 MHz
10182 MHz
001161 MHz
11032500 kHz
01064250 kHz
011128125 kHz

El mínimo es 2 porque el módulo necesita al menos dos ciclos del procesador por bit: a 8 MHz, un byte tarda 1 µs. El reloj del módulo SPI sale del mismo oscilador que la CPU, de modo que cambiar la frecuencia de la CPU cambia también la de SCK.

06 · Primer programa

Código de maestro

La función básica es de tres líneas: escribir el byte, esperar la bandera y devolver lo recibido.

#define F_CPU 16000000UL
#include <avr/io.h>
#include <stdint.h>

#define CS_DAC_BAJO()  (PORTB &= ~(1 << PB2))
#define CS_DAC_ALTO()  (PORTB |=  (1 << PB2))
#define CS_MEM_BAJO()  (PORTB &= ~(1 << PB1))
#define CS_MEM_ALTO()  (PORTB |=  (1 << PB1))

static void spi_init(void) {
    PORTB |= (1 << PB2) | (1 << PB1);                   // todos los CS en alto primero
    DDRB  |= (1 << PB3) | (1 << PB5) | (1 << PB2) | (1 << PB1);   // MOSI, SCK, SS y CS de la memoria
    SPCR = (1 << SPE) | (1 << MSTR);                    // maestro, modo 0, MSB primero, f/4
    SPSR = (1 << SPI2X);                                // f/2 = 8 MHz
}

static uint8_t spi_transferir(uint8_t dato) {
    SPDR = dato;                                         // inicia la transferencia
    while (!(SPSR & (1 << SPIF))) { }                  // 8 pulsos de SCK
    return SPDR;                                         // el byte que llegó por MISO
}

Con eso se manejan los dispositivos reales. El DAC MCP4921 del tema 29 recibe una palabra de 16 bits en una sola transacción (CS en bajo durante los dos bytes):

static void dac_escribir(uint16_t valor12) {
    uint16_t palabra = 0x3000 | (valor12 & 0x0FFF);      // configuración + 12 bits de dato
    CS_DAC_BAJO();
    spi_transferir((uint8_t)(palabra >> 8));
    spi_transferir((uint8_t)(palabra & 0xFF));
    CS_DAC_ALTO();                                       // al subir CS el DAC actualiza la salida
}

Una memoria EEPROM o Flash serie (del tipo 25LC256) se lee con un comando de un byte, una dirección y tantos bytes de relleno como datos se pidan. Para recibir se envía 0x00: lo que importa es el byte que vuelve.

#define MEM_LEER   0x03
#define MEM_WREN   0x06
#define MEM_ESCRIBIR 0x02

static void mem_leer(uint16_t dir, uint8_t *destino, uint8_t n) {
    CS_MEM_BAJO();
    spi_transferir(MEM_LEER);
    spi_transferir((uint8_t)(dir >> 8));
    spi_transferir((uint8_t)(dir & 0xFF));
    while (n--) *destino++ = spi_transferir(0x00);       // relleno para generar los pulsos
    CS_MEM_ALTO();
}

static void mem_escribir_byte(uint16_t dir, uint8_t dato) {
    CS_MEM_BAJO(); spi_transferir(MEM_WREN); CS_MEM_ALTO();      // habilitar escritura (transacción propia)
    CS_MEM_BAJO();
    spi_transferir(MEM_ESCRIBIR);
    spi_transferir((uint8_t)(dir >> 8));
    spi_transferir((uint8_t)(dir & 0xFF));
    spi_transferir(dato);
    CS_MEM_ALTO();                                       // al subir CS comienza el ciclo interno de escritura
    /* esperar unos milisegundos o consultar el registro de estado (bit WIP) antes de la próxima escritura */
}

La memoria enseña dos hábitos de SPI. Primero: el flanco de subida de CS es una orden: en la escritura, es el que arranca el ciclo interno. Segundo: algunos comandos exigen su propia transacción (WREN va con un CS completo antes del comando de escritura). La hoja de datos define cuál es cuál.

Un caso curioso: una cadena de tres registros de desplazamiento 74HC595 (24 salidas con 4 pines). Se envían los tres bytes seguidos y se da un pulso al pin de latch (RCLK) que copia el contenido a las salidas. El primer byte enviado termina en el último registro de la cadena.

static void cadena_escribir(const uint8_t *datos, uint8_t n) {
    for (uint8_t i = 0; i < n; i++) spi_transferir(datos[i]);   // el primero llega al último registro
    PORTB |=  (1 << PB2);                                         // latch (RCLK): salidas = registros
    PORTB &= ~(1 << PB2);
}

07 · En un sistema real

Compartir el bus

Cuando varios dispositivos cuelgan del mismo bus, aparecen cuestiones de convivencia:

  • Modos y velocidades distintos. Un dispositivo puede pedir modo 0 a 10 MHz y otro modo 3 a 1 MHz. Entonces se reconfiguran SPCR y SPSR al comenzar cada transacción (la biblioteca SPI de Arduino lo hace con beginTransaction()).
  • Tarjetas SD. Se inicializan a 400 kHz o menos, con CS en alto y al menos 74 pulsos de reloj, y recién después se sube la velocidad.
  • Interrupciones. Si una ISR usa el mismo bus que el programa principal, hay que protegerse: una transferencia interrumpida por otra rompe ambas (tema 21). Lo normal es no usar SPI desde las ISR, o desactivar las interrupciones durante la transacción.
  • Niveles de tensión. Un dispositivo de 3,3 V no tolera 5 V en MOSI, SCK ni CS. La señal de 3,3 V en MISO hacia un chip de 5 V suele funcionar, porque supera el umbral de 3 V. Los conversores de nivel o los divisores resuelven la dirección de 5 V a 3,3 V.
  • Cables. A varios megahertz, los flancos son rápidos y los cables largos producen rebotes y diafonía. SPI está pensado para distancias de decenas de centímetros: para más hay que bajar el reloj, o cambiar de bus.

08 · Elegir

SPI, I2C y UART frente a frente

Resumen de los tres protocolos.
CaracterísticaUARTI2CSPI
Cables223 + una CS por esclavo
RelojSin relojSCL del maestroSCK del maestro
Dispositivos2Muchos, por direcciónMuchos, por CS
Velocidad típicaHasta ~1 Mbit/s100 a 400 kbit/s1 a 20 Mbit/s o más
Sobrecarga20 % (8N1)1 bit por byte más direcciónPrácticamente nula
ConfirmaciónNo (paridad opcional)ACK por byteNo hay
SentidoDúplex completoSemidúplexDúplex completo
CircuitoSalidas activasColector abierto y pull-upsSalidas activas
EstandarizaciónFormato claro, niveles aparteEspecificación formalSin estándar: modos a mano

La falta de ACK es la diferencia que más se nota al depurar: si el esclavo no está conectado, SPI no se queja. El maestro envía bytes y recibe 0xFF (la línea MISO flota en alto) o 0x00 sin saber que nadie contesta. Por eso suele hacerse una lectura de identificación (un registro con valor conocido) al arrancar, para comprobar que el dispositivo está presente.

09 · Diagnóstico

Cuando no responde

Síntomas más comunes de un bus SPI.
SíntomaCausa probable
Siempre se lee 0xFF o 0x00Esclavo sin alimentación o desconectado, MISO sin conectar, CS que nunca baja
Los datos llegan corridos un bit o con basuraModo (CPOL/CPHA) equivocado o velocidad excesiva para el dispositivo
Funciona una vez y después se bloqueaPB2 (SS) configurado como entrada: el módulo pasó a modo esclavo
Escritura aparentemente correcta, memoria sin cambiosFalta el comando de habilitación (WREN) o CS no subió al final para disparar la escritura
Uno de dos dispositivos falla cuando ambos están conectadosDos CS activos a la vez, o un dispositivo sin alta impedancia en MISO que interfiere
Falla solo con cables largosRebotes y diafonía: bajar SCK, acortar, agregar resistencias en serie (22 a 100 Ω)
La pantalla muestra colores o píxeles erróneosOrden de bytes de 16 bits (alto primero o bajo primero) o palabra de comando mal formada

El instrumento ideal es un analizador lógico con decodificador SPI (el tema 35 lo usa): muestra CS, SCK, MOSI y MISO y reconstruye los bytes, de modo que se ve qué envió el maestro y qué contestó el esclavo. Sin él, un osciloscopio de dos canales sobre SCK y MOSI ya revela si el modo y la velocidad son los esperados.

10 · Analogía con programación

Simular dos registros de desplazamiento

Este programa implementa el intercambio SPI entre un maestro y un esclavo con los cuatro modos, prueba qué combinaciones se entienden, calcula las velocidades del ATmega328P, compara el tiempo de leer 64 bytes con SPI, I2C y UART, y simula la conexión en cadena de tres registros de desplazamiento.

Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.

import random

random.seed(3)

# 1) intercambio SPI entre un maestro y un esclavo, con el reloj que genera el maestro
def bits(valor):
    return [(valor >> (7 - i)) & 1 for i in range(8)]       # MSB primero

def a_byte(lista):
    return sum(b << (7 - i) for i, b in enumerate(lista))

def intercambio(byte_m, byte_e, modo_m, modo_e):
    cpol_m, cpha_m = modo_m >> 1, modo_m & 1
    cpol_e, cpha_e = modo_e >> 1, modo_e & 1
    salida_m, salida_e = bits(byte_m), bits(byte_e)
    # el maestro genera 8 pulsos: sale del reposo y vuelve
    flancos, nivel = [], cpol_m
    for _ in range(8):
        for _ in range(2):
            nivel ^= 1
            flancos.append(nivel)
    estado = {"m": {"idx": 0, "linea": None, "rx": []}, "e": {"idx": 0, "linea": None, "rx": []}}
    # con CPHA=0 el primer bit ya esta en la linea cuando baja CS
    if cpha_m == 0:
        estado["m"]["linea"] = salida_m[0]; estado["m"]["idx"] = 1
    if cpha_e == 0:
        estado["e"]["linea"] = salida_e[0]; estado["e"]["idx"] = 1
    previo = cpol_m
    params = {"m": (cpol_m, cpha_m, salida_m), "e": (cpol_e, cpha_e, salida_e)}
    conflicto = []
    for nivel_nuevo in flancos:
        acciones = {}
        for clave, (cpol, cpha, salida) in params.items():
            principal = nivel_nuevo != cpol                  # flanco que sale del reposo del dispositivo
            acciones[clave] = "muestrea" if (principal if cpha == 0 else not principal) else "desplaza"
        lineas_antes = {k: estado[k]["linea"] for k in estado}   # los dos actuan a la vez
        for clave, (cpol, cpha, salida) in params.items():
            s = estado[clave]
            otra = "e" if clave == "m" else "m"
            if acciones[clave] == "muestrea":
                if acciones[otra] == "desplaza" and estado[otra]["idx"] < 8:
                    conflicto.append(1)                      # el otro cambia su salida justo cuando se lee
                s["rx"].append(lineas_antes[otra])
            elif s["idx"] < 8:
                s["linea"] = salida[s["idx"]]
                s["idx"] += 1
    ok_m = len(estado["m"]["rx"]) == 8 and None not in estado["m"]["rx"] and a_byte(estado["m"]["rx"]) == byte_e
    ok_e = len(estado["e"]["rx"]) == 8 and None not in estado["e"]["rx"] and a_byte(estado["e"]["rx"]) == byte_m
    return ok_m and ok_e and not conflicto

def pruebas(modo_m, modo_e, n=40):
    return all(intercambio(random.randrange(256), random.randrange(256), modo_m, modo_e) for _ in range(n))

print("maestro \\ esclavo   modo 0  modo 1  modo 2  modo 3")
for m in range(4):
    fila = ["  si  " if pruebas(m, e) else "  NO  " for e in range(4)]
    print(f"     modo {m}           " + "  ".join(fila))

# 2) velocidad de SCK del ATmega328P con 16 MHz
print()
print("divisor   SCK          bit       byte")
for div in (2, 4, 8, 16, 32, 64, 128):
    f = 16e6 / div
    print(f"{div:7d}   {f / 1e6:6.3f} MHz  {1e9 / f:7.0f} ns  {8e6 / f:6.2f} us")

# 3) tiempo para leer 64 bytes de una memoria (comando + direccion de 2 bytes), SPI frente a I2C y UART
datos, cabecera = 64, 3
spi = 8 * (cabecera + datos) / 4e6
i2c = (9 * (3 + datos) + 3) / 400e3                     # direccion+W, registro, direccion+R y datos
uart = 10 * (cabecera + datos) / 115200
print()
print(f"leer {datos} bytes: SPI 4 MHz {spi * 1e6:.0f} us, I2C 400 kHz {i2c * 1e6:.0f} us, UART 115200 {uart * 1e6:.0f} us")

# 4) conexion en cadena: tres registros de desplazamiento de 8 bits en serie
def cadena(bytes_a_enviar, n=3):
    registros = [0] * n
    for byte in bytes_a_enviar:                         # el primer byte enviado termina en el ultimo registro
        for b in bits(byte):
            salida = registros[0]
            for i in range(n - 1, 0, -1):
                registros[i] = ((registros[i] << 1) & 0xFF) | (registros[i - 1] >> 7)
            registros[0] = ((registros[0] << 1) & 0xFF) | b
    return registros

enviado = [0xA1, 0xB2, 0xC3]
final = cadena(enviado)
print("cadena de 3 registros, enviando A1 B2 C3 ->", " ".join(f"{r:02X}" for r in final), "(del ultimo al primero de la cadena)")

Resultado: el intercambio funciona cuando el maestro y el esclavo usan el mismo modo (diagonal de la tabla) y falla con cualquier otra combinación. Con 16 MHz, la velocidad va de 8 MHz (divisor 2, 1 µs por byte) a 125 kHz (divisor 128). Leer 64 bytes de una memoria cuesta 134 µs por SPI a 4 MHz, 1515 µs por I2C a 400 kHz y 5816 µs por UART a 115 200 baudios. Y en la cadena de tres registros, al enviar A1 B2 C3 el primer byte (A1) termina en el último registro.

El modelo exige que no haya cambios de la línea en el mismo flanco en que el otro extremo lee (violaría el tiempo de retención). En dispositivos reales, algunas combinaciones, como los modos 0 y 3, a veces funcionan según el chip; no conviene depender de eso.

11 · Exploración interactiva

Modos, registros y tiempos

El visualizador dibuja una transferencia de un byte para el modo elegido, con los datos de MOSI y MISO. La segunda herramienta calcula los registros y la velocidad. La tercera estima el tiempo y el costo en pines de una transacción.

Banco del bus SPI

1. Una transferencia en la línea

Modo—
Cuándo se lee—
Los datos—

2. Registros y velocidad

Velocidad—
Registros—

3. Presupuesto de una transacción

Tiempo—
Caudal efectivo—
Líneas necesarias—

Recorrido guiado

  1. Con modo 0 (CPOL = 0, CPHA = 0) y el byte 0xB2 el dato ya está en la línea cuando SCK sube por primera vez; los puntos rojos marcan los flancos de subida. Pasá a CPHA = 1 (modo 1): los datos cambian en la subida y se leen en la bajada, y el primer bit se retrasa medio pulso.
  2. Con CPOL = 1 el reposo de SCK es alto. Compará modo 2 con modo 0: se lee en el flanco opuesto.
  3. Con «LSB primero», el mismo byte se envía invertido: 0xB2 pasa a 01001101.
  4. En la herramienta 2, 16 MHz con divisor 4 y modo 0 dan SPCR = 0x50, 4 MHz y 2 µs por byte. Con divisor 2 aparece SPSR = 0x01 y 8 MHz. Con el modo 3: SPCR = 0x5C.
  5. Con un dispositivo máximo de 2 MHz y divisor 4, la nota avisa que el reloj lo supera.
  6. En la herramienta 3, 64 bytes con 3 de comando a 4 MHz tardan 139 µs. Subí los esclavos a 8: la nota sugiere un decodificador.
Desafío: una pantalla de 128 × 64 píxeles

Una pantalla monocromática de 128 × 64 píxeles necesita 128 × 64 / 8 = 1024 bytes por cuadro. ¿Cuántos cuadros por segundo se pueden enviar por SPI a 8 MHz y por I2C a 400 kHz? Por SPI: 1024 × 8 / 8 MHz = 1,02 ms, unos 980 cuadros por segundo en el mejor caso. Por I2C a 400 kHz: (1024 + 2) × 9 / 400 kHz = 23 ms, unos 43 cuadros por segundo. Una animación fluida pide 30 cuadros por segundo, de modo que I2C alcanza justo; con una pantalla a color (16 bits por píxel) ya no sería posible, y por eso las pantallas TFT usan SPI.

12 · Comprensión

Confusiones frecuentes

«SPI tiene un ACK como I2C»

No. El maestro nunca sabe si el esclavo existe. Sin dispositivo, MISO flota o está en 0 y el maestro lee 0xFF o 0x00 sin error. Hay que verificar la presencia con una lectura de identificación.

«Para leer solo tengo que recibir»

En SPI cada pulso envía y recibe. Para leer hay que transmitir algo (el relleno), porque el maestro es el único que genera SCK.

«Todos los dispositivos SPI usan el modo 0»

Muchos sí, pero otros usan 1, 2 o 3. Debe leerse la hoja de datos. Un modo equivocado da datos corridos, no un error.

«Puedo subir CS entre bytes para ir más tranquilo»

Subir CS termina la transacción: el esclavo reinicia su estado y descarta el comando. CS debe mantenerse en bajo durante todo el comando, dirección y datos.

«Si no uso el pin 10, lo dejo como entrada»

En modo maestro, el pin SS debe ser salida. Si queda como entrada y se pone en bajo, el módulo pasa a esclavo y el SPI se bloquea.

13 · Práctica guiada

Predecí antes de comprobar

1. La velocidad

Con 16 MHz y divisor 8, ¿cuánto vale SCK y cuánto tarda un byte?

Ver solución

SCK = 16 MHz / 8 = 2 MHz; un bit dura 0,5 µs y un byte, 4 µs.

2. El registro

¿Qué valores de SPCR y SPSR configuran el maestro en modo 3, MSB primero, divisor 16?

Ver solución

SPE (0x40) + MSTR (0x10) + CPOL (0x08) + CPHA (0x04) + SPR0 (0x01) = SPCR = 0x5D. SPI2X = 0, por lo que SPSR = 0x00. SCK = 1 MHz.

3. Leer una hoja de datos

Un dispositivo dice: «el reloj está en alto en reposo y los datos se capturan en el flanco de subida». ¿Qué modo es?

Ver solución

Reposo en alto: CPOL = 1. Con reposo alto, el primer flanco es de bajada y el segundo (subida) es el de captura: CPHA = 1. Es el modo 3.

4. Una lectura de memoria

A 8 MHz, ¿cuánto tarda leer 256 bytes de una memoria con un comando de 3 bytes (sin contar gestión)?

Ver solución

(3 + 256) × 8 bits / 8 MHz = 259 µs. Eso son unos 1,0 MB/s efectivos, el 99 % de los bytes de datos.

5. Los pines

Se quieren conectar 4 dispositivos SPI. ¿Cuántas líneas hacen falta y cómo se reducen?

Ver solución

3 compartidas + 4 CS = 7 líneas. Con un decodificador 74HC138 (3 líneas de dirección para hasta 8 CS) bajan a 3 + 3 = 6, y con más dispositivos el ahorro crece. Si los dispositivos aceptan conexión en cadena, bastan 4.

14 · Síntesis

Ideas para recordar

  • SPI usa cuatro líneas (SCK, MOSI, MISO, CS) y dos registros de desplazamiento en anillo: cada pulso envía y recibe un bit, y cada byte enviado es también un byte recibido.
  • El maestro genera el reloj y elige al esclavo bajando CS; con CS en alto, el esclavo ignora el bus y suelta MISO.
  • Los modos 0 a 3 combinan CPOL (reposo de SCK) y CPHA (flanco de lectura); ambos extremos deben usar el mismo modo.
  • En el ATmega328P, SPCR y SPSR configuran el bus; SCK = fosc / 2, 4, 8, … 128; con 16 MHz, el máximo es 8 MHz.
  • El pin SS (PB2) debe ser una salida en modo maestro; si no, el módulo puede pasar a esclavo.
  • Sin ACK ni direcciones, SPI es rápido y simple, pero exige una línea CS por esclavo y no avisa si el dispositivo falta: se verifica leyendo un identificador.
  • CS debe mantenerse en bajo durante toda la transacción, y su flanco de subida suele ser una orden (por ejemplo, iniciar la escritura de una memoria).

¿Listo para el tema 35?

Antes de avanzar, dibujá el diagrama de tiempos de un byte en el modo 0, calculá SPCR para un modo y una velocidad, y explicá qué hace cada línea. Si podés justificar las tres respuestas, tenés el bus bajo control.

En el próximo tema, un taller: depurar buses con el analizador lógico. Capturaremos y decodificaremos tramas reales de UART, I2C y SPI para diagnosticar problemas con los tres.