← Índice del curso

Microcontroladores · Tema 33

Bus I2C

Con solo dos cables, un microcontrolador puede hablar con decenas de dispositivos: sensores de temperatura, pantallas, relojes, memorias, acelerómetros. Cada uno tiene su dirección y todos comparten las mismas dos líneas. I2C (también llamado TWI) es el bus que más sensores usa en los proyectos con microcontroladores.

01 · Punto de partida

Dos cables para muchos dispositivos

En el tema 31 vimos que una UART conecta solo dos extremos y que SPI necesita una línea de selección por cada esclavo. I2C (Inter-Integrated Circuit, inventado por Philips en 1982) resuelve otro problema: conectar muchos dispositivos lentos con el menor número de cables. Usa dos líneas compartidas por todos: SDA (datos) y SCL (reloj). Cada dispositivo tiene una dirección de 7 bits y solo responde cuando el maestro la nombra.

Es el bus de los módulos baratos: el sensor de temperatura TMP102, el acelerómetro MPU6050, el reloj DS3231, el sensor de presión BMP280, las pantallas OLED SSD1306. Aprender I2C significa, en la práctica, aprender a leer la hoja de datos de esos chips: dirección, registros y una secuencia de bytes.

En el ATmega328P, el hardware I2C se llama TWI (Two-Wire Interface) y usa los pines PC4 (SDA) y PC5 (SCL), que en el Arduino Uno son A4 y A5.

02 · El circuito

SDA y SCL: colector abierto

Bus I2C con resistencias de pull-up Dos resistencias de pull-up unen las líneas SDA y SCL a la alimentación. Un maestro y tres esclavos se conectan a ambas líneas con salidas de colector abierto, que solo pueden llevar la línea a masa. Vcc (5 V o 3,3 V) RpRp SDASCL Maestromicrocontrolador Esclavo 1dir. 0x48 Esclavo 2dir. 0x68 Esclavo 3dir. 0x3C

Cada línea, SDA y SCL, está conectada a Vcc mediante una resistencia (pull-up). Ningún dispositivo entrega tensión a la línea: todos tienen una salida de colector abierto (en un microcontrolador, open-drain), que solo puede llevar la línea a masa o dejarla flotar. Si ningún dispositivo la baja, la resistencia la sube a Vcc. El resultado es una función AND por cable (wired-AND): la línea está en alto solo si todos la sueltan.

Esto tiene cuatro consecuencias importantes:

  • No hay cortocircuitos entre salidas. Si dos dispositivos transmiten a la vez, uno baja y el otro suelta: la línea queda en bajo, sin daño. Es lo que permite varios maestros y el estiramiento del reloj.
  • Los flancos de subida son lentos. Suben por una constante RC (resistencia × capacidad del bus) mientras que los de bajada son rápidos y activos. Esto limita la velocidad.
  • Se pueden mezclar tensiones (por ejemplo, 3,3 V y 5 V) poniendo los pull-ups a la tensión menor, siempre que las entradas de 5 V reconozcan el nivel alto de 3,3 V. Hace falta cuidado y, a menudo, un conversor de nivel.
  • Los pull-ups no son opcionales. Sin ellos, el bus nunca sube. En los pines del ATmega328P se pueden activar los pull-ups internos (unos 20–50 kΩ), que son demasiado débiles para I2C; la biblioteca Wire de Arduino los activa de todas formas, y muchos módulos traen pull-ups propios de 4,7 kΩ o 10 kΩ.

03 · Cuánto valen

Las resistencias de pull-up

El valor de la resistencia es un compromiso entre dos límites. Hacia abajo, un dispositivo que baja la línea tiene que poder absorber la corriente de la resistencia y dejar la tensión por debajo de 0,4 V; la especificación considera 3 mA:

Rmin = (Vcc − 0,4 V) / 3 mA (1533 Ω con 5 V; 967 Ω con 3,3 V)

