← Índice del curso

Comunicación entre Dispositivos · Tema 17 · I²C

Direccionamiento y condiciones del bus

En el tema anterior vimos cómo se manejan las dos líneas. Ahora vemos qué se dice por ellas. Un mensaje I²C empieza con una marca de inicio, sigue con una dirección de siete bits que elige al dispositivo, un bit que indica si se escribe o se lee, y una confirmación por cada byte, y termina con una marca de fin. Vamos a recorrer cada pieza, a leer los mensajes como los muestra un analizador lógico y a armar a mano un maestro por software que los genera.

01 · Un protocolo en dos líneas

Qué viaja por el bus

En SPI, el maestro elegía a su interlocutor bajando una línea de selección, y después los bytes viajaban sin más. En I²C no hay esa línea: quién habla con quién se decide dentro del propio mensaje. Eso obliga a que el protocolo tenga más piezas, todas muy pequeñas:

  • Marcas de inicio y de fin que delimitan cada mensaje, hechas con un cambio de SDA en un momento en que normalmente no cambia.
  • Bytes de ocho bits, el más significativo primero, cada uno seguido de un noveno pulso de reloj en el que el receptor confirma.
  • Una dirección de siete bits en el primer byte, junto con un bit que dice si el maestro va a escribir o a leer.
  • Confirmaciones (ACK) o no confirmaciones (NACK), que le dicen al emisor si el byte llegó.

Todo mensaje sigue el mismo esquema, que es el de la figura de la sección 06: START, dirección + R/W, confirmación, datos con sus confirmaciones, STOP. Quien lo inicia es siempre un maestro, y todos los dispositivos del bus escuchan los primeros nueve bits: solo el que reconoce su dirección sigue participando.

02 · Delimitar el mensaje

START y STOP

En el tema 16 vimos la regla de sincronismo: SDA solo cambia mientras SCL está en bajo, y se lee mientras SCL está en alto. Las dos únicas excepciones a esa regla son justamente las marcas que delimitan un mensaje:

Condiciones de inicio y de fin SCL y SDA en reposo están en alto. El inicio es una caída de SDA mientras SCL está en alto. Después SDA cambia solo mientras SCL está en bajo y se mantiene estable mientras SCL está en alto. El fin es una subida de SDA mientras SCL está en alto. SCLSDA STARTSTOP SDA baja con SCL altoSDA sube con SCL alto SCL alto: SDA estable (se lee el bit) SCL bajo: SDA puede cambiar SCL bajo
  • START (S). SDA pasa de alto a bajo mientras SCL está en alto. Con esto el maestro anuncia que va a usar el bus: todos los dispositivos se ponen a escuchar. Después del START el maestro baja SCL y empieza a enviar bits.
  • STOP (P). SDA pasa de bajo a alto mientras SCL está en alto. El maestro da por terminado el mensaje y libera el bus: tras un STOP, SDA y SCL quedan en alto y cualquier maestro puede empezar otro.
  • START repetido (Sr). Es un START que se envía sin pasar antes por un STOP. Sirve para cambiar de sentido (por ejemplo, de escribir un registro a leerlo) sin soltar el bus, de modo que ningún otro maestro se meta en el medio. Eléctricamente es igual a un START.

Entre un STOP y el START siguiente el bus tiene que quedar libre un tiempo mínimo, y cada marca tiene sus tiempos de preparación y retención:

Tiempos mínimos de las condiciones de bus (valores de la especificación, en µs).
ParámetroQué esModo estándarModo rápido
tHD;STACon SDA ya baja, cuánto debe pasar antes de bajar SCL4,00,6
tSU;STAPreparación de un START repetido (SCL alta antes de bajar SDA)4,70,6
tSU;STOPreparación del STOP (SCL alta antes de subir SDA)4,00,6
tBUFBus libre entre un STOP y el START siguiente4,71,3
tLOW / tHIGHDuración mínima de SCL en bajo y en alto4,7 / 4,01,3 / 0,6

Estos valores explican por qué 100 kHz es la velocidad del modo estándar (el período mínimo es 4,7 + 4,0 µs, algo menos de 10 µs) y 400 kHz la del rápido (1,3 + 0,6 µs, que se redondea hacia arriba con los flancos). También dan la receta para un maestro por software: bastan unos 5 µs de pausa entre un cambio y el siguiente.

Una consecuencia práctica: un STOP o un START falso es un error grave. Si por ruido SDA cambia mientras SCL está en alto, los dispositivos lo interpretan como una marca y descartan o reinterpretan el mensaje. Por eso el rebote del sensor, un cable largo o una masa deficiente se manifiestan como mensajes «partidos».

03 · La unidad de transferencia

Un byte y su confirmación

Entre un START y un STOP, la información viaja en bytes de ocho bits con el bit más significativo primero. Para cada byte, el emisor pone el bit en SDA mientras SCL está en bajo, y el receptor lo toma cuando SCL está en alto. Después de los ocho bits llega un noveno pulso de reloj, que no transporta datos sino la confirmación:

