Codificação compatível com Arduino 18: Comunicação serial síncrona usando o barramento I2C

Codificación compatible con Arduino 18: comunicación serie síncrona mediante el bus I2C

En tutoriales anteriores, cubrimos la comunicación en serie utilizando UART y el software en serie en Arduino. El receptor/transmisor asíncrono universal (UART), I2C y SPI son las interfaces serie más utilizadas en sistemas integrados.

UART es útil para la comunicación serie full-duplex con un solo dispositivo a través de dos cables. La interfaz I2C o interfaz de dos cables (TWI) se utiliza para la comunicación serie síncrona semidúplex con múltiples dispositivos en modo maestro-esclavo. El bus SPI se utiliza para comunicación serie síncrona full-duplex con múltiples dispositivos.

Ahora, en este tutorial, aprenderemos sobre la comunicación serie síncrona en Arduino utilizando el bus de circuito integrado (I2C).

El autobús I2C
I2C, o TWI, es un protocolo de comunicación serie síncrono maestro-esclavo desarrollado originalmente por Philips Semiconductors (que ahora es NXP). El bus I2C tiene sólo dos cables: uno es una línea de datos (SDA) y el otro es una línea de reloj (SCL).

En un bus de dos cables, cientos de dispositivos maestros y esclavos pueden comunicar datos en serie mediante el protocolo I2C.

I2C es un bus de tipo maestro-esclavo y debe haber al menos un dispositivo maestro para controlar el bus de dos cables.

El dispositivo maestro es responsable de sincronizar las transferencias de datos:

  • Generando la señal del reloj
  • Seleccionar un dispositivo esclavo para la comunicación
  • Controlar las operaciones de lectura/escritura en el bus

Dado que sólo hay una línea de datos, sólo es posible la comunicación semidúplex con un único dispositivo esclavo a la vez. Esto significa que se puede conectar cualquier cantidad de dispositivos maestros al bus I2C, pero solo un maestro puede controlar el bus al mismo tiempo.

Los cables se colocan en ALTO de forma predeterminada utilizando las resistencias pull-up y los controladores I2C son de drenaje abierto (es decir, solo pueden colocar la línea en BAJO). Esto evita con éxito cualquier contención del autobús.

Cada esclavo I2C conectado a un bus debe tener una dirección única. El dispositivo maestro utiliza direccionamiento dentro de banda para acceder a la comunicación con los dispositivos esclavos. NXP decide las direcciones I2C de los distintos dispositivos esclavos.

Muchos dispositivos esclavos tienen una dirección I2C configurable. El direccionamiento en banda puede ser de 7 o 10 bits. En el direccionamiento de 7 bits se pueden conectar al bus 112 dispositivos esclavos. En el direccionamiento de 10 bits se pueden conectar 1008 dispositivos esclavos al bus. Además, el maestro I2C puede utilizar direcciones de 7 y 10 bits en el mismo bus.

Además, existen algunas placas de conexión que permiten la comunicación con múltiples dispositivos esclavos utilizando una dirección común. En estas placas, los dispositivos esclavos se multiplexan a través de un controlador integrado.

La implementación del protocolo I2C simplemente requiere dos canales de drenaje abiertos en un dispositivo. En la mayoría de los controladores/computadoras, existe hardware dedicado para administrar el protocolo I2C.

La velocidad de transferencia de datos en I2C depende de la frecuencia de reloj generada por el maestro I2C.

Existen velocidades de reloj I2C estándar, que incluyen:

  • 100 a 400 kHz (estándar I2C)
  • 1 MHz (modo rápido I2C)
  • 3,4 MHz (I2C de alta velocidad)
  • 5 MHz (modo ultrarrápido I2C).

Normalmente, el bus I2C utiliza niveles lógicos TTL de 5V o 3V3. Se recomienda conectar dispositivos compatibles con voltaje a través del bus I2C; de lo contrario, el dispositivo de bajo voltaje corre el riesgo de dañar sus canales I2C al recibir datos. Si dos dispositivos tienen diferentes niveles de tensión TTL, se debe utilizar un variador de tensión adecuado entre los dispositivos y conectarlo a través del bus de dos hilos.

El protocolo I2C
La comunicación de datos siempre la inicia un dispositivo maestro en el bus TWI. Un dispositivo maestro genera una condición inicial para acceder al bus. Al generar la condición de inicio se decide qué maestro accederá al bus si dos o más intentan hacerlo al mismo tiempo.

Después de hacer esto con éxito, el maestro transmite una dirección dentro de banda en forma de una trama de dirección para seleccionar un dispositivo esclavo para la comunicación. El maestro debe leer o escribir datos en el dispositivo esclavo seleccionado, que se indica en el cuadro de dirección.

Después de seleccionar un dispositivo esclavo, el maestro puede leer o escribir datos en forma de paquetes de datos de 8 bits. Después de intercambiar cada paquete de datos, el dispositivo receptor envía un bit de confirmación al remitente para indicar que el byte se comunicó exitosamente.