Hacia arriba, la línea debe subir a tiempo. El tiempo de subida entre el 30 % y el 70 % de Vcc en una red RC es 0,8473 · R · Cb, donde Cb es la capacidad total del bus (pines, cable, pistas). Debe ser menor que 1000 ns en el modo estándar (100 kHz) y 300 ns en el rápido (400 kHz):

Rmax = tr / (0,8473 · Cb) (con 200 pF y 100 kHz: 5,9 kΩ)
Rangos de la resistencia de pull-up, con 5 V.
Modotr máximoCbRminRmaxValor típico
100 kHz1000 ns200 pF1533 Ω5901 Ω4,7 kΩ
400 kHz300 ns100 pF1533 Ω3541 Ω2,2 kΩ a 3,3 kΩ
400 kHz300 ns300 pF1533 Ω1180 ΩNo hay valor: Rmin > Rmax

La última fila ilustra el límite del bus: cuando la capacidad crece (cables largos, muchos dispositivos), el rango se cierra y desaparece. La especificación permite como máximo 400 pF. Las soluciones son bajar la velocidad, acortar los cables, reducir los dispositivos o usar un amplificador activo de bus.

Si conectás varios módulos de sensores, cada uno con sus pull-ups, quedan en paralelo: tres placas con 4,7 kΩ forman 1,57 kΩ, justo en el límite inferior. Con más placas, la resistencia equivalente baja de Rmin y los niveles bajos dejan de ser válidos. Algunos módulos permiten cortarlos con un puente.

04 · Reglas de la línea

Inicio, parada y bits

Un único reloj, SCL, lo genera el maestro. Los datos viajan por SDA con una regla simple: SDA solo puede cambiar cuando SCL está en bajo; mientras SCL está en alto, SDA debe permanecer estable, y el receptor lo lee en el flanco de subida. La única excepción son dos señales especiales, que cambian SDA con SCL en alto:

  • START (S): SDA baja mientras SCL está en alto. Inicia una transacción.
  • STOP (P): SDA sube mientras SCL está en alto. La termina y libera el bus.
  • START repetido (Sr): un START sin STOP intermedio. Permite cambiar de escritura a lectura conservando el control del bus.

Cada byte se envía con el bit más significativo primero, seguido de un noveno pulso de reloj, el ACK: el receptor baja SDA para decir «recibido» (ACK = 0) o la deja alta para decir «no» (NACK = 1). El que transmite suelta la línea durante ese pulso. Un byte ocupa, por lo tanto, 9 pulsos de reloj.

El NACK tiene varios significados: en la dirección, «no hay nadie con esa dirección» (o está ocupado); en un dato escrito, «no acepto más»; en un dato leído, es el maestro quien lo envía para avisar que el último byte fue suficiente.

05 · Quién y qué

Direcciones y transacciones

Cada transacción empieza con un byte de dirección: los 7 bits superiores son la dirección del esclavo y el bit menos significativo es R/W (0 = el maestro escribe, 1 = el maestro lee). Un dispositivo en la dirección 0x48 recibe, entonces, el byte 0x90 para escribirle y 0x91 para leerlo.

Casi todos los dispositivos organizan sus datos en registros numerados. Escribir uno es enviar la dirección con W, el número de registro y los datos. Leerlo requiere dos pasos: primero se escribe el número de registro (para que el esclavo «apunte» a él) y luego se hace un START repetido con la dirección y R. Después, el esclavo envía bytes; el maestro responde ACK a cada uno excepto el último, que cierra con NACK.

Lectura de un registro de 2 bytes (el dispositivo 0x48, registro 0x00).
PasoQuiénQué se envíaRespuesta
1MaestroSTART—
2Maestro0x90 (dirección 0x48 + W)ACK del esclavo
3Maestro0x00 (registro)ACK del esclavo
4MaestroSTART repetido—
5Maestro0x91 (dirección 0x48 + R)ACK del esclavo
6EsclavoByte altoACK del maestro
7EsclavoByte bajoNACK del maestro
8MaestroSTOP—

