Bus I2C - EEPROM AT25C32
1. Introducción:
Usaremos una placa comercial conocida como "Tiny Rtc".

2. Características:
El AT24C32 es una eeprom que aunque es un modelo un poco antiguo, nos sirve para probar y ver cómo funcionan estas memorias.
Tiene las siguientes características:
- Bus I2C compatibles: 1MHz, 400KHz, 100KHz.
- Array de memoria de 32 Kbit (4 KByte).
- Tamaños de página: 32Bytes.
- STensión de alimentación: 1.7 - 5.5 Vdc.
- Tiempo de escritura: 1 Byte - 5ms / 1 página - 5ms.
- Protección contra escritura.
- Ciclos de escritura: más de 4 millones.
- Más de 200 años de retención de datos.



3. Registros:
Este elemento permite conectarse a un bus I2C y podemos asignarle una dirección usando los pines A0, A1 y A2; esto
nos permmite tener varias memorias en un mismo bus pero con direcciones diferentes:


La memoria está formada por 4096 palabras de 8 bits. La primera dirección será la 0x0000 y la última la 0x0FFC (4092).
Para direccionar estos registros, no nos llega con un byte de dirección como en el caso del DS1307, sino que debemos enviar dos:


Nota: Para poder escribir, tenemos que colocar el pin WP a nivel alto.
4. Ejemplo escribir y leer en eeprom:
El siguiente proyecto consiste en escribir un registro de la eeprom y luego leerlo. Esto se repite 5 veces.
/* * File: main.c * Author: Eduardo * * Created on 5 de junio de 2017, 17:16 */ #include#include "config.h" #include "typedefs.h" #include "usart.h" #define SLAVE_I2C_ADDRESS 0x50 //PROTOTIPO DE LAS FUNCIONES USADAS void delay_ms(uint16_t); void escucharMensaje(void); void i2cInit(void); void busWrite (uint8_t data, int direc); unsigned char busRead (int direc); void IdleI2C(); void StartI2C(); void repStartI2C(); void WriteI2C(unsigned char d); char ReadI2C(); void Ack(); void NotAckI2C(); void StopI2C(); void imprimirValorInt (int valor); void main(void) { USART_Initialize(); // Inicializamos el puerto Serie i2cInit(); // Inicializamos la comunicacion I2C delay_ms(500); int b = 0; while (true) { printf ("Escribir y leer \n"); //Escribimos en la eeprom busWrite (b+2, b); delay_ms(500); //Leemos de la eeprom imprimirValorInt(busRead (b)); b ++; delay_ms(1000); while (b>5); } } /****************************************************************************** * FUNCION IMPRIMIR INT * * - Funcion que permite imprimir un int por la uart *****************************************************************************/ void imprimirValorInt (int valor) { unsigned char intStringVal[4]; itoa( intStringVal, valor,10); printf(intStringVal); printf("\n"); } /****************************************************************************** * FUNCION RETARDO DE mS * * - Funcion que realiza un retardo en mS segun el valor que recibe *****************************************************************************/ void delay_ms(uint16_t i) { for ( uint16_t x=0; x Fosc = 48MHz SSPSTAT = 0; //Ponemos a 0 este registro } /****************************************************************************** * FUNCION ENCARGADA DE ESCRIBIR REGISTROS EN EL SLAVE * * - Funcion realiza la secuencia necesaria para escribir registros en el * SLAVE. * - Recibe como parametros el dato y la direccion del registro a escribir *****************************************************************************/ void busWrite (uint8_t data, int direc) { StartI2C(); // Enviamos la condicion de inicio WriteI2C(((SLAVE_I2C_ADDRESS <<1) & 0xFE)); // Indicamos con que Slave nos queremos comunicar // Indicamos que vamos a escribirle uint8_t direc01 = direc >> 8; // Como necesitamos mas de 8 bits para direccionar uint8_t direc02 = direc - (direc01 << 8); // los registros, los separamos en 2 bytes WriteI2C(direc01); // Indicamos el registro del Slave al que queremos apuntar WriteI2C(direc02); // Indicamos el registro del Slave al que queremos apuntar WriteI2C(data); // Enviamos el dato a escribir en dicho registro StopI2C(); // Enviamos la condicion de fin } /****************************************************************************** * FUNCION ENCARGADA DE LEER REGISTROS EN EL SLAVE * * - Funcion realiza la secuencia necesaria para leer registros en el * SLAVE. * - Recibe como parametro la direccion del registro a leer *****************************************************************************/ char busRead (int direc) { unsigned char dataOut = 0; StartI2C(); // Enviamos la condicion de inicio WriteI2C(((SLAVE_I2C_ADDRESS <<1) & 0xFE)); // Indicamos con que Slave nos queremos comunicar // Indicamos que vamos a escribirle uint8_t direc01 = direc >> 8; // Como necesitamos mas de 8 bits para direccionar uint8_t direc02 = direc - (direc01 << 8); // los registros, los separamos en 2 bytes WriteI2C(direc01); // Indicamos el registro del Slave al que queremos apuntar WriteI2C(direc02); // Indicamos el registro del Slave al que queremos apuntar StartI2C(); // Volvemos a enviar la condicion de inicio WriteI2C(((SLAVE_I2C_ADDRESS <<1) | 0x01)); // Indicamos con que Slave nos queremos comunicar // Indicamos que vamos a leer dataOut = ReadI2C(); // Recogemos el dato del registro StopI2C(); // Enviamos la condicion de fin return dataOut; } /****************************************************************************** * FUNCION ENCARGADA DE COMPROBAR QUE NO ESTA OCUPADO EL BUS * * - Funcion que realiza una espera hasta que se puede usar el medio *****************************************************************************/ void IdleI2C() { while ((SSPSTAT & 0x04) || (0x1F & SSPCON2)); } /****************************************************************************** * FUNCION ENCARGADA DE ENVIAR UNA CONDICION DE INICIO * * - Funcion que indica que se va a transmitir por el bus *****************************************************************************/ void StartI2C() // Funcion que envia la condicion de inicio { IdleI2C(); // Esperamos el momento para transmitir SEN = 1; // SSPCON2 bit0. Envía la condición de Inicio while (SSPCON2bits.SEN); // Esperamos hasta que termine el Inicio } /****************************************************************************** * FUNCION ENCARGADA DE ENVIAR UNA CONDICION DE REINICIO * * - Funcion que indica que se continua con la transmision por el bus * Esta funcion se usa cuando el Master no quiere enviar una condicion de Fin * para no perder el bus ante otro Master. *****************************************************************************/ void repStartI2C() { IdleI2C(); // Esperamos el momento para transmitir RSEN=1; // SSPCON2 bit1. Envía la condición Reinicio while (SSPCON2bits.RSEN); // Esperamos hasta que termine el Reinicio } /****************************************************************************** * FUNCION ENCARGADA DE ENVIAR DATOS AL BUS I2C * * - Funcion que escribe en el buffer de salida *****************************************************************************/ void WriteI2C(unsigned char d) { IdleI2C(); // Esperamos el momento para transmitir SSPBUF = d; // Copiamos el dato al buffer } /****************************************************************************** * FUNCION ENCARGADA DE LEER DATOS DEL BUS I2C * * - Funcion que escribe en el buffer de salida *****************************************************************************/ uint8_t ReadI2C() { uint8_t a; IdleI2C(); // Esperamos el momento para transmitir RCEN = 1; // Habilitamos la recepcion I2C IdleI2C(); // Esperamos el momento para transmitir a = SSPBUF; // Copiamos el contenido del buffer IdleI2C(); // Esperamos el momento para transmitir NotAckI2C(); // Indicamos al Slave que hemos recogido el dato return a; // Devuelve el valor recibido } /****************************************************************************** * FUNCION ENCARGADA DE INDICAR QUE NO HUBO PROBLEMAS EN LA COMUNICACION * * - Funcion que responde indicando que los datos se han transmitido correctamente *****************************************************************************/ void Ack() { ACKDT = 0; //Indica que esperamos respuesta ACKEN = 1; //Enviamos ACK } /****************************************************************************** * FUNCION ENCARGADA DE INDICAR QUE HUBO PROBLEMAS EN LA COMUNICACION * * - Funcion que responde indicando que los datos no se han trasmitido correctamente *****************************************************************************/ void NotAckI2C() { ACKDT = 1; //Indica que no esperamos respuesta ACKEN = 1; //Enviamos ACK while (ACKEN); //Esperamos hasta que el Esclavo lo reciba SSPIF = 0; //Borramos la bandera de recepción } /****************************************************************************** * FUNCION ENCARGADA DE ENVIAR UNA CONDICION DE FIN * * - Funcion que indica que se deja el bus libre *****************************************************************************/ void StopI2C() { IdleI2C(); // Esperamos el momento para transmitir PEN = 1; // Habilitamos el bit de Stop while (SSPCON2bits.PEN); // Esperamos hasta que la condicion de Stop finalice }
- Leer y escribir en Eeprom:
5. Descargas: