Si alguna vez te has quedado sin pines digitales en un Arduino, la función shiftOut() es una de las herramientas más importantes que debes aprender. Con ella podrás enviar datos a dispositivos externos, como registros de desplazamiento, pantallas LED, matrices de LEDs y otros circuitos, utilizando únicamente unos pocos pines del microcontrolador.
Conocimientos previos
Registro de desplazamiento
Un registro de desplazamiento (Shift Register) es un circuito digital que sirve para guardar bits y moverlos de una posición a otra cada vez que llega una señal de reloj (clock).
Dicho simple: Es como una fila de casillas donde cada casilla guarda un 0 o un 1. Cuando llega un pulso de reloj, todos los valores avanzan una posición.
Ejemplo mental
Supongamos que tienes 8 espacios vacíos:
[ ][ ][ ][ ][ ][ ][ ][ ]
Cada espacio puede guardar: 0 o 1
Paso 1 — entra el primer bit
Envías: 1
Estado:
[1][ ][ ][ ][ ][ ][ ][ ]
Paso 2 — llega otro bit y se desplaza
Envías: 0
Estado:
[0][1][ ][ ][ ][ ][ ][ ]
Paso 3
Envías: 1
Estado:
[1][0][1][ ][ ][ ][ ][ ]
Paso 4
Envías: 1
Estado:
[1][1][0][1][ ][ ][ ][ ]
Componentes internos
Un registro de desplazamiento normalmente tiene:
- Entrada de datos (DATA)
- Entrada de reloj (CLOCK)
- Memoria interna (Flip-Flops)
- Salidas
DATA
↓
┌──────────────────────┐
│[ ][ ][ ][ ][ ][ ][ ] │
└──────────────────────┘
↑
CLOCK
¿Qué hace el reloj (Clock)?
El reloj es quien dice: “Ahora mueve todos los bits”.
Función shiftOut
La función shiftOut() envía un byte de información bit por bit a través de un pin de datos.
Cada vez que envía un bit, genera un pulso en el pin de reloj (Clock), indicando al dispositivo conectado que debe leer ese valor.
¿Qué hace internamente?
Supongamos que quieres enviar el número: 13
En binario: 00001101
shiftOut() envía esos bits uno por uno: 0 → 0 → 0 → 0 → 1 → 1 → 0 → 1
Mientras envía cada bit:
- Coloca el valor en el pin de datos.
- Genera un pulso en el pin reloj.
- El dispositivo receptor guarda ese bit.
Sintaxis
shiftOut(dataPin, clockPin, bitOrder, value);
- dataPin: Pin que enviará los datos
- clockPin: Pin que marca el ritmo de envío
- bitOrder: Orden de envío (MSBFIRST o LSBFIRST)
- MSBFIRST (Most Significant Bit First) Empieza por el bit más significativo.
- 13 = 00001101 Envía 0 0 0 0 1 1 0 1
- LSBFIRST (Least Significant Bit First) Empieza por el bit menos significativo.
- 13 = 00001101 Envía 1 0 1 1 0 0 0 0
- MSBFIRST (Most Significant Bit First) Empieza por el bit más significativo.
- value: Valor que quieres enviar
Ejemplo práctico en wokwi
En este ejemplo utilizaremos Wokwi, una plataforma que permite similar placas Arduino:
Ingresamos a https://wokwi.com/projects/new/arduino-uno
Componentes
- Arduino UNO
- Analizador lógico https://docs.wokwi.com/parts/wokwi-logic-analyzer
- Protoboard
Circuito
Vamos a realizar la conexion como podemos ver en la siguiente imagen.
Código
Dentro del sitio Wokwi, esta la sección de código, colocaremos el siguiente ejemplo:
// Pines de conexión
const int dataPin = 8;
const int latchPin = 12;
const int clockPin = 11;
void setup() {
pinMode(dataPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
}
void loop() {
// Encender LEDs pares
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, B10101010);
digitalWrite(latchPin, HIGH);
delay(1000);
// Encender LEDs impares
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, B01010101);
digitalWrite(latchPin, HIGH);
delay(1000);
}
Simulación
- Iniciamos el simulador de Wokwi, dejamos que pases algunos segundos para que el Arduino envié datos a el analizador lógico.
- Al finalizar la simulación, pedirá que guardemos en el PC un archivo VCD: https://en.wikipedia.org/wiki/Value_change_dump
- Para visualizar el archivo seguemos los pasos del analizador lógico https://docs.wokwi.com/guides/logic-analyzer#using-the-logic-analyzer
- Descargamos el IDE vs code https://code.visualstudio.com/
- Instalamos la extensión https://marketplace.visualstudio.com/items?itemName=HassanEbrahimi.vcd-analyzer
- Cargamos el archivo descargado en vs code, donde interpretara el archivo y mostrara la grafica de envio de datos:
Resultado
Esta gráfica del Logic Analyzer de Wokwi muestra exactamente cómo trabaja internamente la función shiftOut(). Es una excelente imagen para incluir en tu artículo porque permite visualizar el proceso de envío de los bits. Vamos a analizarla paso a paso.
En tu circuito configuraste los pines así:
| Arduino | Señal | Canal Wokwi |
|---|---|---|
| Pin 8 | dataPin | D0 |
| Pin 12 | latchPin | D1 |
| Pin 11 | clockPin | D2 |
La gráfica representa:
- D0: Datos (Data)
- D1: Latch
- D2: Clock
La imagen del analizador lógico permite observar el funcionamiento interno de shiftOut(). La línea Data contiene el valor de cada bit que será transmitido, mientras que la línea Clock genera un pulso por cada bit enviado. En cada flanco del reloj, el registro de desplazamiento lee el valor presente en la línea de datos y lo almacena temporalmente. Una vez transmitidos los ocho bits, la línea Latch cambia de estado, indicando al registro que copie el byte completo a sus salidas. Gracias a este mecanismo, todas las salidas se actualizan al mismo tiempo, evitando cambios parciales o parpadeos.
Nota: Una observación importante
Al comparar la gráfica con el código y el comportamiento esperado de shiftOut(), parece que los canales del Logic Analyzer están etiquetados de forma distinta a los nombres que indicaste:
- La señal con 8 pulsos corresponde al Clock.
- La señal que cambia una sola vez al finalizar corresponde al Latch.
- La señal superior corresponde a Data.
Buenas prácticas
- Declara los pines como constantes (
const int) para facilitar el mantenimiento del código. - Utiliza la representación binaria (
B10101010) cuando quieras visualizar rápidamente qué salidas estarán encendidas o apagadas. - Si necesitas controlar más de ocho salidas, puedes conectar varios registros 74HC595 en cascada y llamar a
shiftOut()varias veces antes de activar el pinlatch. - Mantén una secuencia clara:
latch LOW→shiftOut()→latch HIGH.
Conclusión
La función shiftOut() es una herramienta fundamental para cualquier proyecto de Arduino que requiera controlar múltiples salidas utilizando pocos pines. Aunque su funcionamiento se basa en un concepto sencillo —enviar un byte bit a bit mediante un pin de datos y sincronizarlo con un pin de reloj—, abre la puerta a proyectos mucho más complejos, como paneles LED, displays de siete segmentos, matrices de LEDs y sistemas con varios registros de desplazamiento.
Una vez comprendas cómo se combinan shiftOut(), el pin latch y el registro 74HC595, podrás ampliar fácilmente tus proyectos sin las limitaciones de pines del Arduino. El ejemplo propuesto en Tinkercad es un excelente punto de partida para experimentar cambiando los patrones binarios y observando cómo cada bit controla una salida diferente.
Preguntas frecuentes (FAQ)
¿shiftOut() funciona sin un 74HC595?
Sí. La función simplemente envía datos en serie por dos pines (datos y reloj). Puede utilizarse con cualquier dispositivo compatible con comunicación serie síncrona por desplazamiento, aunque el 74HC595 es el caso de uso más común.
¿Cuántos bits envía shiftOut()?
Cada llamada envía exactamente 8 bits (un byte).
¿Qué diferencia hay entre MSBFIRST y LSBFIRST?
MSBFIRSTenvía primero el bit más significativo (el de mayor peso).LSBFIRSTenvía primero el bit menos significativo (el de menor peso).
La elección depende del dispositivo que reciba los datos.
¿Puedo controlar más de 8 LEDs?
Sí. Puedes conectar varios registros 74HC595 en cascada y enviar un byte para cada uno antes de activar el pin latch.
¿Cuál es la diferencia entre shiftOut() y digitalWrite()?
digitalWrite() controla un único pin del Arduino directamente. En cambio, shiftOut() envía un conjunto de 8 bits a un dispositivo externo, permitiendo controlar muchas salidas utilizando solo unos pocos pines del Arduino.