Una transacción así consume 5 bytes en el bus: 48 pulsos de reloj, es decir, 480 µs a 100 kHz o 120 µs a 400 kHz. La eficiencia es baja (solo 16 de 48 bits son datos), lo que explica por qué I2C sirve para sensores lentos y no para mover grandes volúmenes.

Dos advertencias sobre las direcciones. Primera: las direcciones 0x00–0x07 y 0x78–0x7F están reservadas (llamada general, direcciones de 10 bits y otras). Segunda: algunas hojas de datos indican la dirección como un byte de 8 bits (por ejemplo 0xD0 y 0xD1 para un reloj DS3231) y otras como 7 bits (0x68). Son lo mismo: 0xD0 = 0x68 << 1. Confundirlas es la causa más frecuente de «no responde». Algunas direcciones típicas: 0x48 (sensor de temperatura TMP102), 0x68 (reloj DS3231 y acelerómetro MPU6050), 0x3C (pantalla OLED SSD1306) y 0x76 o 0x77 (sensor de presión BMP280); verificá siempre en el datasheet o con un escáner.

06 · Casos especiales

Velocidades, estiramiento y arbitraje

Modos de velocidad de I2C.
ModoFrecuencia de SCL
Estándar100 kHz
Rápido (fast)400 kHz
Rápido plus1 MHz
Alta velocidad (high speed)3,4 MHz

El ATmega328P especifica hasta 400 kHz. La velocidad real del bus la manda el dispositivo más lento: si uno solo admite 100 kHz, todo el bus corre a 100 kHz.

Dos mecanismos nacen del colector abierto:

  • Estiramiento del reloj (clock stretching): un esclavo lento puede mantener SCL en bajo después de que el maestro la soltó, para pedir más tiempo (por ejemplo, un sensor que necesita terminar una conversión). El maestro debe esperar hasta que SCL realmente suba. Un maestro que ignora esto lee datos incorrectos.
  • Arbitraje: si dos maestros comienzan a la vez, ambos transmiten y comparan lo que ven en SDA con lo que enviaron. El que envía un 1 pero ve un 0 perdió y se retira sin destruir el mensaje del ganador. No se pierden datos ni hay colisión destructiva.

Las direcciones de 10 bits (con un prefijo reservado) existen pero son raras. En proyectos de aficionados lo normal es un maestro y varios esclavos de 7 bits.

07 · Hardware

El módulo TWI del ATmega328P

El módulo TWI genera los pulsos de reloj y las condiciones de START y STOP, y envía y recibe bytes, pero lo hace un paso por vez: el programa escribe una orden en TWCR, el hardware la ejecuta y activa la bandera TWINT cuando terminó; el programa lee el estado en TWSR, decide el paso siguiente y vuelve a escribir. Mientras TWINT está en 1, el reloj SCL queda en bajo y el bus se detiene esperando al programa.

Registros del TWI.
RegistroContenido
TWBRDivisor de la velocidad del bit (8 bits)
TWSRBits 7:3 = código de estado; bits 1:0 = TWPS, prescaler (1, 4, 16 o 64)
TWDRByte a enviar o recibido
TWCRTWINT (bandera, se borra escribiendo 1), TWEA (enviar ACK), TWSTA (START), TWSTO (STOP), TWWC (colisión de escritura), TWEN (habilita el módulo), TWIE (interrupción)
TWAR, TWAMRDirección propia y máscara, si el microcontrolador actúa como esclavo

La frecuencia de SCL sale de:

fSCL = fCPU / (16 + 2 · TWBR · 4TWPS)

Con 16 MHz y prescaler 1, TWBR = 72 da 100 kHz y TWBR = 12 da 400 kHz. La primera herramienta del laboratorio lo calcula. En modo maestro, el datasheet recomienda TWBR ≥ 10.