Un byte de dirección y su confirmación Nueve pulsos de SCL. En los ocho primeros el maestro envía los bits 1, 0, 0, 1, 0, 0, 0, 0, que son la dirección 0x48 en siete bits y el bit de escritura. En el noveno pulso el maestro suelta SDA y el esclavo la baja para confirmar. SCLSDA 123456789 100100000 A6A5A4A3A2A1A0R/WACK el esclavo baja SDA

En el dibujo, el maestro envía el byte 0x90 (1001 0000), que es la dirección 0x48 con el bit de escritura. Durante los ocho primeros pulsos maneja SDA el maestro. En el noveno el maestro suelta SDA y es el receptor el que, si aceptó el byte, la baja durante ese pulso. Como las salidas son de colector abierto (tema 16), el maestro ve en SDA el resultado de lo que hace el otro:

  • SDA en bajo en el noveno pulso: ACK (acknowledge). «Recibí el byte y estoy listo para seguir».
  • SDA en alto en el noveno pulso: NACK (not acknowledge). Nadie bajó la línea y la pull-up la dejó arriba.

Cuánto cuesta esto: cada byte son 9 pulsos de reloj, así que a 100 kHz una transferencia de datos no pasa de 11 100 bytes por segundo, y a 400 kHz de 44 400 (tema 16). A esto hay que sumar los bytes de dirección de cada mensaje.

Un dato de varios bytes, como una medición de 16 bits, se manda byte por byte, y el orden de los bytes lo define cada dispositivo: la mayoría envía primero el byte alto, pero hay chips que envían primero el bajo. No es parte de I²C sino de la hoja de datos.

04 · A quién se le habla

La dirección de 7 bits

El primer byte después de un START tiene dos partes: los siete bits más significativos son la dirección del dispositivo, y el bit menos significativo es R/W, que le dice al esclavo qué va a pasar a continuación:

byte enviado = (dirección << 1) | R/W  R/W = 0: el maestro escribe R/W = 1: el maestro lee

Por ejemplo, para un dispositivo en la dirección 0x48 (100 1000 en siete bits): el byte de escritura es 0x48 << 1 = 0x90 y el de lectura, 0x91. Todos los dispositivos comparan esos siete bits con su propia dirección; el que coincide responde con ACK y el resto se desentiende hasta el próximo START.

Con siete bits hay 128 combinaciones, pero no todas se pueden usar. La especificación reserva dos grupos de direcciones:

Direcciones reservadas de 7 bits. Quedan 112 libres, de 0x08 a 0x77.
DirecciónUso
0x00Llamada general: el maestro le habla a todos los dispositivos a la vez (por ejemplo, para un reinicio). Con R/W = 1 es el «byte de inicio»
0x01Reservada para el bus CBUS, un protocolo antiguo que podía coexistir con I²C
0x02 y 0x03Reservadas para otros formatos de bus y para usos futuros
0x04 a 0x07Código de maestro del modo de alta velocidad (Hs)
0x78 a 0x7BPrefijo de las direcciones de 10 bits: 1111 0XX, con dos bits más de dirección y un segundo byte con los ocho restantes
0x7C a 0x7FReservadas (entre ellas, la 0x7C para la identificación del dispositivo)

En la práctica, un dispositivo común usa direcciones de 7 bits entre 0x08 y 0x77. Las direcciones de 10 bits existen pero se usan muy poco. Lo que sí importa es cómo se asigna la dirección a cada chip:

  • Los fabricantes fijan una parte fija (la familia del dispositivo) y dejan de uno a tres bits configurables mediante pines (A0, A1, A2) que se conectan a masa o a VDD. Un PCF8574 (expansor de pines) usa 0x20 más tres pines: de 0x20 a 0x27, o de 0x38 a 0x3F en la variante A. Una memoria 24C02 va de 0x50 a 0x57.
  • Otros dispositivos tienen una sola dirección fija (el reloj DS3231, en 0x68) o dos opciones (el sensor BME280, 0x76 o 0x77, según un pin; el MPU6050, 0x68 o 0x69; la pantalla SSD1306, 0x3C o 0x3D).

Dos dispositivos con la misma dirección en el mismo bus responden a la vez y se mezclan sus datos: es el problema de las «direcciones repetidas». Las soluciones (cambiar un pin, un multiplexor I²C, un segundo bus) las vemos en el tema 19. Por ahora, la regla es leer la dirección de cada dispositivo antes de comprarlo, y no depender de que el módulo permita cambiarla.

05 · Confirmar y no confirmar

ACK y NACK

El noveno pulso tiene un sentido que cambia según el sentido de los datos: confirma siempre el que recibe el byte. Eso da dos situaciones:

El maestro envía (escritura)

Después de cada byte (la dirección, el registro, cada dato) el esclavo responde. ACK: «recibido». NACK: «no puedo aceptarlo». Si nadie contesta la dirección, el maestro lo detecta por el NACK y puede abortar.

El maestro recibe (lectura)

Después de la dirección, el esclavo confirma. Pero luego manda datos y es el maestro quien confirma cada byte. Con ACK le dice «seguí». Con un NACK en el último byte le dice «no mandes más»; recién entonces puede enviar un STOP.

