Te muestro un ejemplo de utilización de rutinas I2C, para comunicarme con una memoria 24C04.
Separé tres bloques dentro del main, para que sea un poco mas legible.
El primer bloque, se comunica con la memoria para leer un dato (1 byte). Según el comportamiento de dicha memoria, se lee la posición actual de un contador interno que posee. Como es la primera vez que se accede, el contador apunta a la dirección 0x00.
En este bloque, el llamado a "i2cs_write(0b10100001)", corresponde a enviar -desde el micro- al bus la dirección correspondiente a la memoria. En este caso el bit de menor peso está a "1" indicando que quiero acceder como lectura.
En el segundo bloque, me comunico para grabar un byte, según especificaciones de la memoria 24C04.
En este bloque el llamado a "i2cs_write(0b10100000)", indica que me quiero comunicar con la memoria para escribir información. El llamado a "i2cs_write(0x02)", le indica al contador interno de la memoria que apunte a su dirección 0x02. Y el llamado a "i2cs_write(0x05)" es el propio dato a grabar.
En el tercer bloque, el llamado a "i2cs_write(0b10100000)" indica que me comunico con la memoria para escritura. El llamado a "i2cs_write(0x02)" le indica al contador interno que apunte a la dirección 0x02. Luego realizo un RepeateStart para reiniciar la comunicación. El llamado a "i2cs_write(0b10100001)" le indica que me quiero comunicar con la memoria para lectura.
Adjunto una captura donde se aprecia en el I2C DEBUGGER todo el proceso de la comunicación. Cada bloque de mi programa, aparece en un renglón. Realmente, cada renglón corresponde a un ciclo de comunicación, que comienza con un Start y termina con un Stop.
Te recomiendo leer algún documento respecto al protocolo I2C, para lograr comprender mejor su funcionamiento. También sería bueno que leyeras el datasheet de la 24C04 para poder comprender mejor el funcionamiento de este ejemplo.
#include <xc.h>
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#include "swi2c.h"
void main(void)
{
unsigned char data;
i2cs_start(); //comienzo comunicacion
i2cs_write(0b10100001); //accedo a la memoria para lectura (posicion actual)
i2cs_read(); //leo la memoria
i2cs_nack(); //no respondo
i2cs_stop(); //termino comunicacion
i2cs_start(); //comienzo comunicacion
i2cs_write(0b10100000); //accedo a la memoria para escritura
i2cs_write(0x02); //direccion que quiero escribir
i2cs_write(0x05); //dato a escribir
i2cs_stop(); //termino comunicacion
__delay_ms(5); //espero para que se grabe el dato en la memoria
i2cs_start(); //comienzo comunicacion
i2cs_write(0b10100000); //accedo a la memoria para escritura
i2cs_write(0x02); //direccion que quiero escribir
i2cs_start(); //comienzo comunicacion (para leer la posicion)
i2cs_write(0b10100001); //accedo a la memoria para lectura (posicion actual)
i2cs_read(); //leo la memoria
i2cs_nack(); //no respondo
i2cs_stop(); //termino comunicacion
while(1);
}