Códigos de estado del maestro (TWSR & 0xF8), definidos en <util/twi.h>.
CódigoNombreSignificado
0x08TW_STARTSTART enviado
0x10TW_REP_STARTSTART repetido enviado
0x18TW_MT_SLA_ACKDirección + W enviada, el esclavo respondió ACK
0x20TW_MT_SLA_NACKDirección + W enviada, NACK: nadie contestó
0x28TW_MT_DATA_ACKDato enviado, ACK
0x30TW_MT_DATA_NACKDato enviado, NACK
0x38TW_MT_ARB_LOSTSe perdió el arbitraje
0x40TW_MR_SLA_ACKDirección + R enviada, ACK
0x48TW_MR_SLA_NACKDirección + R enviada, NACK
0x50TW_MR_DATA_ACKDato recibido, se devolvió ACK
0x58TW_MR_DATA_NACKDato recibido, se devolvió NACK

08 · Primer programa

Código de maestro

Las funciones básicas siguen los pasos del módulo: iniciar una orden, esperar TWINT con un tiempo máximo (un bus colgado no debe bloquear el programa para siempre) y comprobar el estado.

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/twi.h>               // TW_START, TW_MT_SLA_ACK, TW_STATUS, ...
#include <stdint.h>

static void i2c_init(void) {
    TWSR = 0;                          // prescaler 1
    TWBR = 72;                         // 100 kHz con 16 MHz
    TWCR = (1 << TWEN);                // habilita el módulo
}

static uint8_t i2c_esperar(void) {     // devuelve el estado, o 0xFF si el bus no responde
    uint16_t limite = 60000;
    while (!(TWCR & (1 << TWINT)))
        if (--limite == 0) return 0xFF;
    return TW_STATUS;                  // TWSR & 0xF8
}

static uint8_t i2c_start(void) {       // START o START repetido
    TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
    return i2c_esperar();
}

static uint8_t i2c_enviar(uint8_t dato, uint8_t esperado) {   // 0 = salió bien
    TWDR = dato;
    TWCR = (1 << TWINT) | (1 << TWEN);
    return i2c_esperar() == esperado ? 0 : 1;
}

static uint8_t i2c_recibir(uint8_t ack) {                     // ack = 0 para el último byte
    TWCR = (1 << TWINT) | (1 << TWEN) | (ack ? (1 << TWEA) : 0);
    i2c_esperar();
    return TWDR;
}

static void i2c_stop(void) {
    TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);      // no hay que esperar TWINT
}

Con ellas, la lectura del registro de 2 bytes de la tabla anterior son cinco líneas. Cada una devuelve un código de error distinto, para saber en qué paso se cortó la conversación.

static int8_t i2c_leer_reg16(uint8_t dir, uint8_t reg, uint16_t *valor) {
    int8_t error = 0;
    if (i2c_start() != TW_START)                                      { error = -1; goto fin; }
    if (i2c_enviar((uint8_t)(dir << 1) | TW_WRITE, TW_MT_SLA_ACK)) { error = -2; goto fin; }
    if (i2c_enviar(reg, TW_MT_DATA_ACK))                              { error = -3; goto fin; }
    if (i2c_start() != TW_REP_START)                                  { error = -4; goto fin; }
    if (i2c_enviar((uint8_t)(dir << 1) | TW_READ, TW_MR_SLA_ACK))  { error = -5; goto fin; }
    uint8_t alto = i2c_recibir(1);
    uint8_t bajo = i2c_recibir(0);
    *valor = ((uint16_t)alto << 8) | bajo;
fin:
    i2c_stop();
    return error;
}

// Termómetro de 12 bits (por ejemplo TMP102, dirección 0x48): centésimas de grado
static int32_t temperatura_centesimas(uint16_t crudo) {
    int16_t t = (int16_t)(crudo >> 4);          // 12 bits alineados a la izquierda
    if (t & 0x800) t -= 4096;                   // extensión de signo
    return (int32_t)t * 625 / 100;              // 0,0625 °C por cuenta
}

El goto fin es una de las pocas situaciones donde el estilo de C lo acepta: garantiza que siempre se envíe el STOP, aunque un paso falle, y no se deje el bus a medias. Si el esclavo queda con la línea SDA retenida, ningún otro dispositivo podrá usar el bus.