El NACK tiene entonces cuatro orígenes bien distintos:

  1. Nadie tiene esa dirección. Se mandó el byte de dirección y ningún dispositivo bajó SDA. Es el motivo de la mayoría de los «mi sensor no responde»: dirección mal escrita (en notación de 8 bits, por ejemplo), dispositivo sin alimentación, cableado flojo o falta de pull-up.
  2. El dispositivo existe pero está ocupado. Una memoria EEPROM, mientras escribe internamente (unos 5 ms), no atiende el bus: no confirma su dirección. La solución es reintentar hasta que conteste (acknowledge polling).
  3. Rechazó un dato. La dirección se confirmó pero un byte posterior no: un registro inexistente, un valor fuera de rango o un buffer lleno.
  4. Fin normal de una lectura. El maestro da NACK al último byte que quiere recibir. Es la señal prevista para terminar, no un error.

Tené en cuenta que un ACK dice solo que el byte se recibió, no que el comando tenga sentido ni que el dispositivo funcione correctamente. Un sensor mal configurado contesta ACK a todo.

La biblioteca Wire entrega este resultado en el valor que devuelve endTransmission():

Códigos devueltos por Wire.endTransmission().
CódigoSignificadoQué ocurrió en el bus
0ÉxitoACK en la dirección y en todos los datos
1Datos demasiado largosNo entran en el buffer de transmisión: no se llegó a mandar nada
2NACK al enviar la direcciónNadie contestó (o el dispositivo estaba ocupado)
3NACK al enviar un datoLa dirección se confirmó pero un dato fue rechazado
4Otro errorPor ejemplo, un fallo del bus (pérdida de arbitraje)
5Tiempo agotadoEl bus no respondió en el tiempo previsto (línea trabada)

El código 2 es el más útil: enviar solo la dirección, sin datos, y mirar si el resultado es 0, equivale a preguntar «¿hay alguien ahí?». Es lo que hace un detector de dispositivos del bus (tema 18).

06 · Todo junto

Los mensajes completos

Estructura de los tres mensajes básicos Escritura: inicio, dirección con bit de escritura, confirmación, uno o más datos con su confirmación y fin. Lectura: inicio, dirección con bit de lectura, confirmación, datos del esclavo confirmados por el maestro excepto el último, que termina con no confirmación, y fin. Escritura seguida de lectura: igual que una escritura de un registro pero sin fin, con un inicio repetido y una lectura. EscrituraSdirección (7 bits)W=0Adato 1A…dato nAP LecturaSdirección (7 bits)R=1Adato 1A…dato nNP Escribir el registro y leer (con inicio repetido)SdirecciónWAregistroASrdirecciónRAdato 1A…dato nNP lo envía el maestro lo envía el esclavo · A = confirma (ACK) · N = no confirma (NACK)

Con las piezas anteriores se arman tres tipos de mensaje. Los símbolos son los de las cajas: S inicio, Sr inicio repetido, A ACK, N NACK, P fin.

  • Escritura. S dir+W A dato A dato A … P. El maestro envía una cantidad cualquiera de bytes. En la mayoría de los dispositivos, el primero es la dirección de un registro interno y los siguientes son los valores que se escriben ahí y en los registros consecutivos.
  • Lectura. S dir+R A dato A dato N P. El esclavo envía; el maestro confirma cada byte salvo el último. Sin indicar qué leer: el dispositivo manda lo que corresponda a su registro actual.
  • Escritura seguida de lectura. S dir+W A reg A Sr dir+R A dato A … dato N P. Es el mensaje más usado: se escribe el número del registro que se quiere leer y, sin soltar el bus (con un START repetido), se pasa a leer. Si en lugar del Sr se pusiera un STOP y un START, muchos dispositivos funcionarían igual, pero otros pierden el puntero de registro y algún maestro podría colarse entre ambos.

Dos cuentas para dimensionar un mensaje. Pulsos de reloj = 9 × (cantidad de bytes, contando cada dirección); los START y STOP no suman pulsos de datos, pero sí un poco de tiempo. Y tiempo = pulsos / frecuencia. Una lectura de dos bytes de un registro (0x68, registro 0x01) son 5 bytes: dirección, registro, dirección, dato y dato; 45 pulsos, o 450 µs a 100 kHz y 112,5 µs a 400 kHz.

Dos casos especiales que conviene reconocer en una captura. La llamada general (dirección 0x00 con escritura) la reciben todos los dispositivos; en ella nadie envía datos de vuelta, y se usa para comandos como un reinicio de todo el bus. Y las direcciones de 10 bits empiezan con el byte 1111 0XX0 (que contiene los dos bits altos de la dirección) y siguen con un segundo byte con los ocho bits bajos; son muy raras en los proyectos habituales.

07 · Con el microcontrolador

Con el microcontrolador

Para entender el protocolo conviene escribirlo una vez a mano. El primer programa es un maestro I²C por software (bit-banging) con las funciones del tema 16 para manejar una línea como colector abierto: bajar un pin y soltarlo, nunca poner un pin en alto. Cada función corresponde a una pieza de las que vimos: START, STOP, enviar un byte y leer la confirmación, recibir un byte y dar el ACK o NACK. Con ellas se arma ping(), que pregunta si una dirección contesta.

const byte PIN_SDA = 21;
const byte PIN_SCL = 22;
const unsigned int MEDIO_US = 5;       // medio período: unos 100 kHz o menos

