
Es muy habitual el uso de dispositivos I2C externos tales como las memorias EEPROM. Sin embargo, la mayoría de las rutinas I2C son secuenciales, y mantienen al micro a la espera de finalizar la comunicación sin hacer otra cosa.
Con esta rutina el tratamiento se realiza por interrupción, con lo que nuestro micro podrá estar atendiendo otras tareas y sólo saltar a la interrupción cuando «toque».
La comunicación I2C permite gestionar muchos dispositivos en el mismo bus, a vecocidades que alcanzan 400kbps, lo cual es muy versátil en nuestros diseños.
La mayoría de los compiladores tienen instrucciones que facilitan la escritura y lectura en el bus I2C, aunque la gestión de la respuesta del periférico suele hacerse por esperas hasta que determinado flag cambia de sentido.
El planteamiento que hago a continuación gestiona dicha comunicación tanto en lectura como en escritura mediante una interrupción y una máquina de estados.
En el ejemplo utilizamos una memoria EEPROM 24LC256 y un dsPIC30F6014, aunque es fácilmente extrapolable a otros sistemas.
Este es el datagrama de un ciclo de escritura en la EEPROM:

Podemos observar que hay que:
- enviar el byte de control y esperar un ACK
- la parte alta de la dirección y esperar otro ACK
- la parte baja de la dirección y esperar otro ACK
- el byte a escribir y esperar otro ACK
- vuelta al paso anterior por cada byte a escribir
- bit de STOP al final

En este caso hay que:
- enviar el byte de control y esperar un ACK
- la parte alta de la dirección y esperar otro ACK
- la parte baja de la dirección y esperar otro ACK
- enviar otro byte de control y esperar un ACK
- leemos el byte y esperar otro ACK
- vuelta al paso anterior por cada byte a leer
- bit de STOP al final
Para resolverlo mediante interrupciones utilizaremos una máquina con los siguientes estados :

Y haremos el intercambio de datos con la rutina de interrupción I2C mediante la siguiente estructura:

Sin más preámbulos, dejo aquí la rutina de interrupción, que lleva incorporados los comentarios para facilitar la comprensión.

Veamos un ejemplo de uso de esta función:

Y este es el resultado que obtenemos:

Si quieres descargar la rutina de interrupción I2C y el resto de código que te he mostrado en el artículo, puedes hacerlo aquí:
Nota: mi agradecimiento a Marcel CREMMEL, autor de la rutina original que yo he traducido y adaptado a mis necesidades. Artículo original
