Autor Tema: dsPIC30F + EEPROM I2C  (Leído 11484 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
dsPIC30F + EEPROM I2C
« en: 10 de Marzo de 2008, 03:16:38 »
Llevo un par de días atascado con esto y necesito que alguien me eche una mano.

No consigo que funcione la conexión I2C de un dsPIC30F6014 con una EEPROM 24LC256; he probado utilizando el hardware del micro y sin usarlo, programando directamente sobre los pines data y clock.
Tengo puestas resistencias pullup de 10K en los pines, aunque antes tenía de 4K7 y tampoco iba.

La memoria va bien, porque puedo leerla y escribirla perfectamente con mi GTPUSB PLUS.

De hecho, ya no intento ni escribirla; la he rellenado de datos distintos a 0xFF y estoy probando sólo a leerla a ver si encuentro algo.

He hecho muchas pruebas y muchos cambios en mi código, pero os pego aquí la versión actual por si véis algún fallo. El programa está escrito en C30 y se asume incluída la librería "isc.h".

De todas maneras, me gustaría ver algún ejemplo de alguien que lo haya logrado. Gracias

Así configuro el I2C (el micro está trabajando a 32MIPS)
Código: C
  1. OpenI2C(I2C_ON & I2C_IDLE_CON & I2C_CLK_HLD & I2C_IPMI_DIS & I2C_7BIT_ADD & I2C_SLW_DIS & I2C_SM_DIS &
  2.          I2C_GCALL_DIS & I2C_STR_DIS & I2C_NACK & I2C_ACK_DIS & I2C_RCV_DIS & I2C_STOP_DIS & I2C_RESTART_DIS &
  3.          I2C_START_DIS,290);

Y esta es mi rutina de lectura:
Código: C
  1. void I2CDone() {
  2.         while(I2CCONbits.SEN );    //wait till start sequence is complete      
  3. }      
  4.  
  5. void I2CAck() {
  6.         AckI2C();
  7. }
  8.        
  9. void I2CNack() {       
  10.         NotAckI2C();
  11. }
  12.        
  13. char readByte_24512x8(long memaddress){
  14.  
  15. int address;
  16. char controlbyte;
  17. char data;
  18.  
  19. address=memaddress;
  20. controlbyte=0xa0;
  21.  
  22. IdleI2C();
  23. StartI2C();
  24. I2CDone();
  25.  
  26. MasterWriteI2C(controlbyte      );    // Write Slave address and set master for transmission
  27. I2CAck();
  28.  
  29. MasterWriteI2C(address>>8);     // Transmit data
  30. I2CAck();
  31.  
  32. MasterWriteI2C(address);     // Transmit data
  33. I2CAck();
  34.  
  35. RestartI2C();
  36. I2CDone();
  37.  
  38. MasterWriteI2C(controlbyte+1);
  39. I2CAck();
  40.  
  41. data = MasterReadI2C();
  42. I2CNack();
  43. StopI2C();
  44.  
  45. return data;
  46. }

Desconectado jfmateos2

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3145
Re: dsPIC30F + EEPROM I2C
« Respuesta #1 en: 10 de Marzo de 2008, 04:46:22 »
Es para un 33F, pero a lo mejor te ayuda: http://ww1.microchip.com/downloads/en/AppNotes/01079A.pdf

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: dsPIC30F + EEPROM I2C
« Respuesta #2 en: 10 de Marzo de 2008, 05:02:08 »
Ese ya casi me lo sé de memoria, Juanfe. No miro otra cosa los dos últimos días.
Gracias por pasármelo, pero sigo sin conseguirlo aún...  :(

Desconectado stk500

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4919
Re: dsPIC30F + EEPROM I2C
« Respuesta #3 en: 10 de Marzo de 2008, 07:26:41 »
Manolo a ver si te sirve esto
http://www.opencircuits.com/DsPIC30F_5011_Development_Board#Code_Examples aqui lei que debe poner en los pine resistencia de 2k2 Ohm y esto
http://electronique.marcel.free.fr/dsPIC/Programmes/I2C/I2C_dsPIC.pdf
espero te sirva
salute



Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: dsPIC30F + EEPROM I2C
« Respuesta #4 en: 11 de Marzo de 2008, 15:52:39 »
Yo lo hago de esta manera y si me funciona bien en C30

Código: [Seleccionar]
unsigned int IO_I2C2pageHDread(unsigned char add, unsigned int dir, unsigned char *rdptr, unsigned char length)
{

INT8U err, i2c_err;
INT8U retry = 4;

OSSemPend( I2C2_Sem, 0, &err );  // Pedir semaforo a RTOS

do{

i2c_err = 0;

IdleI2C2(); //wait for bus Idle
StartI2C2(); //Generate Start condition

if( WriteI2C2( add & 0xFE ) != 0 ) i2c_err++;           //send device address for a write

IdleI2C2(); //wait for bus Idle

if( WriteI2C2( (dir >> 8) & 0x00FF ) != 0 ) i2c_err++;                //send memory address

IdleI2C2();   //wait for bus Idle

if( WriteI2C2( ( dir ) & 0x00FF   ) != 0 ) i2c_err++;                    //send memory address

IdleI2C2();

RestartI2C2(); //Generate I2C Restart Condition

if( WriteI2C2( add | 0x01 ) != 0 ) i2c_err++;            //send memory address ( READ )

IdleI2C2(); //wait for bus Idle

getsI2C2(rdptr, length);     //Read in multiple bytes

NotAckI2C2();       //send Not Ack

StopI2C2(); //Generate a stop

retry--;

}
while( i2c_err & retry );

err = OSSemPost( I2C2_Sem );

if( retry ) return 0;
else return 1;

}


Cuando escribes debes esperar un ACK de la memoria ... además la velocidad de una memoria de esas no debe ser mayor a 400kHz ... creo ... pero supongo que ya intentaste con la velocidad mas baja, además las resistencias que tengo son de 1.2k ... yo depure el código utilizando un ORC ..


Esta es la rutina de escritura ... observa que espero el ACK ..

Código: [Seleccionar]
unsigned int WriteI2C2(unsigned char byte)
{

unsigned int time = I2C_TIMEOUT;

I2C2TRN = byte; //Load byte to I2C2 Transmit buffer
while (I2C2STATbits.TBF) //wait for data transmission
{
if( time == 0 ) return -3;
else time--;

if( I2C2STATbits.BCL ) return -4;
}

time = I2C_TIMEOUT;

    if(I2C2STATbits.IWCOL) return -1; /* If write collision occurs,return -1 */
    if(I2C2STATbits.BCL) return -2; /* If bus collision occurs,return -1 */
   
while( I2C2STATbits.ACKSTAT ) //Espera ACK del SLAVE sino salir
{
if( time == 0 ) return -3;
else time--;

if( I2C2STATbits.BCL ) return -4;
};

return 0;

}
« Última modificación: 11 de Marzo de 2008, 15:58:47 por blackcat »
Control Automático, DSP & Microcontroladores

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: dsPIC30F + EEPROM I2C
« Respuesta #5 en: 11 de Marzo de 2008, 15:58:17 »
Ya estoy a punto de conseguirlo con el código que publicó Rafael. la lectura ya la he implementado; sólo me falta la escritura. La verdad es que después de haberme roto los sesos para entenderlo porque los comentarios estaban en francés, me alegro de haberlo resuelto porque todo funciona por interrupciones.
Ya lo pego aquí cuando lo termine. Gracias Blackcat

¿Qué es un ORC?

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: dsPIC30F + EEPROM I2C
« Respuesta #6 en: 11 de Marzo de 2008, 16:05:41 »
Bueno un osciloscopio de rayos catodicos ....   :)  .... pero eso de los rayos catodicos creo que ya no se usa pues ahora casi todos son digitales  :D :D

Pero mejor te incluyo la rutina de C del codigo que utilizo quiza te pueda servir de algo ...

Te podra parecer un poco complicado pues del proyecto que tengo la configuracion de I2C debo poder modificarla en tiempo de ejecucion ... y no en tiempo de compilacion como normalmente se hace


Esas rutinas son modificadas de unos ejemplos de microchip ... pues como es comun ... las baje y no me funcionaron ... entonces las modifique un poco
« Última modificación: 11 de Marzo de 2008, 16:45:08 por blackcat »
Control Automático, DSP & Microcontroladores

Desconectado manex_1987

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1127
Re: dsPIC30F + EEPROM I2C
« Respuesta #7 en: 12 de Marzo de 2008, 20:21:17 »
Aer. Almenos en algo te voy a poder ayudar, espero! jajaj  Bueno, te pego mi codigo. Los comentarios estan en vasco y estoy perezoso para borrar todos... pero bueno aver que tal.
Código: [Seleccionar]

#define IDATZI_EEPROM 0
#define IRAKURRI_EEPROM 1
#define IDATZI_SRF 2
#define IRAKURRI_SRF 3

void HasiI2C()
{
I2CCON=0b1001000000000000;
I2CBRG=181;
}

void EEPROMEscribirDato(unsigned char data,unsigned int helbidea, unsigned char bankua)
{

I2CHasiEragiketa(IDATZI_EEPROM,helbidea,bankua);

IdatziI2C(data);

I2CCONbits.PEN=1;
while(I2CCONbits.PEN);
}

void I2CHasiEragiketa(unsigned char modua,unsigned int helbidea,unsigned char bankua)
{
unsigned char temp;

while(I2CCONbits.SEN || I2CCONbits.PEN || I2CCONbits.RCEN ||
  I2CCONbits.ACKEN || I2CSTATbits.TRSTAT);

I2CCONbits.SEN=1;
while(I2CCONbits.SEN);

if(modua==IDATZI_EEPROM)temp=0b10100000|(bankua<<3);
else if (modua==IRAKURRI_EEPROM) temp=0b10100001|(bankua<<3);

else if (modua==IDATZI_SRF) temp=0b11100000; //SRF-aren helbidea 0xE0 da
else if (modua==IRAKURRI_SRF) temp=0b11100001; //SRF irakurtzeko

I2CTRN=temp;

while(I2CSTATbits.TRSTAT);

I2CTRN=(unsigned char)(helbidea>>8);

while(I2CSTATbits.TRSTAT);


I2CTRN=(unsigned char)helbidea;

while(I2CSTATbits.TRSTAT);

}

void IdatziI2C(unsigned char data)
{

I2CTRN=data;

while(I2CSTATbits.TRSTAT);

}



Si teneis alguna duda me decis. Aver, cursillo acelerado de vascuence: HELBIDEA = DIRECCION. No creo que haga falta mas, lo demas se deduce facilmente.

Que engorro el vasco eh... jejje  :P si hay algun problema me comentais. Nocturno si quieres alguna rutina mas me lo dices por msn.

un saludo

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: dsPIC30F + EEPROM I2C
« Respuesta #8 en: 12 de Marzo de 2008, 22:10:52 »
Chanfle!  :?
Control Automático, DSP & Microcontroladores

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: dsPIC30F + EEPROM I2C
« Respuesta #9 en: 13 de Marzo de 2008, 01:59:22 »
Arggggg, deja, deja, que ya lo he pasado mal interpretando el francés del código que me pasó Rafael, como para ponerme ahora con el Euskera...

Aquí dejo la adaptación que he realizado del código que ya funciona perfectamente, con la ventaja de que toda la gestión la hace por Interrupciones, así que nuestro dsPIC quedará libre para otras tareas.
En todas las rutinas que había visto hasta ahora había "delays" o "while (bit de estado);" que sumían al dsPIC en una nerviosa espera comiendo ciclos mientras llegaba un dato o un ack por el bus I2C. En esta el dsPIC se podrá dedicar a otras cosas con la tranquilidad de que la interrupción del I2C lo llamará cuando sea necesario.

Para utilizarlo, he creado una estructura en C que es la siguiente:
Código: C
  1. typedef struct
  2.  {
  3.   unsigned char Adr_I2C;    // Dirección del dispositivo I2C
  4.   unsigned int  Direccion;      // Posición de memoria a la que apuntamos.
  5.   unsigned int  Longitud;       // Nº de bytes que se van a transmitir
  6.   unsigned char *Datos;         // Puntero a los datos que se transmitirán
  7.   unsigned char Sentido;        // 0 = Escritura; 1 = Lectura
  8.  } tCOM_I2C;
Una vez cumplimentada con la información necesaria, simplemente llamamos a la función ComunicacionI2C que lanza el proceso.

Dicho proceso está basado en una máquina de estados. A lo largo de la comunicación, la máquina va cambiando de un estado a otro en función de lo que esté ocurriendo en cada momento. Los estados que se utilizan son estos:
Código: C
  1. typedef enum
  2. {
  3.   Start    = 0,
  4.   Envia    = 1,
  5.   Recibe   = 2,
  6.   Restart  = 3,
  7.   MAck     = 4,
  8.   Stop     = 5
  9. }tSecuenciaI2C; // Tipo de secuencia de I2C

La rutina de interrupción es la siguiente:
Código: C
  1. // Interrupción I2C
  2. void _ISR __attribute__((interrupt, auto_psv)) _MI2CInterrupt (void)
  3. {
  4.  IFS0bits.MI2CIF=0; // Borramos flag de interrupción
  5.  if (COM_I2C.Sentido==Escritura)
  6.  {
  7.   // Acceso de escritura
  8.   // *****************
  9.   switch (EstadoI2C)
  10.   {
  11.    case Start : // Fin de secuencia START
  12.    {
  13.     I2CTRN=COM_I2C.Adr_I2C;                     // El primer byte de pDatas_I2C contiene la ADDRESS (A0 en eeprom)
  14.     EstadoI2C=Envia;                                    // El siguiente paso será Envia
  15.     break;
  16.    }
  17.    case Envia :                                                 // Ya se ha enviado otro byte
  18.    {
  19.     BytesTransmitidos++;                                // Incremento de nº de bytes transmitidos
  20.     // los bytes 1 y 2 son la posición de memoria
  21.     // Enviamos el byte de dirección que corresponda (alto y bajo)  
  22.     if (BytesTransmitidos == 1)
  23.     {
  24.      I2CTRN=COM_I2C.Direccion>>8;               // enviamos la parte alta de la dirección
  25.      break;
  26.     }
  27.     if (BytesTransmitidos == 2)
  28.     {
  29.      I2CTRN=COM_I2C.Direccion & 0xFF;   // enviamos la parte baja de la dirección
  30.      break;
  31.     }
  32.     if (I2CSTATbits.ACKSTAT)                    // ¿Ha llegado un NACK?
  33.     {
  34.      EstadoI2C=Stop;                                    // Activamos la secuencia de Stop
  35.      I2CCONbits.PEN=1;                                  // y finalizamos la comunicación
  36.      break;
  37.     }
  38.     if (BytesTransmitidos < (COM_I2C.Longitud + 3)) // ¿Todavía no hemos llegado al final?
  39.     {
  40.      I2CTRN=*COM_I2C.Datos;                     // Enviamos otro byte
  41.      COM_I2C.Datos++;                                   // e incrementamos el puntero
  42.      break;
  43.     }
  44.     if (BytesTransmitidos==(COM_I2C.Longitud+3)) // ¿Hemos llegado al final?
  45.     {
  46.      EstadoI2C=Stop;                                    // Activamos la secuencia de Stop
  47.      I2CCONbits.PEN=1;                                  // y finalizamos la comunicación
  48.      break;
  49.     }
  50.    }
  51.    case Stop : // Final de secuencia
  52.    {
  53.     break;
  54.    }
  55.   }
  56.  }
  57.  else
  58.  {
  59.   // Acceso de lectura
  60.   // ****************
  61.   switch (EstadoI2C)
  62.   {
  63.    case Start :                                                 // Fin de secuencia START
  64.    {
  65.     I2CTRN=COM_I2C.Adr_I2C;                     // El primer byte de pDatas_I2C contiene la ADDRESS (A0 en eeprom)
  66.     EstadoI2C=Envia;                                    // El siguiente paso será Envia
  67.     break;
  68.    }
  69.    case Envia :                                                 // Ya se ha enviado otro byte
  70.    {
  71.     if (I2CSTATbits.ACKSTAT)                    // ¿Fin de la comunicación?
  72.     {
  73.      EstadoI2C=Stop;                                    // NACK : El siguiente paso será STOP
  74.      I2CCONbits.PEN=1;                                  // Activar la secuencia de STOP
  75.      break;
  76.     }
  77.     BytesTransmitidos++;                                // Incremento de nº de bytes transmitidos
  78.     // los bytes 1 y 2 son la posición de memoria
  79.     // Enviamos el byte de dirección que corresponda (alto y bajo)  
  80.     if (BytesTransmitidos == 1)
  81.     {
  82.      I2CTRN=COM_I2C.Direccion>>8;               // enviamos la parte alta de la dirección
  83.      break;
  84.     }
  85.     if (BytesTransmitidos == 2)
  86.     {
  87.      I2CTRN=COM_I2C.Direccion & 0xFF;   // enviamos la parte baja de la dirección
  88.      break;
  89.     }
  90.     if (BytesTransmitidos==3)                   // Ya hemos enviado la dirección completa, ahora toca RESTART
  91.     {
  92.      EstadoI2C=Restart;                                 // Siguiente paso: RESTART
  93.      I2CCONbits.RSEN=1;                         // Activamos
  94.      break;
  95.     }
  96.     if (BytesTransmitidos==4)                   // Se ha enviado ya la ID + Dir alto + Dir bajo. Ahora a recibir
  97.     {
  98.      EstadoI2C=Recibe;                                  // Siguiente paso: RECIBIR
  99.      BytesTransmitidos=0;                               // Empezamos de nuevo el recuento de bytes recibidos
  100.      I2CCONbits.RCEN=1;                                 // Activamos secuencia de recepción
  101.      break;
  102.     }
  103.    }
  104.    case Restart :                                               // Fin de la secuencia Restart
  105.    {
  106.     I2CCONbits.ACKDT=0;                                 // A partir de ahora siempre contestaremos ACK 0
  107.     I2CTRN=COM_I2C.Adr_I2C+1;                   // Enviamos la dirección del dispositivo con el bit de lectura marcado
  108.     EstadoI2C=Envia;                                    // Siguiente paso: ENVIAR
  109.     break;
  110.    }
  111.    case Recibe :                                                // Se ha recibido un BYTE
  112.    {
  113.     BytesTransmitidos++;                        // Incrementamos el contador de bytes
  114.     *COM_I2C.Datos=I2CRCV;                              // Almacenamos el dato
  115.         COM_I2C.Datos++;                                // e incrementamos el array
  116.    
  117.     if (BytesTransmitidos==COM_I2C.Longitud)
  118.         I2CCONbits.ACKDT=1;                     // En la siguiente devolvemos un NACK
  119.     I2CCONbits.ACKEN=1;                                 // Activamos la respuesta del ACK
  120.     EstadoI2C=MAck;                                             // Y ese será el siguiente estado
  121.     break;
  122.    }
  123.    case MAck :                                                  // Finalizamos la secuencia
  124.    {
  125.     if (BytesTransmitidos==COM_I2C.Longitud)
  126.      {
  127.       EstadoI2C=Stop;                                   // NACK : El siguiente paso será STOP
  128.       I2CCONbits.PEN=1;                         // Activar la secuencia de STOP
  129.      }
  130.     else
  131.      {
  132.       EstadoI2C=Recibe;                                 // Nueva secuencia de recepción
  133.       I2CCONbits.RCEN=1;                                // activamos la secuencia
  134.      }
  135.     break;
  136.    }
  137.    case Stop : // Final de secuencia
  138.    {
  139.     break;
  140.    }
  141.   }
  142.  }
  143. }

En este ejemplo vemos qué fácil es utilizar este sistema una vez integrado en nuestro programa:

Código: C
  1. // Inicializamos el buffer con un valor determinado
  2.         for (i=0;i<50;i++)
  3.                 BufferI2C[i]=i;
  4.        
  5.         // Vamos a iniciar una secuencia de escritura en la EEPROM
  6.         COM_I2C.Adr_I2C=0xA0;                   // Identificación de la EEPROM
  7.         COM_I2C.Direccion=0x0000;               // Vamos a escribir en la dirección 0x0123
  8.         COM_I2C.Datos=&BufferI2C;               // Puntero a nuestro Buffer
  9.         COM_I2C.Longitud=50;                    // Número de bytes a transmitir
  10.         COM_I2C.Sentido=Escritura;              // Vamos a escribir
  11.         ComunicacionI2C();                              // Lanzamos la comunicación
  12.        
  13.         printf ("\n\rEscribiendo 50 bytes");
  14.         delay_ms(100);
  15.        
  16.         // Ahora vamos a leer de la EEPROM lo que hemos escrito
  17.         COM_I2C.Adr_I2C=0xA0;                   // Identificación de la EEPROM
  18.         COM_I2C.Direccion=0x0000;               // Vamos a leer desde la dirección 0x0123
  19.         COM_I2C.Datos=&BufferI2C;               // Puntero a nuestro Buffer
  20.         COM_I2C.Longitud=50;                    // Número de bytes a transmitir
  21.         COM_I2C.Sentido=Lectura;                // Vamos a leer
  22.         ComunicacionI2C();                              // Lanzamos la comunicación
  23.         delay_ms(100);
  24.        
  25.         printf ("\n\rLeido: ");  
  26.        
  27.         for (i=0;i<50;i++)
  28.                 printf ("%u ",BufferI2C[i]);

Y aquí el resultado de este ejemplo:


Dejo adjunto el programa completo por si alguien lo quiere descargar. Gracias a todos los que me habéis ayudado.

Desconectado stk500

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4919
Re: dsPIC30F + EEPROM I2C
« Respuesta #10 en: 13 de Marzo de 2008, 02:09:57 »
 :D :D eso te va a costar una botella de ron manolo  :D :D :D :D
en hora buena genio de la botella  :D :D

Desconectado blackcat

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 600
Re: dsPIC30F + EEPROM I2C
« Respuesta #11 en: 13 de Marzo de 2008, 03:16:20 »
Muy buena propuesta ...  :mrgreen: :mrgreen:  diferente a todas! me gusta mucho pues le veo un gran potencial para utilizarlo con un RTOS

Si me permites le hare algunas modificaciones .. viendo el código siempre esperas el fin de la transmisión con un delay ... en este caso con un RTOS la tarea de comunicación se deja "dormida" con un semaforo ( PEND ) ..  esto hara que el RTOS habilite otras tareas mientras se esta transmitiendo .. cuando la comunicación termine se utiliza un POST dentro de la misma rutina de servicio que despierta la tarea .... y asi continuar el código ... 

Excelente ...  :o :o

Control Automático, DSP & Microcontroladores

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: dsPIC30F + EEPROM I2C
« Respuesta #12 en: 13 de Marzo de 2008, 03:17:50 »
Sí, claro, lo de los delay_ms están ahí porque es un ejemplo. Obviamente en una aplicación real no tiene sentido utilizarlos si pretendemos tener al micro ocupado.

Desconectado marielys_ng

  • PIC10
  • *
  • Mensajes: 3
Re: dsPIC30F + EEPROM I2C_ DRIVER PARA MANEJO DEL RTC(DS1307) Y EEPROM I2C
« Respuesta #13 en: 27 de Mayo de 2009, 15:25:39 »
fUNCIONA EXCELENTE, LO TRABAJE CON UN DSPIC QUE OPERA A 64MHZ

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//        DRIVER PARA MANEJO DEL RTC(DS1307) Y EEPROM POR EL BUS I2C       //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////


/***************************************************************************
                       FUNCIONES PARA MANEJO DEL BUS I2C
****************************************************************************/
//Declaracion de funciones
void ini_i2c(void);
void start(void);
void stop(void);
void restart(void);
int write(unsigned char);
unsigned char read(void);

/****************************************************************************
FUNCIÓN DE INICIALIZACIÓN DE I2C:
****************************************************************************/
void ini_i2c(void)
{
   I2CBRG = 0x091;    /*I2CBRG=[(Fcy/Fscl)-(Fcy/1111111)-1]Hz
                  Fcy=16MHz y Fscl=100KHz* ==>> 145*/
   I2CCON = 0x1200;
   I2CRCV = 0;
   I2CTRN = 0;
   I2CSTAT = 0;
   IFS0bits.MI2CIF=0;    /*I2C Bus Collision Flag Status bit
                  1 = Interrupt request has occurred
                  0 = Interrupt request has not occurred*/
   IFS0bits.SI2CIF=0;    /*I2C Transfer Complete Interrupt Flag Status bit
                  1 = Interrupt request has occurred
                  0 = Interrupt request has not occurred*/
   I2CCONbits.I2CEN=1;
}
/****************************************************************************
FUNCIÓN DE CONDICIÓN START:
****************************************************************************/
void start()
{   
   IdleI2C();
   IFS0bits.MI2CIF=0;
   I2CCONbits.SEN=1;
   while(!IFS0bits.MI2CIF);   
}
/****************************************************************************
FUNCIÓN DE CONDICIÓN STOP:
****************************************************************************/
void stop()
{
   IdleI2C();
   IFS0bits.MI2CIF=0;
   I2CCONbits.PEN = 1;
   while(!IFS0bits.MI2CIF);   
}
/****************************************************************************
FUNCIÓN DE CONDICIÓN RESTART:
****************************************************************************/
void restart()
{
   IdleI2C();
   IFS0bits.MI2CIF=0;
   I2CCONbits.RSEN=1;
   while(!IFS0bits.MI2CIF);
}
/****************************************************************************
FUNCIÓN DE ESCRITURA EN EL BUS I2C:
****************************************************************************/
int write(unsigned char dato)
{
   IFS0bits.MI2CIF=0;
   I2CTRN=dato;
   while(I2CSTATbits.TBF);
   while(!IFS0bits.MI2CIF);
   if(!I2CSTATbits.ACKSTAT)
   {
      return(0);
   }
   else
   {
      return(1);   //Error
   }
   
}
/****************************************************************************
FUNCIÓN DE LECTURA EN EL BUS I2C:
****************************************************************************/
unsigned char read()
{
   unsigned char dato;
   IFS0bits.MI2CIF=0;
   I2CCONbits.RCEN=1;
   while(!IFS0bits.MI2CIF);
   dato=I2CRCV;
   while(I2CSTATbits.RBF);
   IFS0bits.MI2CIF=0;
   I2CCONbits.ACKDT=1;   //Condición NACK
   I2CCONbits.ACKEN=1;
   while(!IFS0bits.MI2CIF);
   return(dato);
}

/*.........................................................................*/


/***************************************************************************
                         FUNCIONES PARA EL RTC(DS1307)
****************************************************************************/
//Declaracion de variables
unsigned char seg,min,hora,dia,fecha,mes,ano,control;

//Declaracion de funciones
void conf_rtc();
void ds1307_hora(unsigned char, unsigned char,unsigned char,unsigned char);
void ds1307_fecha(unsigned char, unsigned char,unsigned char,unsigned char);
unsigned char lee_ds1307 (unsigned char);
unsigned char bin2bcd(unsigned char);


/****************************************************************************
FUNCIÓN DE CONFIGURACIÓN:
Permite cargar los los valores para los registros que configuran el RTC con
valores introducidos mediante el teclado
****************************************************************************/
void conf_rtc()
{
   int p=0,h=0;
   char j=0,t;
   p=1;

   while(p==1)
   {
      lcd_enviar(0,0x01);
      lcd_gotoxy(1,1);   lcd_dato("* CONFIG. RTC *");
      lcd_gotoxy(3,1);    lcd_dato("1)CONFIGURAR");   
      lcd_gotoxy(4,1);    lcd_dato("2)ESC");
      delay(500000);
      while((j=tecla())==0);
      h=tecla_int(j);

      if(h==1)
      {
         delay(500000);

         t=0;
         while(t!='.')
         {
            lcd_enviar(0,0x01);   
            lcd_gotoxy(1,1);   lcd_dato("seg=");
            seg=bin2bcd(calcu_int(2,1,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               seg=0;            
               lcd_gotoxy(1,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(1,9);   lcd_dato("min=");
            min=bin2bcd(calcu_int(2,1,13));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               min=0;            
               lcd_gotoxy(1,13);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(2,1);   lcd_dato("hra=");
            hora=bin2bcd(calcu_int(2,2,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               hora=0;            
               lcd_gotoxy(2,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(2,9);   lcd_dato("dia=");
            dia=bin2bcd(calcu_int(2,2,13));            
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               dia=0;            
               lcd_gotoxy(2,13);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(3,1);   lcd_dato("fec=");
            fecha=bin2bcd(calcu_int(2,3,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               fecha=0;            
               lcd_gotoxy(3,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(3,9);   lcd_dato("mes=");
            mes=bin2bcd(calcu_int(2,3,13));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               mes=0;            
               lcd_gotoxy(3,13);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(4,1);   lcd_dato("ano=");
            ano=bin2bcd(calcu_int(2,4,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               ano=0;            
               lcd_gotoxy(4,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(4,9);   lcd_dato("c_b=");
            control=bin2bcd(calcu_int(2,4,13));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               control=0;            
               lcd_gotoxy(4,13);   lcd_dato("  ");

            }
         }

      }

      if(h==2)
      {
         p=0;
      }
   }
}
/****************************************************************************
FUNCIÓN DE BINARIO A BCD:
****************************************************************************/
unsigned char bin2bcd(unsigned char binary_value)
{
   int temp;
     int retval;
     temp = binary_value;
     retval = 0;
    while(1)
     {
       // Get the tens digit by doing multiple subtraction
       // of 10 from the binary value.
       if(temp >= 10)
       {
            temp -= 10;
            retval += 0x10;
       }
         else // Get the ones digit by adding the remainder.
         {
           retval += temp;
            break;
         }
     }
     return(retval);
}
/****************************************************************************
FUNCIÓN DE LECTURA DEL DS1307:
****************************************************************************/
unsigned char lee_ds1307(unsigned char registro)

   unsigned char data;
   unsigned int status;

   IdleI2C();
   start();
   status=write(0xD0);
   if(status==0)
   {
      status=write(registro);
      if(status==0)
      {      
         restart();
         status=write(0xD1);
         if(status==0)
         {
            data=read();
            stop();
         }
      }
   }
   else
   {
      stop();
   }
   return(data);
}
/****************************************************************************
FUNCIÓN DE ESCRITURA DEL DS1307:
****************************************************************************/
void ds1307_hora(unsigned char seg, unsigned char min,unsigned char hora,
             unsigned char dia)

   unsigned int status;

   IdleI2C();
   start();
   status=write(0xD0);
   if(status==0)
   {
      status=write(0x00);
      if(status==0)
      {
         status=write(seg);
         if(status==0)
         {
            status=write(min);
            if(status==0)
            {
               status=write(hora);
               if(status==0)
               {
                  status=write(dia);
                  if(status==0)
                  {   
                     stop();
                  }
               }
            }
         }
      }
   }
   else
   {
      stop();
   }
}

void ds1307_fecha(unsigned char fecha, unsigned char mes,unsigned char ano,
              unsigned char control)

   unsigned int status;

   IdleI2C();
   start();
   status=write(0xD0);
   if(status==0)
   {
      status=write(0x04);
      if(status==0)
      {
         status=write(fecha);
         if(status==0)
         {
            status=write(mes);
            if(status==0)
            {
               status=write(ano);
               if(status==0)
               {
                  status=write(control);
                  if(status==0)
                  {
                     stop();
                  }
               }
            }
         }
      }
   }
   else
   {
      stop();
   }
}


/*.........................................................................*/


/***************************************************************************
                       FUNCIONES PARA LA MEMORIA EEPROM
****************************************************************************/
//Declaración de funciones
void escribe_eeprom(unsigned int,unsigned char);
unsigned char lee_eeprom(unsigned int);

/****************************************************************************
FUNCIÓN DE ESCRITURA DE EEPROM:
****************************************************************************/
void escribe_eeprom(unsigned int address,unsigned char data)

   unsigned int status;

   IdleI2C();
   start();
   status=write(0xA0);
   if(status==0)
   {
      IdleI2C();
      status=write(address>>8);
      if(status==0)
      {
         status=write(address);
         if(status==0)
         {
            status=write(data);
            if(status==0)
            {
               stop();
            }
         }
      }
   }
   else
   {
      stop();
   }
}
/****************************************************************************
FUNCIÓN DE LECTURA DE EEPROM:
****************************************************************************/
unsigned char lee_eeprom(unsigned int address)
{
   unsigned char data;
   unsigned int status;

   start();
   status=write(0xA0);
   if(status==0)
   {
      status=write(address>>8);
      if(status==0)
      {      
         status=write(address);
         if(status==0)   
         {
            restart();
            status=write(0xA1);
            if(status==0)
            {
               data=read();
               stop();
            }
         }
      }
   }
   else
   {
      stop();
   }
   return(data);
}




Desconectado stevengalindom

  • PIC10
  • *
  • Mensajes: 18
con que cristal lo manejas?
« Respuesta #14 en: 16 de Agosto de 2011, 12:55:43 »
fUNCIONA EXCELENTE, LO TRABAJE CON UN DSPIC QUE OPERA A 64MHZ

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//        DRIVER PARA MANEJO DEL RTC(DS1307) Y EEPROM POR EL BUS I2C       //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////


/***************************************************************************
                       FUNCIONES PARA MANEJO DEL BUS I2C
****************************************************************************/
//Declaracion de funciones
void ini_i2c(void);
void start(void);
void stop(void);
void restart(void);
int write(unsigned char);
unsigned char read(void);

/****************************************************************************
FUNCIÓN DE INICIALIZACIÓN DE I2C:
****************************************************************************/
void ini_i2c(void)
{
   I2CBRG = 0x091;    /*I2CBRG=[(Fcy/Fscl)-(Fcy/1111111)-1]Hz
                  Fcy=16MHz y Fscl=100KHz* ==>> 145*/
   I2CCON = 0x1200;
   I2CRCV = 0;
   I2CTRN = 0;
   I2CSTAT = 0;
   IFS0bits.MI2CIF=0;    /*I2C Bus Collision Flag Status bit
                  1 = Interrupt request has occurred
                  0 = Interrupt request has not occurred*/
   IFS0bits.SI2CIF=0;    /*I2C Transfer Complete Interrupt Flag Status bit
                  1 = Interrupt request has occurred
                  0 = Interrupt request has not occurred*/
   I2CCONbits.I2CEN=1;
}
/****************************************************************************
FUNCIÓN DE CONDICIÓN START:
****************************************************************************/
void start()
{   
   IdleI2C();
   IFS0bits.MI2CIF=0;
   I2CCONbits.SEN=1;
   while(!IFS0bits.MI2CIF);   
}
/****************************************************************************
FUNCIÓN DE CONDICIÓN STOP:
****************************************************************************/
void stop()
{
   IdleI2C();
   IFS0bits.MI2CIF=0;
   I2CCONbits.PEN = 1;
   while(!IFS0bits.MI2CIF);   
}
/****************************************************************************
FUNCIÓN DE CONDICIÓN RESTART:
****************************************************************************/
void restart()
{
   IdleI2C();
   IFS0bits.MI2CIF=0;
   I2CCONbits.RSEN=1;
   while(!IFS0bits.MI2CIF);
}
/****************************************************************************
FUNCIÓN DE ESCRITURA EN EL BUS I2C:
****************************************************************************/
int write(unsigned char dato)
{
   IFS0bits.MI2CIF=0;
   I2CTRN=dato;
   while(I2CSTATbits.TBF);
   while(!IFS0bits.MI2CIF);
   if(!I2CSTATbits.ACKSTAT)
   {
      return(0);
   }
   else
   {
      return(1);   //Error
   }
   
}
/****************************************************************************
FUNCIÓN DE LECTURA EN EL BUS I2C:
****************************************************************************/
unsigned char read()
{
   unsigned char dato;
   IFS0bits.MI2CIF=0;
   I2CCONbits.RCEN=1;
   while(!IFS0bits.MI2CIF);
   dato=I2CRCV;
   while(I2CSTATbits.RBF);
   IFS0bits.MI2CIF=0;
   I2CCONbits.ACKDT=1;   //Condición NACK
   I2CCONbits.ACKEN=1;
   while(!IFS0bits.MI2CIF);
   return(dato);
}

/*.........................................................................*/


/***************************************************************************
                         FUNCIONES PARA EL RTC(DS1307)
****************************************************************************/
//Declaracion de variables
unsigned char seg,min,hora,dia,fecha,mes,ano,control;

//Declaracion de funciones
void conf_rtc();
void ds1307_hora(unsigned char, unsigned char,unsigned char,unsigned char);
void ds1307_fecha(unsigned char, unsigned char,unsigned char,unsigned char);
unsigned char lee_ds1307 (unsigned char);
unsigned char bin2bcd(unsigned char);


/****************************************************************************
FUNCIÓN DE CONFIGURACIÓN:
Permite cargar los los valores para los registros que configuran el RTC con
valores introducidos mediante el teclado
****************************************************************************/
void conf_rtc()
{
   int p=0,h=0;
   char j=0,t;
   p=1;

   while(p==1)
   {
      lcd_enviar(0,0x01);
      lcd_gotoxy(1,1);   lcd_dato("* CONFIG. RTC *");
      lcd_gotoxy(3,1);    lcd_dato("1)CONFIGURAR");   
      lcd_gotoxy(4,1);    lcd_dato("2)ESC");
      delay(500000);
      while((j=tecla())==0);
      h=tecla_int(j);

      if(h==1)
      {
         delay(500000);

         t=0;
         while(t!='.')
         {
            lcd_enviar(0,0x01);   
            lcd_gotoxy(1,1);   lcd_dato("seg=");
            seg=bin2bcd(calcu_int(2,1,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               seg=0;            
               lcd_gotoxy(1,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(1,9);   lcd_dato("min=");
            min=bin2bcd(calcu_int(2,1,13));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               min=0;            
               lcd_gotoxy(1,13);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(2,1);   lcd_dato("hra=");
            hora=bin2bcd(calcu_int(2,2,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               hora=0;            
               lcd_gotoxy(2,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(2,9);   lcd_dato("dia=");
            dia=bin2bcd(calcu_int(2,2,13));            
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               dia=0;            
               lcd_gotoxy(2,13);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(3,1);   lcd_dato("fec=");
            fecha=bin2bcd(calcu_int(2,3,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               fecha=0;            
               lcd_gotoxy(3,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(3,9);   lcd_dato("mes=");
            mes=bin2bcd(calcu_int(2,3,13));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               mes=0;            
               lcd_gotoxy(3,13);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(4,1);   lcd_dato("ano=");
            ano=bin2bcd(calcu_int(2,4,5));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               ano=0;            
               lcd_gotoxy(4,5);   lcd_dato("  ");

            }
         }

         t=0;
         while(t!='.')
         {
            lcd_gotoxy(4,9);   lcd_dato("c_b=");
            control=bin2bcd(calcu_int(2,4,13));
            while((t=tecla())!='.' && (t=tecla())!='#');
            if(t=='#')
            {
               control=0;            
               lcd_gotoxy(4,13);   lcd_dato("  ");

            }
         }

      }

      if(h==2)
      {
         p=0;
      }
   }
}
/****************************************************************************
FUNCIÓN DE BINARIO A BCD:
****************************************************************************/
unsigned char bin2bcd(unsigned char binary_value)
{
   int temp;
     int retval;
     temp = binary_value;
     retval = 0;
    while(1)
     {
       // Get the tens digit by doing multiple subtraction
       // of 10 from the binary value.
       if(temp >= 10)
       {
            temp -= 10;
            retval += 0x10;
       }
         else // Get the ones digit by adding the remainder.
         {
           retval += temp;
            break;
         }
     }
     return(retval);
}
/****************************************************************************
FUNCIÓN DE LECTURA DEL DS1307:
****************************************************************************/
unsigned char lee_ds1307(unsigned char registro)

   unsigned char data;
   unsigned int status;

   IdleI2C();
   start();
   status=write(0xD0);
   if(status==0)
   {
      status=write(registro);
      if(status==0)
      {      
         restart();
         status=write(0xD1);
         if(status==0)
         {
            data=read();
            stop();
         }
      }
   }
   else
   {
      stop();
   }
   return(data);
}
/****************************************************************************
FUNCIÓN DE ESCRITURA DEL DS1307:
****************************************************************************/
void ds1307_hora(unsigned char seg, unsigned char min,unsigned char hora,
             unsigned char dia)

   unsigned int status;

   IdleI2C();
   start();
   status=write(0xD0);
   if(status==0)
   {
      status=write(0x00);
      if(status==0)
      {
         status=write(seg);
         if(status==0)
         {
            status=write(min);
            if(status==0)
            {
               status=write(hora);
               if(status==0)
               {
                  status=write(dia);
                  if(status==0)
                  {   
                     stop();
                  }
               }
            }
         }
      }
   }
   else
   {
      stop();
   }
}

void ds1307_fecha(unsigned char fecha, unsigned char mes,unsigned char ano,
              unsigned char control)

   unsigned int status;

   IdleI2C();
   start();
   status=write(0xD0);
   if(status==0)
   {
      status=write(0x04);
      if(status==0)
      {
         status=write(fecha);
         if(status==0)
         {
            status=write(mes);
            if(status==0)
            {
               status=write(ano);
               if(status==0)
               {
                  status=write(control);
                  if(status==0)
                  {
                     stop();
                  }
               }
            }
         }
      }
   }
   else
   {
      stop();
   }
}


/*.........................................................................*/


/***************************************************************************
                       FUNCIONES PARA LA MEMORIA EEPROM
****************************************************************************/
//Declaración de funciones
void escribe_eeprom(unsigned int,unsigned char);
unsigned char lee_eeprom(unsigned int);

/****************************************************************************
FUNCIÓN DE ESCRITURA DE EEPROM:
****************************************************************************/
void escribe_eeprom(unsigned int address,unsigned char data)

   unsigned int status;

   IdleI2C();
   start();
   status=write(0xA0);
   if(status==0)
   {
      IdleI2C();
      status=write(address>>8);
      if(status==0)
      {
         status=write(address);
         if(status==0)
         {
            status=write(data);
            if(status==0)
            {
               stop();
            }
         }
      }
   }
   else
   {
      stop();
   }
}
/****************************************************************************
FUNCIÓN DE LECTURA DE EEPROM:
****************************************************************************/
unsigned char lee_eeprom(unsigned int address)
{
   unsigned char data;
   unsigned int status;

   start();
   status=write(0xA0);
   if(status==0)
   {
      status=write(address>>8);
      if(status==0)
      {      
         status=write(address);
         if(status==0)   
         {
            restart();
            status=write(0xA1);
            if(status==0)
            {
               data=read();
               stop();
            }
         }
      }
   }
   else
   {
      stop();
   }
   return(data);
}