inline void bajar(byte pin)  { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); }
inline void soltar(byte pin) { pinMode(pin, INPUT); }          // la pull-up externa sube la línea
inline bool leer(byte pin)   { return digitalRead(pin); }
inline void medio()          { delayMicroseconds(MEDIO_US); }

void i2cStart() {                      // SDA baja mientras SCL está alta
    soltar(PIN_SDA); soltar(PIN_SCL); medio();
    bajar(PIN_SDA);  medio();
    bajar(PIN_SCL);                    // desde acá SDA puede cambiar
}

void i2cStop() {                       // SDA sube mientras SCL está alta
    bajar(PIN_SDA);  medio();
    soltar(PIN_SCL); medio();
    soltar(PIN_SDA); medio();
}

bool i2cEscribirByte(byte b) {         // devuelve true si el esclavo contestó ACK
    for (byte i = 0; i < 8; i++) {
        if (b & 0x80) soltar(PIN_SDA); else bajar(PIN_SDA);   // el bit más significativo primero
        medio();
        soltar(PIN_SCL); medio();      // SCL alta: el esclavo toma el bit
        bajar(PIN_SCL);
        b <<= 1;
    }
    soltar(PIN_SDA);                   // noveno pulso: el maestro suelta SDA
    medio();
    soltar(PIN_SCL); medio();
    bool ack = !leer(PIN_SDA);         // si el esclavo la bajó, hay ACK
    bajar(PIN_SCL);
    return ack;
}

byte i2cLeerByte(bool darAck) {
    byte b = 0;
    soltar(PIN_SDA);                   // ahora maneja SDA el esclavo
    for (byte i = 0; i < 8; i++) {
        medio();
        soltar(PIN_SCL); medio();
        b = (b << 1) | leer(PIN_SDA); // se lee con SCL alta
        bajar(PIN_SCL);
    }
    if (darAck) bajar(PIN_SDA); else soltar(PIN_SDA);   // ACK = bajar; NACK = dejar subir
    medio();
    soltar(PIN_SCL); medio();
    bajar(PIN_SCL);
    soltar(PIN_SDA);
    return b;
}

bool ping(byte dir7) {                 // S dir+W [A/N] P
    i2cStart();
    bool ack = i2cEscribirByte((dir7 << 1) | 0);
    i2cStop();
    return ack;
}

void setup() {
    Serial.begin(115200);
    soltar(PIN_SDA); soltar(PIN_SCL);
    const byte probar[] = { 0x48, 0x68, 0x3C };
    for (byte d : probar) {
        Serial.print("0x"); Serial.print(d, HEX);
        Serial.println(ping(d) ? ": ACK" : ": NACK (nadie contesta)");
    }
}

void loop() {}

Tres puntos del código. SDA solo se cambia con SCL en bajo: por eso cada bit se pone después de bajar(PIN_SCL). START y STOP rompen esa regla a propósito: en i2cStart() se baja SDA con SCL alta, y en i2cStop() se sube con SCL alta. Y el ACK se lee soltando SDA: si el maestro la manejara, no podría ver lo que hace el esclavo. Este maestro no maneja el estiramiento del reloj (un esclavo que mantiene SCL en bajo), tema del 19; con dispositivos lentos habría que esperar a que SCL suba realmente antes de seguir.

El segundo programa hace lo mismo con la biblioteca Wire, que genera todas estas señales con el periférico de hardware, y muestra el uso del START repetido para leer un registro:

#include <Wire.h>

const char *explicar(byte codigo) {
    switch (codigo) {
        case 0: return "ACK en todo el mensaje";
        case 1: return "datos demasiado largos para el buffer";
        case 2: return "NACK en la dirección: nadie contesta o está ocupado";
        case 3: return "NACK en un dato: el dispositivo lo rechazó";
        case 4: return "otro error del bus";
        case 5: return "tiempo agotado: línea trabada";
        default: return "código desconocido";
    }
}

bool ping(byte dir7) {                 // S dir+W [A/N] P
    Wire.beginTransmission(dir7);      // Wire usa la dirección de 7 bits y agrega R/W
    return Wire.endTransmission() == 0;
}

// S dir+W A reg A Sr dir+R A dato ... dato N P
int leerRegistro(byte dir7, byte registro, byte *destino, byte n) {
    Wire.beginTransmission(dir7);
    Wire.write(registro);
    byte codigo = Wire.endTransmission(false);     // false: sin STOP, queda pendiente el START repetido
    if (codigo != 0) return -codigo;
    byte recibidos = Wire.requestFrom(dir7, n);    // Sr + lectura de n bytes; NACK en el último; STOP
    for (byte i = 0; i < recibidos; i++) destino[i] = Wire.read();
    return recibidos;
}

void setup() {
    Serial.begin(115200);
    Wire.begin();

    Wire.beginTransmission(0x49);                  // una dirección donde no hay nadie
    Wire.write(0x01);
    byte codigo = Wire.endTransmission();
    Serial.print("Escribir en 0x49: "); Serial.print(codigo); Serial.print(" - "); Serial.println(explicar(codigo));

    byte datos[2];
    int r = leerRegistro(0x68, 0x01, datos, 2);
    if (r < 0) { Serial.print("Falló la escritura del registro: "); Serial.println(explicar(-r)); }
    else { Serial.print("Leídos "); Serial.print(r); Serial.println(" bytes"); }
}