Los registros de los dispositivos reales tienen cada uno su convención: algunos entregan el byte alto primero, otros el bajo; algunos tienen el dato justificado a la izquierda, algunos usan complemento a dos y otros BCD (como los relojes DS1307 y DS3231). La hoja de datos manda.

09 · Diagnóstico

Escáner y diagnóstico

La herramienta de diagnóstico por excelencia es el escáner de bus: probar todas las direcciones y anotar cuáles responden con ACK.

static void i2c_escanear(void) {
    for (uint8_t dir = 0x08; dir < 0x78; dir++) {
        uint8_t presente = 0;
        if (i2c_start() == TW_START)
            presente = (i2c_enviar((uint8_t)(dir << 1) | TW_WRITE, TW_MT_SLA_ACK) == 0);
        i2c_stop();
        if (presente) {
            /* imprimir la dirección por la UART (tema 32) */
        }
    }
}
Síntomas más comunes.
SíntomaCausa probable
El escáner no encuentra nadaSDA y SCL cruzados, sin masa común, sin pull-ups, alimentación mal conectada o dispositivo de 3,3 V alimentado con 5 V
Estado 0x20 (NACK en la dirección)Dirección equivocada (8 bits contra 7 bits), el dispositivo no está alimentado o está ocupado
Estado 0x30 (NACK en un dato)Registro inexistente o dato rechazado
Aparece un dispositivo solo a vecesPull-ups débiles o cables largos (flancos lentos), falsos contactos de la protoboard
Dos dispositivos con la misma direcciónCambiar la dirección con los pines de configuración (A0, A1…) del chip o usar un multiplexor de I2C
El bus queda trabado con SDA en bajoEl maestro se reinició en medio de un byte y el esclavo espera más pulsos. Solución: generar hasta 9 pulsos de SCL a mano y un STOP
Lecturas corruptas con un sensor lentoEl maestro no respeta el estiramiento del reloj
El monitor serie muestra bien pero el bus fallaPull-ups paralelos de varios módulos que bajan de Rmin

Un osciloscopio o un analizador lógico (el tema 35 lo usa) permiten ver START, direcciones, ACK y NACK. Los analizadores decodifican I2C automáticamente y muestran la secuencia como texto.

10 · Analogía con programación

Codificar y decodificar un bus I2C

Este programa calcula TWBR y el rango de los pull-ups, y verifica la constante 0,8473 del tiempo de subida. Después genera las muestras de SCL y SDA de una lectura de registro, las decodifica como lo haría un analizador lógico, convierte los bytes de un termómetro de 12 bits en grados y simula un escáner de direcciones.

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

import math

# 1) frecuencia de SCL del ATmega328P: f = fcpu / (16 + 2 * TWBR * 4^TWPS)
def twbr_para(fcpu, objetivo, prescaler=1):
    return round((fcpu / objetivo - 16) / (2 * prescaler))

print("SCL pedido   TWBR   SCL real")
for objetivo in (50e3, 100e3, 400e3):
    twbr = twbr_para(16e6, objetivo)
    real = 16e6 / (16 + 2 * twbr)
    print(f"{objetivo / 1e3:7.0f} kHz  {twbr:5d}   {real / 1e3:7.2f} kHz")

# 2) resistencias de pull-up: Rmin por la corriente de 3 mA, Rmax por el tiempo de subida
print()
print("Vcc   modo      Cb       Rmin     Rmax")
for vcc, modo, tr, cb in ((5.0, "100 kHz", 1000e-9, 200e-12), (5.0, "400 kHz", 300e-9, 100e-12),
                          (5.0, "400 kHz", 300e-9, 300e-12), (3.3, "400 kHz", 300e-9, 100e-12)):
    rmin = (vcc - 0.4) / 0.003
    rmax = tr / (0.8473 * cb)
    estado = "" if rmin <= rmax else "  (no hay valor posible)"
    print(f"{vcc:3.1f}   {modo}  {cb * 1e12:4.0f} pF  {rmin:6.0f}  {rmax:7.0f}{estado}")

