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:






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:



www.microedu.es

Si chove, non orballa!