TODOPIC

Microcontroladores PIC => dsPIC => Mensaje iniciado por: blackcat en 11 de Septiembre de 2007, 02:24:05

Título: Memoria EEPROM por I2C
Publicado por: blackcat en 11 de Septiembre de 2007, 02:24:05
Hola

 No se si alguien me puede ayudar, estoy tratando de utilizar una memoria EEPROM 24FC512, que funciona con el puerto I2C de un dsPIC33F256MC710, la cosa es que no funciona!!!! y ya he buscado en todo el internet viendo a ver cual es el problema .. lo que hago es llamar las funciones I2C para escritura/lectura, esto esta en el main(); mi idea  es hacer unicamente dos funciones para I2C ... una que lea y otra que escriba,  :mrgreen:

La de escritura es solo mandar la direccion del dispositivo y escribir cuantos datos me de la gana ... igual la lectura, escribir la direccion del dispositivo y leer cuantos datos me de la gana, queria probar las rutinas con una memoria EEPROM ... OK para una memorilla de esas solo hay que escribir la primera direccion de memoria y mandar los datos y automaticamente la memoria incrementa la direccion, eso hago con el array eepromW, los dos primeros datos son las direcciones ( Hi y Lo ) el resto los datos, para la lectura igual, nada mas regreso la direccion inicial y luego hago la lectura ...

Para la lectura he visto que muchos mandan la direccion de dispositivo (A0), luego la posiciion de memoria inicial (0x0000).. realizan un RESTART, luego mandan la direccion de dispositivo( A1 )  y luego leer ...

Eso ya lo hice y no me funciono!  :x
 
Código: [Seleccionar]
unsigned char eepromW[] = {0, 0, 1, 2, 3, 4, 5, 6, 7, 8 };
unsigned char eepromR[] = {0, 0, 0, 0, 0, 0, 0, 0 };

IO_I2CConfig( );    /* Configuro el modulo */

IO_I2C1write( 0xA0, &eepromW[0], sizeof( eepromW ) );  /* Escribo datos*/

        /* Ahora quiero leerlos */
IO_I2C1write( 0xA0, &eepromW[0], 2 );     /* Regreso a la direccion inicial */

IO_I2C1read( 0xA1, &eepromR[0], sizeof( eepromR ) );  /* leo los datos */



  Ahora esto son las funciones I2C que estan en un archivo aparte ...

Código: [Seleccionar]


/*
***********************************************************************************************
* Configuracion del puerto I2C 1
***********************************************************************************************
*/
     
#define I2C1_EN_PERIPH 1 /* Habilita el modulo I2C1 */
#define I2C1_SCLREL 1 /* Release control bit, 0: Hold, 1: Release */
#define I2C1_IPMIEN 0 /* Intelligent Peripheral Management Ack, 0: Dis, 1: Ena */
#define I2C1_A10M 0 /* 10 bit Slave Add bit, 0: Dis, 1: Ena */
#define I2C1_DISSLW 0 /* Slew rate, 0: Dis, 1: En */
#define I2C1_SMEN 0 /* SMBus input levels bit, 0: Dis, 1: Ena */
#define I2C1_GCEN 0 /* General Call, 0: Dis, 1: Ena */
#define I2C1_STREN 0 /* Clock Stretch, 0: Dis, 1: Ena */
#define I2C1_ACKDT 0 /* ACK Data, 0: Send ACK, 1: Send NACK */
#define I2C1_ACKEN 0 /* ACK Sequence, 0: Dis, 1: Ena */
#define I2C1_RCEN 0 /* Receive Enable, 0: Dis, 1: Ena */
#define I2C1_PEN 0 /* Stop Condition, 0: Dis, 1: Ena */
#define I2C1_RSEN 0 /* Repeated Start Condition, 0: Dis, 1: Ena */
#define I2C1_SEN 0 /* Start Condition, 0: Dis, 1: Ena */
#define I2C1_FCLK 100 /* Serial Clock Rate, in kHz */

/*
*********************************************************************************************************
*
* Rutina de configuracion del modulo I2C 1
*
*
* Utilize el archivo IO_CFG.H para cambiar la configuracion
*
*********************************************************************************************************
*/

void IO_I2CConfig( void )
{
#if( I2C1_EN_PERIPH )

#if ( pin_RG2 != 0 )
#error "I2C1: EL pin RG2/SCL1 no esta configurado como salida "
#endif

ODCGbits.ODCG2 = 1;  //Activar le pull up!
ODCGbits.ODCG3 = 1;

I2C1CONbits.SCLREL = I2C1_SCLREL;
I2C1CONbits.IPMIEN = I2C1_IPMIEN;
I2C1CONbits.A10M = I2C1_A10M;
I2C1CONbits.DISSLW = !I2C1_DISSLW;
I2C1CONbits.SMEN = I2C1_SMEN;
I2C1CONbits.GCEN = I2C1_GCEN;
I2C1CONbits.STREN = I2C1_STREN;
I2C1CONbits.ACKDT = I2C1_ACKDT;
I2C1CONbits.ACKEN = I2C1_ACKEN;
I2C1CONbits.RCEN = I2C1_RCEN;
I2C1CONbits.PEN = I2C1_PEN;
I2C1CONbits.RSEN = I2C1_RSEN;
I2C1CONbits.SEN = I2C1_SEN;

I2C1BRG = ((CPU_MIPS * 1000) / I2C1_FCLK) - (CPU_MIPS/10) - 1;

I2C1RCV = 0x0000;
I2C1TRN = 0x0000;

I2C1CONbits.I2CEN = 1;

#endif
}