# el factor 0,8473 es el tiempo entre el 30 % y el 70 % de Vcc en un circuito RC
print("t(30%->70%) / RC =", round(math.log(0.7 / 0.3), 4))

# 3) codificar una transaccion en muestras (SCL, SDA) y decodificarla como un analizador logico
def codificar(eventos):
    m = [(1, 1)]
    def paso(scl, sda):
        m.append((scl, sda))
    for ev in eventos:
        if ev[0] == "S":
            paso(1, 0); paso(0, 0)
        elif ev[0] == "Sr":
            paso(0, 1); paso(1, 1); paso(1, 0); paso(0, 0)
        elif ev[0] == "P":
            paso(0, 0); paso(1, 0); paso(1, 1)
        else:                                   # ("B", valor, ack)
            valor, ack = ev[1], ev[2]
            for i in range(7, -1, -1):
                bit = (valor >> i) & 1
                paso(0, bit); paso(1, bit); paso(0, bit)
            paso(0, 0 if ack else 1); paso(1, 0 if ack else 1); paso(0, 0 if ack else 1)
    return m

def decodificar(muestras):
    salida, bits, previo = [], [], muestras[0]
    for scl, sda in muestras[1:]:
        pscl, psda = previo
        if scl == 1 and pscl == 1 and psda == 1 and sda == 0:
            salida.append("S" if not salida or salida[-1] == "P" else "Sr")
            bits = []
        elif scl == 1 and pscl == 1 and psda == 0 and sda == 1:
            salida.append("P")
            bits = []
        elif scl == 1 and pscl == 0:             # flanco de subida: se muestrea SDA
            bits.append(sda)
            if len(bits) == 9:
                valor = int("".join(map(str, bits[:8])), 2)
                salida.append(f"0x{valor:02X} {'ACK' if bits[8] == 0 else 'NACK'}")
                bits = []
        previo = (scl, sda)
    return salida

eventos = [("S",), ("B", 0x90, True), ("B", 0x00, True), ("Sr",), ("B", 0x91, True),
           ("B", 0x19, True), ("B", 0x80, False), ("P",)]
muestras = codificar(eventos)
print()
print("transaccion decodificada:", " ".join(decodificar(muestras)))
bytes_en_bus = 5
print(f"bits de reloj: {bytes_en_bus * 9 + 3}  ->  {(bytes_en_bus * 9 + 3) / 100e3 * 1e6:.0f} us a 100 kHz, {(bytes_en_bus * 9 + 3) / 400e3 * 1e6:.0f} us a 400 kHz")

# 4) un termometro de 12 bits (como el TMP102): dos bytes -> temperatura
def temperatura_centesimas(msb, lsb):
    crudo = (msb << 4) | (lsb >> 4)
    if crudo & 0x800:
        crudo -= 4096                           # extension de signo de 12 bits
    return crudo * 625 // 100                   # 0,0625 C por cuenta

print()
for msb, lsb in ((0x19, 0x00), (0x1A, 0x80), (0xE7, 0x00)):
    c = temperatura_centesimas(msb, lsb)
    print(f"bytes 0x{msb:02X} 0x{lsb:02X} -> {c / 100:.2f} C")

# 5) escaner de direcciones: quien responde con ACK
presentes = {0x3C: "pantalla OLED", 0x48: "sensor de temperatura", 0x68: "reloj de tiempo real"}
print()
print("escaner del bus (direcciones 0x08 a 0x77):")
for direccion in range(0x08, 0x78):
    if direccion in presentes:
        print(f"  0x{direccion:02X} responde: {presentes[direccion]}")

