El bus I2C
El estándar I2C
(Inter-Integrated Circuit) fue desarrollado por Philips en 1982 para la
comunicación interna de dispositivos electrónicos en sus artículos.
Posteriormente fue adoptado progresivamente por otros fabricantes hasta
convertirse en un estándar del mercado.
También es denominado
TWI (Two Wired Interface) únicamente por motivos de licencia, aunque
actualmente la patente ha caducado y no existe restricción sobre el término
I2C.
El bus I2C requiere
únicamente dos cables para su
funcionamiento, uno para la señal de reloj (CLK) y otro para el envío de datos
(SDA), lo cual es una ventaja frente al bus SPI. Por contra, su funcionamiento
es un poco más complejo, así como la electrónica necesaria para implementarlo.
En el bus cada dispositivo dispone de una dirección.
Esta dirección puede ser fijada por hardware (frecuentemente se pueden
modificar los últimos 3 bits mediante jumpers o interruptores) o totalmente por
software.
En general, cada dispositivo conectado al bus debe tener
una dirección única. Si tenemos varios dispositivos similares tendremos que
cambiar la dirección o, en caso de no ser posible, implementar un bus
secundario.
El bus I2C tiene una arquitectura de tipo maestro-esclavo. El
dispositivo maestro inicia la comunicación con los esclavos, y puede mandar o
recibir datos de los esclavos. Los esclavos no pueden iniciar la comunicación
(el maestro tiene que preguntarles), ni hablar entre si directamente. Es
posible disponer de más de un maestro, pero solo uno puede ser el maestro cada vez. El
cambio de maestro supone una alta complejidad, por lo que no es algo frecuente.
El bus I2C es síncrono, el maestro proporciona una señal de
reloj que mantiene sincronizados a todos los dispositivos del bus. De esta
forma, se elimina la necesidad de que cada dispositivo tenga su propio reloj,
de tener que acordar una velocidad de transmisión y mecanismos para mantener la
transmisión sincronizada (como en UART).
El protocolo I2C prevé resistencias de Pull-UP de las líneas a Vcc.
En Arduino frecuentemente no se instalan estas resistencias, ya que la librería
Wire activa las resistencias internas de Pull-UP. Sin embargo las resistencias
internas tienen un valor de entre 20-30kOhmnios, por lo que son unas
resistencias de Pull-UP muy blandas.
Usar unas resistencias blandas implica que los flancos de
subida de la señal serán menos rápidas, lo que implica que podremos usar
velocidades menores y distancias de comunicación inferiores. Si queremos
emplear velocidades o distancias de transmisión superiores, deberemos
poner físicamente resistencias de Pull-UP de entre 1k a 4K7.
En arduino, las tramas constan de los siguientes elementos:
- 7 bits a la dirección del dispositivo esclavo con el que queremos comunicar.
- Un bit restante indica si queremos enviar o recibir información.
- Un bit de validación
- Uno o más bytes son los datos enviados o recibidos del esclavo.
- Un bit de validación
Las transmisiones son de 9 bits, tanto de sincronización
como de datos, sin tener en cuenta lo bits de start y stop.
Con estos 7 bits de dirección es posible
acceder a 112 dispositivos en un mismo bus (16 de las 128 direcciones
posibles se reservan para usos especiales). Sin embargo, la cantidad de
dispositivos que se pueden conectar también está limitada por la capacidad
máxima permitida, que es de 400pF.
Este encapsulado en la trama, de 10bits por cada 8 o 16bits
de datos, supone que en general la velocidad del bus I2C sea reducida. La
velocidad estándar de transmisión es de 100MHz, aunque existe un modo de alta
velocidad de 400MHz.
Funcionamiento del bus
Los bits de datos se transmiten por la línea SDA. Por cada
bit de información se necesita un pulso del reloj en la línea SCL. El dato
transmitido por la línea SDA sólo pueden cambiar cuando la línea SCL está a
nivel bajo. Están prohibidas las transiciones de la línea SDA mientras la línea
SCL esté en nivel alto. La única excepción a esta regla son las señales de
arranque (start) y parada (stop).
Un
ejemplo de transmisión completa podría ser el siguiente:
Donde podemos ver que el bit de lectura/escritura está
puesto a nivel alto (modo lectura), momento en el cual el maestro genera pulsos
para que el dispositivo esclavo pueda enviar los datos. Tras cada byte recibido
por el maestro, este genera un pulso de reconocimiento (ACK).
Para poder utilizar la comunicación I2C en arduino
necesitamos importar la librería “wire.h”.
Las librerías son colecciones que facilitan la interconexión
de sensores, pantallas, módulos electrónicos, etc. Podríamos decir que son
trozos de códigos hechos por terceros, que usamos para simplificar nuestros
programas, ya que nos ahorran estudiar los componentes en profundidad.
En este caso, la librería wire.h viene por defecto instalada
en el IDE de arduino y solo tenemos que incluirla en nuestro programa. Existen
dos formas de incluir una librería:
·
#include <wire.h> busca la librería en la carpeta por defecto
·
#include “wire.h” tenemos que especificar la ruta de la librería
Para poner en práctica estos conocimientos sobre el bus I2C,
realizaremos una simulación en proteus con el DS1621, un termómetro digital y
termostato. Tiene un rango desde -55 ⁰C hasta los 125 ⁰C,
con un incremento de 0.5 ⁰C.
Podemos configurar hasta 8 dispositivos, mediante el uso de los pines
A2, A1, A0 de la dirección, los primero 4 dígitos son fijos y depende del
DS1621. La dirección por defecto es
0x48.
Aquí tenemos
una muestra de lo enviado por el puerto serial.
En esta
imagen podemos ver una muestra del sniffer del bus I2C, con una serie de
transmisiones. Explicaremos algunos elementos de esta captura:
- · 65.541ms: este primer número hace referencia el tiempo que ha tardado en arrancar el sistema, ver que nadie trata de comunicarse con él, cargar la primera instrucción y ejecutarla.
- · La diferencia entre el primer y el segundo tiempo, se corresponde con el tiempo que ha tardado en ejecutar las instrucciones que siguen (se ven abriendo el desplegable).
- · S: start
- · 90: dirección + bit W/R
- · A: acknowlegement (ACK) o acuse de recibo, para confirmar la recepción
- · N: NACK mensaje no recibido o con errores
- · P: stop
- · Sr: condición de inicio repetida
- · EE: datos maestro a esclavo
Es posible
profundizar aún más en la trasmisión abriendo los despegables y accediendo al
envío de cada byte de información, como se puede ver en la siguiente captura:
Un motivo
importante para utilizar proteus es que además de simular, nos permite depurar.
Si iniciamos la simulación del programa y abrimos la pestaña “Source Code” en
la parte inferior encontramos las posibles visualizaciones del debugger.
En el caso de
la simulación actual, podemos ver por ejemplo, los registros del ds1621:
Debemos tener
cuidado con la extensión en la que guardamos los archivos, pues la extensión
.elf permite simulación y depuración, mientras que la .hex solo permite
simulación.











No hay comentarios:
Publicar un comentario