void IO_I2C1write( INT8U add, INT8U* data_out, INT16U length )
{

/* Wait until I2C Bus is Inactive */
    IdleI2C1( );
   
StartI2C1( );

WriteI2C1( add ); /* Write Slave address and set master for transmission */
IdleI2C1( );

/* Transmit data string */
while( length )
{
WriteI2C1( *data_out );
IdleI2C1( );

data_out++;
length--;
}

StopI2C1( );

}

void IO_I2C1read( INT8U add, INT8U* data_out, INT16U length )
{

/* Wait until I2C Bus is Inactive */
  IdleI2C1( );
 
StartI2C1( );

WriteI2C1( add ); /* Write Slave address and set master for transmission */

while(length) /* Receive the number of bytes specified by length */
       {
          I2C1CONbits.RCEN = 1;
          asm("nop");
          while( I2C1STATbits.RBF );
       
          *data_out = I2C1RCV; /* save byte received */
       
          data_out++;
          length--;
       
          if(length == 0) /* If last char, generate NACK sequence */
          {
              I2C1CONbits.ACKDT = 1;
              I2C1CONbits.ACKEN = 1;
          }
          else                         /* For other chars,generate ACK sequence */
         {
              I2C1CONbits.ACKDT = 0;
              I2C1CONbits.ACKEN = 1;
          }

          while(I2C1CONbits.ACKEN);    /* Wait till ACK/NACK sequence is over */
    }

StopI2C1( );

}

void WriteI2C1( INT8U data )
{
I2C1TRN = data;
while( I2C1STATbits.TBF );
}

void IdleI2C1( void )
{
    while( I2C1STATbits.TRSTAT );
}

void StartI2C1( void )
{
I2C1CONbits.SEN = 1; /* initiate Start on SDA and SCL pins */
while( I2C1CONbits.SEN ); /* Wait till Start sequence is completed */
}

void ReStartI2C1( void )
{
I2C1CONbits.RSEN = 1; /* initiate Start on SDA and SCL pins */
while( I2C1CONbits.RSEN ); /* Wait till Start sequence is completed */
}

void StopI2C1( void )
{
I2C1CONbits.PEN = 1; /* initiate Stop on SDA and SCL pins */
while( I2C1CONbits.PEN ); /* Wait till stop sequence is completed */
}

void CloseI2C1( void )
{

/* clear the I2CEN bit */
I2C1CONbits.I2CEN = 0;

/* clear the SI2C & MI2C Interrupt enable bits */
IEC1bits.SI2C1IE = 0;
IEC1bits.MI2C1IE = 0;

/* clear the SI2C & MI2C Interrupt flag bits */
IFS1bits.SI2C1IF = 0;
IFS1bits.MI2C1IF = 0;

}

/* FIN DE PAGINA */



Cuando ejecuto el codigo el arreglo con la salida de los datos son puros 0xFF ...

Ya revise las conexiones, todo esta bien, tiene las resistencias de pull-up, etc pero NO FUNKA!!!!  :x


Gracias a los que me ayuden ...
Título: Re: Memoria EEPROM por I2C
Publicado por: togarha en 11 de Septiembre de 2007, 03:57:23
Buenas,

Varios comentarios al respecto (por si pueden suponer algo de ayuda):

Citar
Para la lectura he visto que muchos mandan la direccion de dispositivo (A0), luego la posiciion de memoria inicial (0x0000).. realizan un RESTART, luego mandan la direccion de dispositivo( A1 )  y luego leer ...
Esto es para poner el puntero de direccion en la posicion correcta. Es lo que tienes que hacer

Por otro lado, el principal error supongo que lo tienes porque no estás haciendo escrituras paginadas, si miras el datasheet te dirá que puedes escribir un byte o una pagina, tu te estás quedando a mitad, ni un byte ni una pagina, no se si eso será posible, prueba grabando un byte y leyendo un byte.

Has comprobado con un osciloscopio, datalogger, etc que el micro saca la señal correcta? Seria una buena manera de empezar.

Comprueba los bits de colision, etc (aunque solo tengas un maestro y un esclavo), puede darte indicaciones de error de hardware/software.

Compruebas el ACK que te debe enviar la memoria? No lo compruebas, deberias saber si la memoria "se ha enterado" de tu petición de escritura.

En caso que la escritura se hiciese correctamente, debes darle más tiempo para leerla (seguro que no te contesta el ACK de la escritura del puntero de direccion, puesto que acaba de empezar el ciclo de escritura interna de la memoria eeprom), por tanto estarías leyendo en otra dirección, ya que no escribiria bien el puntero.

Espero que sirva de ayuda, comenta los avances y podremos seguir ayudandote...

Un saludo,



Título: Re: Memoria EEPROM por I2C
Publicado por: blackcat en 14 de Septiembre de 2007, 01:24:31
Hola

 Muchas gracias por tu respuesta ... pude hacer funcionar el I2C.. ! Tenia dos grandes problemas!!

1 - Tenia que poner un tiempo de almenos 1300ns entre cada llamada a las rutinas, segun la hoja de datos de la memoria es necesario esperar ese tiempo si se quiere accesar nuevamente al dispositivo.

2- Tambien tire a la basura la idea que tenia y segui tu recomendacion de enviar siempre ( en lectura y escritura ) la direccion de memoria, entiendo bien esto, pero queria hacer una rutina mas general .... pero ya que ... lo importante es que funcione bien

Saludos ...
Título: Re: Memoria EEPROM por I2C
Publicado por: togarha en 17 de Septiembre de 2007, 04:42:27
Buenas,

Me alegro mucho que se te haya solucionado el problema.

Un saludo,