Resultado: con 16 MHz, TWBR vale 72 para 100 kHz, 12 para 400 kHz y 152 para 50 kHz, y las tres frecuencias salen exactas. Con 5 V y 200 pF a 100 kHz, la resistencia puede ir de 1533 Ω a 5901 Ω; con 300 pF a 400 kHz el rango desaparece (1533 Ω > 1180 Ω). El decodificador reconstruye S 0x90 ACK 0x00 ACK Sr 0x91 ACK 0x19 ACK 0x80 NACK P, 48 pulsos de reloj. Los bytes 0x19 0x00 equivalen a 25,00 °C, 0x1A 0x80 a 26,50 °C y 0xE7 0x00 a −25,00 °C.

La codificación usa un modelo ideal, sin flancos lentos ni estiramiento del reloj; el decodificador simplifica las condiciones de START y STOP, pero sigue el mismo principio que un analizador real.

11 · Exploración interactiva

TWBR, pull-ups y transacciones

La primera herramienta calcula el divisor del reloj. La segunda halla el rango de los pull-ups para tu bus. La tercera arma la secuencia de bytes de una escritura o lectura y su duración.

Banco del bus I2C

1. Velocidad de SCL

Divisor—
Frecuencia real—
Registros—

2. Resistencias de pull-up

Rango permitido—
Tiempo de subida—
Corriente y potencia—

3. Una transacción paso a paso

PasoQuiénQuéRespuesta
Total—
Dirección en el bus—

Recorrido guiado

  1. Con 16 MHz y 100 kHz: TWBR = 72 exacto. Cambiá a 400 kHz: 12. Con 16 MHz y 10 kHz el prescaler 1 no alcanza (TWBR = 792, más de 255); subí el prescaler a 4 o 16.
  2. Con 16 MHz y 1 MHz de SCL sale TWBR = 0, fuera de la recomendación y de la especificación del chip.
  3. En los pull-ups, 5 V, 100 kHz y 200 pF dan el rango 1533 Ω a 5901 Ω; 4,7 kΩ da 796 ns de subida, dentro del máximo. Cambiá a 400 kHz con 300 pF: aparece «no existe un valor».
  4. Con 3,3 V el límite inferior baja a 967 Ω. Elegí 500 Ω: la nota avisa que es demasiado baja.
  5. La lectura de dos bytes del registro 0x00 del dispositivo 0x48 son 5 bytes y 48 pulsos, 480 µs a 100 kHz. Pasá a 400 kHz: 120 µs.
  6. Probá la dirección 0x7F: la nota avisa que está reservada. Cambiá a «Escribir»: desaparece el START repetido.
Desafío: leer un acelerómetro

Un acelerómetro en la dirección 0x68 entrega 6 bytes (X, Y y Z de 16 bits) a partir del registro 0x3B. ¿Cuánto tarda leerlos a 400 kHz y cuántas veces por segundo se puede hacer? Una lectura de registro de 6 bytes usa 3 + 6 = 9 bytes en el bus: 9 × 9 + 3 = 84 pulsos, 210 µs a 400 kHz. El techo teórico es 4760 lecturas por segundo, sin contar el tiempo de la CPU entre una y otra. A 100 kHz serían 840 µs: 1190 lecturas por segundo. Para muestrear una vibración de 1 kHz (tema 27) harían falta al menos 2000 por segundo, que exige los 400 kHz.

12 · Comprensión

Confusiones frecuentes

«I2C no necesita resistencias, el microcontrolador ya las tiene»

Las resistencias internas de unos 20–50 kΩ son demasiado débiles: el flanco de subida sería lento y el bus fallaría salvo a velocidades muy bajas y con cables cortos. Hacen falta pull-ups externos de 2,2 a 10 kΩ.

«La dirección de mi sensor es 0xD0, así que uso 0xD0»

Si el datasheet da el byte de 8 bits (0xD0 para escribir, 0xD1 para leer), la dirección de 7 bits es 0x68. Las bibliotecas y el código de este tema esperan la dirección de 7 bits y la desplazan solos.

«Un ACK significa que el dato es correcto»

Significa que el receptor lo recibió. No verifica el contenido ni la coherencia: para eso hay sumas de verificación en el protocolo del dispositivo (algunos sensores devuelven un CRC).