void loop() {}

Comparando con el primero: beginTransmission + endTransmission arma un mensaje de escritura completo, con dirección, bytes y STOP; con endTransmission(false) el STOP no se envía y el siguiente requestFrom arranca con un START repetido; y requestFrom se ocupa de dar ACK a todos los bytes menos el último y cerrar con NACK y STOP. En el tema 18 usamos estas funciones para trabajar con los registros de un sensor real.

08 · Analogía con programación

Los mensajes en Python

Un mensaje I²C es una lista de símbolos, así que se puede modelar sin hardware. El programa siguiente arma esa lista para una escritura, una lectura y una escritura seguida de lectura sobre dos dispositivos virtuales, devuelve el código que daría Wire y cuenta los pulsos de reloj. Sirve para escribir y probar un controlador antes de tener el sensor, y para contrastar después con la captura real.

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

PRESENTES = {                        # dirección de 7 bits -> registros del dispositivo
    0x48: bytes([0x85, 0x83]),
    0x68: bytes([0x30, 0x45, 0x12, 0x03]),
}


def valida(direccion):
    return 0x08 <= direccion <= 0x77   # fuera de este rango están las reservadas


def byte_dir(direccion, leer):
    return (direccion << 1) | (1 if leer else 0)


def hexa(b):
    return f"{b:#04x}"


def escribir(direccion, datos):
    ev = ["S", f"{hexa(byte_dir(direccion, False))}(W)"]
    if direccion not in PRESENTES:
        return ev + ["N", "P"], 2        # nadie baja SDA en el noveno pulso
    ev.append("A")
    for d in datos:
        ev += [hexa(d), "A"]
    return ev + ["P"], 0


def leer(direccion, n, inicio=0, repetido=False):
    ev = ["Sr" if repetido else "S", f"{hexa(byte_dir(direccion, True))}(R)"]
    if direccion not in PRESENTES:
        return ev + ["N", "P"], []
    ev.append("A")
    datos = []
    for i in range(n):
        registros = PRESENTES[direccion]
        d = registros[inicio + i] if inicio + i < len(registros) else 0xFF
        datos.append(d)
        ev += [hexa(d), "A" if i < n - 1 else "N"]   # el maestro da NACK al último byte
    return ev + ["P"], datos


def registro_y_leer(direccion, registro, n):
    ev, codigo = escribir(direccion, [registro])
    if codigo:
        return ev, []
    ev2, datos = leer(direccion, n, registro, repetido=True)
    return ev[:-1] + ev2, datos          # se quita el P de la escritura: queda el Sr


def pulsos(ev):
    return 9 * sum(1 for e in ev if e.startswith("0x"))


def mostrar(titulo, ev, extra=""):
    print(f"{titulo}\n   {' '.join(ev)}   [{pulsos(ev)} pulsos]{extra}")


ev, codigo = escribir(0x48, [0x01, 0x83])
mostrar("Escribir 2 bytes en 0x48", ev, f"  endTransmission = {codigo}")
ev, codigo = escribir(0x49, [0x01])
mostrar("Escribir en 0x49 (no hay nadie)", ev, f"  endTransmission = {codigo}")
ev, datos = leer(0x68, 3)
mostrar("Leer 3 bytes de 0x68", ev, f"  datos = {[hexa(d) for d in datos]}")
ev, datos = registro_y_leer(0x68, 0x01, 2)
mostrar("Registro 0x01 de 0x68, 2 bytes, con START repetido", ev, f"  datos = {[hexa(d) for d in datos]}")
p = pulsos(ev)
print(f"   tiempo: {p / 100e3 * 1e6:.1f} µs a 100 kHz, {p / 400e3 * 1e6:.1f} µs a 400 kHz")

print()
print("Direcciones de 7 bits válidas:", " ".join(f"{d:#04x}:{valida(d)}" for d in (0x00, 0x07, 0x08, 0x48, 0x77, 0x78)))
print("Total de direcciones libres:", sum(valida(d) for d in range(128)))
print(f"La hoja dice 0x90 (8 bits) -> dirección de 7 bits {0x90 >> 1:#04x}; bytes {byte_dir(0x48, False):#04x} y {byte_dir(0x48, True):#04x}")

Resultado: escribir dos bytes en 0x48 da S 0x90(W) A 0x01 A 0x83 A P con 27 pulsos y código 0. Escribir en 0x49 da S 0x92(W) N P: 9 pulsos y código 2, porque nadie confirma. Leer tres bytes de 0x68 da S 0xd1(R) A 0x30 A 0x45 A 0x12 N P, con 36 pulsos y el NACK final del maestro. La lectura del registro 0x01 con START repetido es S 0xd0(W) A 0x01 A Sr 0xd1(R) A 0x45 A 0x12 N P: 45 pulsos, que son 450,0 µs a 100 kHz y 112,5 µs a 400 kHz, y devuelve 0x45 y 0x12. De las direcciones probadas, 0x00, 0x07 y 0x78 no son válidas y 0x08, 0x48 y 0x77 sí; hay 112 libres. Y el 0x90 de una hoja de 8 bits corresponde a la dirección 0x48, cuyos bytes de escritura y de lectura son 0x90 y 0x91.

