viernes, 2 de junio de 2017

El bus I2C

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