«Más pull-ups de menor resistencia son siempre mejores»

Mejoran el flanco pero aumentan la corriente que los dispositivos deben absorber. Por debajo de Rmin el nivel bajo deja de ser válido; es lo que ocurre al conectar muchos módulos con sus propios pull-ups.

«El maestro puede olvidar el STOP»

Sin STOP el bus queda ocupado: los otros maestros esperan y algunos esclavos mantienen su estado interno. Siempre debe cerrarse la transacción, incluso si hubo un error.

13 · Práctica guiada

Predecí antes de comprobar

1. El divisor

Con 16 MHz y prescaler 1, ¿qué TWBR da 400 kHz?

Ver solución

(16 000 000 / 400 000 − 16) / 2 = (40 − 16) / 2 = 12.

2. Pull-ups a 3,3 V

Un bus de 3,3 V con 200 pF a 100 kHz: ¿qué rango de resistencias es válido y entra una de 4,7 kΩ?

Ver solución

Rmin = (3,3 − 0,4) / 3 mA = 967 Ω. Rmax = 1000 ns / (0,8473 × 200 pF) = 5901 Ω. Sí, 4,7 kΩ está en el rango.

3. Escribir un registro

Un reloj en la dirección 0x68 recibe el valor 0x80 en el registro 0x0F. ¿Qué bytes se envían y cuánto dura a 400 kHz?

Ver solución

START, 0xD0 (0x68 << 1), 0x0F, 0x80, STOP: son 3 bytes (dirección, registro y dato) = 27 pulsos más START y STOP = 29 pulsos, 72,5 µs a 400 kHz.

4. Direcciones de 8 bits

Un datasheet indica «dirección de escritura 0xD0, de lectura 0xD1». ¿Cuál es la dirección de 7 bits?

Ver solución

0xD0 >> 1 = 0x68. Es el desplazamiento del bit R/W.

5. Bus trabado

Se reinicia el microcontrolador en medio de una lectura y SDA queda en bajo para siempre. ¿Por qué ocurre y cómo se libera?

Ver solución

El esclavo estaba enviando un bit 0 y espera el siguiente pulso de reloj para continuar; como el maestro se reinició, nadie se lo da. Se libera generando hasta 9 pulsos de SCL a mano (con los pines como salidas normales) hasta que el esclavo suelte SDA, y después un STOP.

14 · Síntesis

Ideas para recordar

  • I2C usa dos líneas compartidas, SDA y SCL, con salidas de colector abierto y resistencias de pull-up: es un AND por cable.
  • Pull-up: Rmin = (Vcc − 0,4 V) / 3 mA y Rmax = tr / (0,8473 · Cb). Valores típicos: 4,7 kΩ a 100 kHz y 2,2 kΩ a 400 kHz.
  • SDA cambia solo con SCL en bajo; START y STOP son las únicas excepciones. Cada byte lleva 9 pulsos: 8 bits y un ACK.
  • La dirección de 7 bits se envía con R/W en el bit 0. Leer un registro es escribir su número, hacer un START repetido y leer, con NACK en el último byte.
  • fSCL = fCPU / (16 + 2 · TWBR · 4TWPS); en el ATmega328P, TWBR = 72 da 100 kHz y 12 da 400 kHz.
  • El TWI avanza un paso por vez: se escribe TWCR, se espera TWINT, se verifica el estado y se sigue; con un tiempo máximo para no colgarse.
  • Un escáner de direcciones, un analizador lógico y una cuenta de pull-ups resuelven la mayoría de los problemas de bus.

¿Listo para el tema 34?

Antes de avanzar, explicá por qué I2C necesita pull-ups, dibujá la secuencia de lectura de un registro y calculá TWBR para una velocidad dada. Si podés justificar las tres respuestas, entendés el bus.

En el próximo tema vemos el bus SPI: maestro y esclavo, modos de reloj, selección de chip y una velocidad mucho mayor, a cambio de más cables.