Después de obtener acceso al bus I2C, un maestro puede generar múltiples condiciones de arranque para hablar con un dispositivo esclavo varias veces, o para hablar con múltiples dispositivos esclavos uno tras otro.

Sin embargo, para liberar el bus a otros maestros, el maestro necesita generar una condición de parada. Los dispositivos esclavos nunca pueden iniciar la comunicación por sí solos ni controlar el bus, pero pueden mantener temporalmente el pulso del reloj (después de una condición de parada) para hacer que los maestros esperen para acceder al bus. Esto se llama alargamiento del reloj. (Obtenga más información sobre el protocolo I2C aquí ).

Aplicaciones del bus I2C
Dado que varios dispositivos pueden comunicar datos a través de solo dos cables utilizando el protocolo I2C, la interfaz I2C/TWI es ampliamente utilizada por sensores y módulos integrados. Algunos ejemplos de sensores que utilizan el bus I2C para la comunicación de datos son el acelerómetro ADXL345, el giroscopio L3G4200D, el magnetómetro MC5883L, el sensor de presión BMP180, el RTC DS1307 y otros.

Usando I2C en placas Arduino
La mayoría de las placas Arduino tienen al menos un módulo I2C. Se puede acceder al módulo I2C a través de uno o más puertos de la placa.

Los pines I2C no están internamente elevados, por lo que es posible que deba colocarlos en ALTO usando resistencias externas, dependiendo del dispositivo I2C al que estén conectados.

Los pines I2C de un Arduino UNO se muestran aquí:

Esta tabla resume la ubicación de los pines I2C en varias placas Arduino...

la biblioteca de alambre
Es más fácil hablar con dispositivos I2C/TWI usando Arduino, en parte porque esta plataforma proporciona una biblioteca: Un cable para administrar la comunicación de las placas Arduino en un bus I2C.

Las placas Arduino se pueden configurar como maestra I2C y esclava I2C. La biblioteca de cables utiliza un búfer de 32 bytes, por lo que cualquier transferencia de datos I2C debe estar dentro de este límite. Si se comunican más bytes en una transmisión, los bytes sobrantes se omiten.

La biblioteca de cables se puede importar a un boceto de Arduino siguiendo estas instrucciones:

#incluir

La biblioteca de cables tiene estos métodos:

fio.begin : se utiliza para unirse al bus I2C como maestro o esclavo. Esto tiene esta sintaxis:

Cable.comenzar
o
Cable.comienzo (dirección)

Si el Arduino se une al bus I2C como maestro, el método debe llamarse sin argumentos. Si Arduino se une al bus I2C como esclavo, se debe pasar una dirección arbitraria de 7 bits como argumento. El sa esclavo puede tener una dirección entre 8 y 127. Sin embargo, las direcciones 0 a 7 están reservadas y no son utilizadas por Arduino.

A continuación se muestran ejemplos válidos de este método:

Wire.begin //Arduino como maestro I2C
Wire.begin(8) // Arduino como esclavo I2C

Wire.setClock : utilizado por Arduino y configurado como maestro I2C. Este método se utiliza para cambiar la frecuencia de reloj del bus I2C. Los esclavos I2C no tienen una frecuencia mínima, aunque 100 kHz es la base. Este método tiene esta sintaxis:

Wire.setClock (frecuencia del reloj)

Toma como argumento la frecuencia del reloj en Hercios. Aquí hay un ejemplo válido:

Cable.setClock(3200)

Wire.beginTransmission (dirección) : utilizado por Arduino y configurado como maestro I2C. Este método se utiliza para iniciar la transmisión a un esclavo I2C. La dirección del esclavo I2C seleccionado se pasa como argumento a la función. Tiene esta sintaxis:

Wire.beginTransmission(dirección)

Y aquí hay un ejemplo válido:

Cable.beginTransmission(8)

Wire.write : se utiliza para escribir datos en el bus I2C. Arduino puede utilizarlo como maestro I2C y esclavo I2C. Como maestro, este método debe usarse entre llamadas a los métodos startTransmission y endTransmission.

Como esclavo, este método se puede utilizar en respuesta a una solicitud de un dispositivo maestro. Se puede utilizar para transmitir un valor, una cadena o una matriz de bytes. Tiene esta sintaxis:

Cable.escritura(valor)
o
Cable.escribir (cadena)
o
Wire.write(datos, longitud)

Aquí hay ejemplos válidos:

Cable.escritura(7)
Cable.write(“Hola”)
Wire.write(arraybytes, 5) //arraybytes es una matriz de valores de 5 bytes
matriz de valores de 5 bytes

Wire.onReceive(controlador) utilizado por Arduino y configurado como esclavo. Asigna una función de controlador que se llamará en respuesta cuando se reciban datos del maestro I2C. La función de controlador definida por el usuario debe tomar el número de bytes leídos del maestro como argumento si es necesario. La función también debe ser de tipo void y no devolver nada. Tiene esta sintaxis:

Wire.onReceive(controlador)

Aquí hay un ejemplo válido:

Wire.onReceive(receiveEvent);
anular recibir evento
{
Serial.print(“datos recibidos del maestro I2C);
}