Observá que la lista de símbolos es lo que un analizador lógico muestra, y que el código que Wire entrega (0 o 2) sale del primer símbolo que no es una confirmación. Esa correspondencia es la que se usa para diagnosticar.

09 · Exploración interactiva

Laboratorio: mensajes, direcciones y confirmaciones

El laboratorio tiene tres herramientas. La primera arma un mensaje completo: elegís la dirección, el tipo de operación y los bytes, y ves los símbolos, los pulsos y el tiempo. La segunda convierte una dirección en el byte que viaja a partir de los pines de configuración de un dispositivo real. La tercera es un catálogo de ACK y NACK con la causa de cada uno.

1. Armar un mensaje

Primer byte (dirección + R/W)—
Símbolos en el bus—
Bytes · pulsos de SCL—
Tiempo a 100 kHz · a 400 kHz—
Resultado en Wire—
Veredicto—

Elegí la dirección y la operación y presioná «Armar el mensaje».

2. De los pines de dirección al byte

Dirección de 7 bits—
Byte de escritura (dir << 1 | 0)—
Byte de lectura (dir << 1 | 1)—
Direcciones posibles—
Pines que cuentan—

Elegí un dispositivo y la conexión de sus pines de dirección.

3. Catálogo de ACK y NACK

Símbolos—
Qué pasa en el noveno pulso—
Resultado en Wire—
Veredicto—

Elegí una situación para ver su patrón.

En la herramienta 1, los datos que lee el dispositivo virtual son 0xA0, 0xA1, etc.; los START y STOP no se cuentan como pulsos de reloj de datos. En la 2, los pines que no existen en el dispositivo se ignoran (el DS3231, por ejemplo, tiene una dirección fija). En la 3, los tiempos internos (como los 5 ms de la EEPROM) son típicos.

Recorrido guiado

  1. Con los valores iniciales (dirección 48, escritura de 01 83) presioná «Armar el mensaje». El primer byte es 0x90 y los símbolos son S 0x90(W) A 0x01 A 0x83 A P: son 3 bytes, 27 pulsos, 270 µs a 100 kHz y 67,5 µs a 400 kHz. El resultado en Wire es endTransmission() = 0.
  2. Cambiá a «nadie»: el mensaje se corta después de la dirección, S 0x90(W) N P, con 9 pulsos y código 2. Los datos ni siquiera se envían, porque el maestro aborta cuando nadie confirma.
  3. Dejá la escritura vacía (borrá los bytes): S 0x90(W) A P. Es el mensaje que usan los detectores de dispositivos para ver si una dirección contesta.
  4. Poné la dirección 68, elegí «Lectura» de 2 bytes: S 0xD1(R) A 0xA0 A 0xA1 N P. Observá que el último byte lleva N: el maestro avisa que no quiere más.
  5. Elegí «Escribir registro y leer» con registro 01 y 2 bytes: S 0xD0(W) A 0x01 A Sr 0xD1(R) A 0xA0 A 0xA1 N P, con 5 bytes y 45 pulsos: 450 µs a 100 kHz y 112,5 µs a 400 kHz. Hay un Sr en lugar de un P y un S.
  6. Probá la dirección 90 (la «dirección de escritura» que da alguna hoja): el laboratorio avisa que no cabe en 7 bits y que la dirección que corresponde es 0x48.
  7. Probá las direcciones 00 y 78: están reservadas y ningún dispositivo común debería contestar ahí.
  8. En la herramienta 2 con el PCF8574 y los tres pines a masa: dirección 0x20, bytes 0x40 y 0x41. Poné A0 en 1: pasa a 0x21 (0x42 y 0x43). Con los tres en 1, 0x27: ocho expansores en el mismo bus.
  9. Elegí el DS3231: da 0x68 sin importar los pines. Elegí el MPU6050 con el pin en 0: también 0x68. Ahí está el conflicto de direcciones repetidas: no se pueden conectar los dos al mismo bus sin cambiar el pin del MPU6050.
  10. En la herramienta 3 recorré los casos. «Dirección sin dispositivo» y «EEPROM ocupada» terminan igual (código 2): la dirección no se confirma. «Dato rechazado» da código 3: la dirección sí se confirmó y falló un dato. «Fin normal de una lectura» tiene NACK pero no es un error. «Lectura sin NACK final» es el caso peligroso: el esclavo sigue enviando y puede retener SDA.
Desafío: cuántos mensajes por segundo

Un sensor se lee con «escribir registro y leer 6 bytes»: S, dirección+W, registro, Sr, dirección+R y 6 datos. ¿Cuántos bytes y pulsos son, y cuántas lecturas por segundo permite el bus a 400 kHz si no hay otras pausas? Son 1 + 1 + 1 + 6 = 9 bytes y 81 pulsos: a 400 kHz son 202,5 µs, es decir, unas 4900 lecturas por segundo. A 100 kHz serían 810 µs y poco más de 1200 lecturas por segundo. En la práctica el sensor limita antes (cada medición tarda milisegundos) y los START/STOP agregan algo de tiempo.

10 · Un procedimiento

Leer una captura

Cuando un dispositivo I²C no responde, la herramienta más directa es un analizador lógico conectado a SDA y SCL (más la masa). Con el decodificador de I²C se ven los símbolos como en las secciones anteriores. Para leerlos, siempre en el mismo orden:

  1. Reposo. Antes del primer START, las dos líneas deben estar en alto. Si no, falla la parte eléctrica del tema 16.
  2. START y dirección. Después del START, ¿el byte es el que se esperaba? La mayoría de los decodificadores muestran la dirección de 7 bits y R/W por separado; si muestran el byte completo, hay que dividir por 2.
  3. Primera confirmación. ¿ACK o NACK? Un NACK acá deja al resto del mensaje sin sentido: se corrige la dirección, la alimentación o el cableado antes de seguir.
  4. Datos y confirmaciones. ¿El número de bytes es el esperado? ¿Cada uno tiene su ACK, y el último de una lectura su NACK?
  5. Cierre. ¿Hay un STOP, o un Sr si debía haber una segunda parte? Un mensaje sin STOP deja el bus ocupado y el siguiente START queda mal.
  6. Tiempos. ¿La frecuencia de SCL es la configurada? Una subida lenta (tema 16) o un esclavo que estira el reloj bajan la velocidad efectiva.
Qué se ve en la captura y qué significa.
En la capturaCausa probableQué hacer
S dir(W) N PNadie confirma la direcciónRevisar la dirección (7 u 8 bits), alimentación y conexiones; si es una memoria, esperar a que termine de escribir
ACK en la dirección y NACK en un datoEl dispositivo rechaza el registro o el valorRevisar el mapa de registros de la hoja de datos
Los bytes leídos son todos 0xFFNadie manejó SDA durante la lectura y la pull-up la dejó en altoVerificar que el dispositivo recibió el puntero de registro y que respondió con ACK
Se ve un START en medio de un byteRuido en SDA con SCL en altoAcortar cables, revisar masa, bajar la velocidad
La lectura no termina: el maestro da ACK al último byteFalta el NACK finalRevisar el código (el último byte de una lectura lleva NACK)
No se ve ninguna actividadEl maestro no está generando el mensaje (pines o configuración equivocados)Verificar los pines SDA/SCL asignados y la inicialización

El tema 18 aplica este procedimiento a los registros de un sensor y el tema 19 a los problemas más complicados (clock stretching, bus bloqueado).

11 · Comprensión

Confusiones frecuentes

«La dirección I²C tiene 8 bits»

Tiene 7. El octavo bit del primer byte es R/W. Las hojas de datos que dan «0x90 y 0x91» muestran el byte tal como viaja; la dirección es 0x48. Wire, y casi todas las bibliotecas, esperan los 7 bits.

«Un NACK siempre es un error»

No. El maestro envía un NACK al último byte que lee para avisar que no quiere más: es el final normal. Un NACK es un error cuando lo da el esclavo a la dirección o a un dato de una escritura.

«Si recibí ACK, el dispositivo hizo lo que le pedí»

El ACK solo indica que el byte fue recibido. El dispositivo puede estar mal configurado, haber ignorado el comando o estar en un modo que no esperaba. Hay que leer algo de vuelta (por ejemplo, un registro de identificación) para comprobarlo.

«endTransmission() == 0 significa que el sensor funciona»

Significa que alguien contestó en esa dirección. Podría ser otro dispositivo con la misma dirección, o el sensor correcto pero sin configurar. La prueba definitiva es leer el registro de identificación.

«Da lo mismo un STOP más un START que un START repetido»

No siempre. Con el STOP se libera el bus, otro maestro puede ocuparlo y algunos dispositivos pierden el puntero de registro o reinician su estado. Con el Sr el bus se conserva. Muchas hojas de datos exigen el START repetido para leer un registro.

«Puedo usar cualquier dirección de 0 a 127»

No. Las direcciones 0x00 a 0x07 y 0x78 a 0x7F están reservadas; quedan 112, de 0x08 a 0x77.

«El esclavo genera el reloj de los datos que me envía»

No. El reloj lo genera siempre el maestro, incluso cuando lee. El esclavo solo puede retener SCL en bajo para pedir tiempo (tema 19), pero no la maneja de otro modo.

«Da lo mismo cuándo cambia SDA, mientras no sea durante un pulso de dato»

Un cambio de SDA con SCL en alto es un START o un STOP. Si ocurre por error en medio de un byte, los dispositivos lo toman como una marca y pierden el mensaje. Los datos solo se cambian con SCL en bajo.

12 · Práctica guiada

Predecí antes de comprobar

1. El byte de dirección

Una pantalla SSD1306 está en la dirección 0x3C. ¿Qué bytes viajan por el bus para escribirle y para leerla?

Ver solución

0x3C << 1 = 0x78 para escribir y 0x79 para leer. En binario, 0111 1000 y 0111 1001.

2. Una hoja de 8 bits

La hoja de datos de un reloj dice «dirección de escritura 0xD0, dirección de lectura 0xD1». ¿Qué dirección hay que pasarle a Wire.beginTransmission()?

Ver solución

0xD0 >> 1 = 0x68. Wire agrega el bit R/W: escritura 0xD0 y lectura 0xD1 son los bytes que realmente viajan.