Solicitud de cable desde utilizado por Arduino y configurado como maestro I2C. Este método se utiliza para solicitar datos del esclavo I2C. Luego, el maestro Arduino recupera los datos solicitados utilizando los métodos Wire.available y Wire.read. Tiene esta sintaxis:

Wire.requestFrom(dirección, cantidad)
Wire.requestFrom(dirección, cantidad, parada)

El método toma dos argumentos: la dirección I2C del dispositivo esclavo y la cantidad de bytes solicitados. Tiene un argumento booleano opcional – stop que puede ser 'Verdadero' o 'Falso'.

Detener es Verdadero por defecto. Cuando es Verdadero, se genera una condición de parada después de la solicitud, liberando el bus. Cuando es False, se genera una condición de reinicio después de la solicitud, lo que permite que el maestro Arduino continúe usando el bus. El método devuelve la cantidad de bytes recibidos del dispositivo esclavo. Aquí hay un ejemplo válido:

Wire.requestFrom(8, 6, verdadero)

Wire.onRequest(handler) : utilizado por Arduino configurado como esclavo. Asigna una función de controlador que se llamará en respuesta cuando el maestro I2C solicite datos de este esclavo. La función de controlador definida por el usuario no toma argumentos y no devuelve nada. Este método tiene esta sintaxis:

Wire.onRequest(controlador)

Y aquí hay un ejemplo válido:

Wire.onRequest(requestEvent);
solicitud anuladaEvento
{
Wire.write(“Maestro, obtenga estos datos”);
}

Hilo.disponible utilizado ya que Arduino está configurado como maestro o esclavo. Devuelve el número de bytes disponibles para recuperación del bus I2C. Debe ser llamado por el Arduino maestro después de una llamada a requestFrom y por el Arduino esclavo dentro del controlador onReceive. Tiene esta sintaxis:

Hilo.disponible

El método no acepta argumentos. Este es un ejemplo válido:

mientras (Cable.disponible)
{
char c = Cable.leer;
}

Wire.read: lee un byte transmitido desde un dispositivo esclavo a un maestro después de una llamada a requestFrom o si se transmite de un maestro a un esclavo. Tiene esta sintaxis:

Fio.ler

El método no acepta argumentos. Este es un ejemplo válido:

Cable.requestFrom(2, 6);
mientras (Cable.disponible)
{
char c = Cable.leer;
}

Transmisión del extremo del cable utilizado por un Arduino y configurado como maestro I2C. Este método se utiliza para finalizar la transmisión al esclavo I2C y transmitir bytes en cola utilizando el método de escritura. Por lo tanto, se debe invocar después de una llamada al método de escritura. Tiene esta sintaxis:

Transmisión del extremo del cable
Wire.endTransmission(detener)

El método toma un argumento opcional: detenerse. Es un valor booleano que, si se establece en True, genera una condición de parada y libera el autobús. Si se establece en False, genera una condición de reinicio, lo que permite que el Arduino maestro continúe accediendo al bus.

Este método devuelve un byte de estado, que puede ser 0, 1, 2, 3 o 4.

  • Si el byte de estado es 0, la transmisión finalizó exitosamente.
  • Si es 1, los datos eran demasiado largos para caber en el búfer de 32 bytes.
  • Si es 2, se recibió NACK en la dirección de transmisión
  • Si es 3, se recibió NACK en la transmisión de datos.
  • Si es 4, ocurrió un error.

A continuación se muestra un ejemplo válido de este método:

Wire.beginTransmission(8);
Wire.write(“Hola, soy I2C Master”);
Wire.endTransmission;

Arduino como maestro I2C
El Arduino se puede configurar como maestro I2C llamando a Wire.begin sin ningún argumento. El maestro Arduino puede configurar la frecuencia del reloj I2C utilizando el método Wire.setClock si es necesario modificar la velocidad del reloj.

Puede transmitir datos a un esclavo llamando a los métodos Wire.beginTransmission, Wire.write y Wire.endTransmission. También puede solicitar datos de un esclavo utilizando el método requestFrom y recuperar los datos solicitados utilizando los métodos Wire.available y Wire.read.

Arduino como esclavo I2C
El Arduino puede unirse al bus I2C como esclavo llamando al método Wire.begin con su dirección pasada como argumento. Puede ejecutar un bloque de código en respuesta a los datos recibidos del maestro utilizando el método Wire.onReceive(handler).

En la función del controlador, los bytes recibidos se pueden leer utilizando los métodos Wire.available y Wire.read. También puede ejecutar un bloque de código en respuesta a una solicitud del maestro I2C utilizando el método Wire.onRequest(handler).

En la función del controlador, los datos solicitados se pueden enviar utilizando el método Wire.write.

En el próximo tutorial, cubriremos cómo conectar un sensor acelerómetro ADXL345 con Arduino usando la interfaz I2C.

(tagsToTranslate)Arduino

Regresar al blog

Deja un comentario

Ten en cuenta que los comentarios deben aprobarse antes de que se publiquen.