3. Contar pulsos y tiempo

Escribís dos registros consecutivos de un dispositivo: dirección, registro y dos datos. ¿Cuántos pulsos de reloj son y cuánto tardan a 100 kHz y a 400 kHz?

Ver solución

4 bytes × 9 pulsos = 36 pulsos: 360 µs a 100 kHz y 90 µs a 400 kHz (sin contar START, STOP ni las pausas entre mensajes).

4. Cuántos dispositivos entran

¿Cuántas direcciones libres hay? ¿Cuántos PCF8574 (0x20 a 0x27) se pueden conectar en el mismo bus? ¿Y si se mezclan con la variante PCF8574A (0x38 a 0x3F)?

Ver solución

Hay 112 direcciones libres (0x08 a 0x77). Con tres pines de dirección se conectan 8 PCF8574. Mezclando las dos variantes, cuyas direcciones no se superponen, hasta 16 expansores.

5. Decodificar una captura

Después de un START, el analizador muestra estos bits de SDA, uno por pulso de SCL: 1 1 0 1 0 0 0 1 | 0, luego 0 0 1 1 0 0 0 0 | 0, luego 0 1 0 0 0 1 0 1 | 1, y un STOP. ¿Qué mensaje es?

Ver solución

El primer byte es 1101 0001 = 0xD1: dirección 0x68 y bit de lectura; el noveno bit es 0, ACK del esclavo. El segundo byte es 0011 0000 = 0x30, con ACK (0) del maestro. El tercero es 0100 0101 = 0x45, con NACK (1) del maestro: es el último. Es una lectura de dos bytes de 0x68 (0x30 y 0x45), cerrada con STOP: un fin normal.

6. Qué código devuelve Wire

¿Qué código de endTransmission() esperás si (a) la dirección está mal escrita, (b) la memoria EEPROM está en pleno ciclo de escritura, (c) escribís un valor inválido en un registro que el sensor rechaza?

Ver solución

(a) y (b) dan 2: la dirección no se confirma. (c) da 3: la dirección se confirmó pero un dato no. Para distinguir (a) de (b) se reintenta unos milisegundos: la EEPROM terminará contestando y la dirección equivocada no.

7. Tiempo del maestro por software

En el programa de la sección 07, cada cambio espera 5 µs (medio()). ¿Cuánto tarda un ping() aproximadamente, y a qué frecuencia de SCL equivale?

Ver solución

Cada bit usa dos medios períodos: 10 µs, así que SCL queda en 100 kHz o algo menos (las llamadas a pinMode y digitalWrite agregan tiempo). El START usa 2 pausas (10 µs), el byte con su confirmación 9 × 10 µs = 90 µs y el STOP 3 pausas (15 µs): unos 115 µs en total, más el costo de las llamadas.

13 · Síntesis

Ideas para recordar

  • Un mensaje I²C va de un START a un STOP. START: SDA baja con SCL alto; STOP: SDA sube con SCL alto. Es la única vez que SDA cambia con SCL en alto; los datos cambian solo con SCL en bajo y se leen con SCL en alto.
  • Un START repetido (Sr) cambia de sentido sin liberar el bus: se usa para escribir el número de registro y leerlo en un solo mensaje.
  • Todo byte son 8 bits (el más significativo primero) más un noveno pulso de confirmación: nueve pulsos de reloj por byte. El receptor confirma bajando SDA (ACK); si la línea queda en alto es NACK.
  • El primer byte es (dirección << 1) | R/W. La dirección tiene 7 bits; R/W = 0 escribe y R/W = 1 lee. Wire usa la dirección de 7 bits.
  • Las direcciones 0x00 a 0x07 y 0x78 a 0x7F están reservadas: quedan 112 (0x08 a 0x77). Cada chip fija parte de la dirección y deja uno a tres bits a los pines; dos chips con la misma dirección en un bus chocan.
  • Quien recibe el byte confirma: en una escritura, el esclavo; en una lectura, el maestro. El maestro envía NACK al último byte que lee, y eso es normal.
  • Un NACK en la dirección (código 2 de Wire) significa que nadie contestó o que el dispositivo está ocupado; un NACK en un dato (código 3), que se lo rechazó. Un ACK no prueba que el dispositivo funcione.
  • Pulsos = 9 × bytes, tiempo = pulsos / frecuencia. Una lectura de registro de 2 bytes son 45 pulsos: 450 µs a 100 kHz y 112,5 µs a 400 kHz.
  • Para depurar se mira la captura en orden: reposo, START, dirección, primera confirmación, datos con sus confirmaciones, STOP.

¿Listo para el siguiente tema?

Antes de avanzar, calculá los bytes de escritura y de lectura de un dispositivo en la dirección 0x57; escribí la secuencia de símbolos para leer 3 bytes empezando en el registro 0x10 de un dispositivo en 0x50; y explicá qué indica un código 3 de endTransmission() y en qué se distingue de un código 2. (Para la primera: 0x57 << 1 = 0xAE y 0xAF.) Si podés justificar las tres respuestas, tenés el protocolo de I²C.

En el próximo tema usamos la biblioteca Wire para leer y escribir los registros de un sensor real: el mapa de registros, el barrido de direcciones y los datos de varios bytes.