Autor Tema: Problemas con I2C  (Leído 2056 veces)

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

Desconectado Vitaemons

  • PIC10
  • *
  • Mensajes: 2
Problemas con I2C
« en: 27 de Marzo de 2006, 12:53:00 »
Hola a todos,
Estamos realizando un proyecto para el cual se necesita comunicar 2 Pic mediante el bus I2C.

La cuestion es que, despues de haber realizado un programa maestro y otro esclavo, no conseguimos, ni siquiera que el esclavo lea la direccion.

Os agradeceriamos, si alguno teneis ejemplos de maestros y esclavos que comuniquen que nos los pusierais ya que por mas que hemos buscado en este foro y en internet, aun no hemos encontrado nada que funicone.

Por otro lado, os agregamos los dos programas realizados por si teneis tiempo y os apetece echarles un vistazo.

Muchas gracias y esperamos vuestra ayuda.

P.D. Estamos utilizando MPLAB, espero que no os cause mucho trastorno.



MAESTRO:

#include <p18F452.h>
#include <tcepi2.h>
#include <i2c.h>  
#include <delays.h>

#include "I2Cv1.h"

void sai(void);
void I2C_config(void);
//void I2C_Enviar(char);
void I2C_recibir(void);
void esperar_ACK(void);

//#define ESCLAVO_WRITE 0xA0
//#define ESCLAVO_READ  0xA1

char lin1[17]="Escrita         ";
char lin2[17]="Direccion       ";
char lin3[17]="colision  direcc";
char lin4[17]="colision  dato  ";
char lin5[17]="no ACK          ";
char lin6[17]="interrupcion    ";
char lin7[17]="Enviado         ";
char lin8[17]="Dato            ";
char lin9[17]="3m              ";
char lin10[17]="4m              ";
char lin11[17]="5m              ";
char lin12[17]="6m              ";
char lin13[17]="SOY             ";
char lin14[17]="MAESTRO         ";

unsigned char i;
unsigned char p_enviada[5]="Hola";
unsigned char p_recibida[5]="Nada";
unsigned char carac_recibido;

/**************************************/
/* Simulando el bootloader            */
/* (comentar antes de generar el hex) */
/**************************************/
//#pragma code AL_STARTUP = 0x0
//void _al_startup (void)
//{
//  _asm
//    goto 0x200
//  _endasm
//}
//#pragma code AL_VECTOR_INTERRUPCIONES_ALTAS = 0x8
//void _al_vector_interrupciones_altas (void)
//{
//  _asm
//    goto 0x208
//  _endasm
//}

/**************************************/
/* Aquí va el tema de la interrupción */
/**************************************/
#pragma code VECTOR_INTERRUPCIONES_ALTAS = 0x208
void salto_altas (void)
{
  _asm
    goto sai
  _endasm
}

#pragma code
#pragma interrupt sai
void sai (void)
{

   PutsLcd(lin1,lin6);
   p0(WAIT_PUSH);

}

void main(void)
{
   RCONbits.IPEN = 1;         /* Habilitamos prioridades */
   INTCONbits.GIEH = 1;      /* Habilitamos interrupciones altas */

   I2C_config();
   p0(WAIT_PUSH);
   PutsLcd(lin13,lin14);


/******************************************************************************
                                 ESCRITURA

*******************************************************************************/
// Bucle para enviar la cadena
  for (i=0;i<5;i++)
  {
    StartI2C();
   //Esperamos a que detecte la condicion de Start.
   while(PIR1bits.SSPIF==0){};


   PIR1bits.SSPIF=0;
    //I2C_Enviar(ESCLAVO_WRITE); // Envia la direccion del esclavo
   IdleI2C(); // Espera que este libre
    WriteI2C(0x00);

   // Miramos si hay colision de escritura de la direccion
    if(SSPCON1bits.WCOL)
    {
   p0(WAIT_PUSH);        
   PutsLcd(lin1,lin3);
    }

   
    esperar_ACK();

    // Ponemos esto despues de que reciba el ACK. Si pone esto es
   // que el esclavo ha leido la direccion.

      p0(WAIT_PUSH);
   PutsLcd(lin1,lin2);


   PIR1bits.SSPIF=0;
   p0(WAIT_PUSH);
   PutsLcd(lin1,lin2);   
   
   //I2C_Enviar(p_enviada);
   IdleI2C();
   WriteI2C(p_enviada);

   p0(WAIT_PUSH);
   PutsLcd(lin1,lin2);
   
// Imprimimos mensaje si hay colision de escritura de dato  
   if(SSPCON1bits.WCOL)
    {
        PutsLcd(lin1,lin4);
       
    }
    esperar_ACK();
    PIR1bits.SSPIF=0;
   p0(WAIT_PUSH);
   PutsLcd(lin7,lin8);
           
    StopI2C();
  }
 
// Realizamos una espera entre lectura y escritura
   Delay10KTCYx(255);

/***********************************************************************************
                                  LECTURA
************************************************************************************/

// Inicializamos el contador
  i=0;
  while(i<5)
  {
    StartI2C();
   while(PIR1bits.SSPIF==0){};
   PIR1bits.SSPIF=0;
    //I2C_Enviar(ESCLAVO_READ); // Envia la direccion del esclavo, y le dice que quiere leer
   IdleI2C(); // Espera que este libre
    WriteI2C(0x01);
   // Miramos si hay colision de escritura de la direccion
    if(SSPCON1bits.WCOL)
    {   
   PutsLcd(lin1,lin3);

    }
    esperar_ACK();
   PIR1bits.SSPIF=0;
    I2C_recibir();
    //Si se ha recibido, se genera el ACK.
    if(carac_recibido)
    {
      AckI2C();
      p_recibida=carac_recibido;
      
    }
    else
    {
      NotAckI2C();
    }
   
    i++;
 }
   PutsLcd(lin1,p_recibida);
}

void I2C_config(void)
{
   // Inicializa el módulo del MSSP en modo maestro
    OpenI2C(MASTER, SLEW_OFF);
    // Valor de recarga del baudrate generator.Frecuencia del reloj
    SSPADD = 0x63;
    // ACKSTAT y ACKDT a 1 Inicialización delos ACK"s
    SSPCON2= 0x60;
    TXSTAbits.TXEN=1;
    INTCON=0xC0;
    TRISCbits.TRISC3=0; // SCL del maestro, y por tanto del módulo.
    TRISCbits.TRISC4=0; // Data del maestro. Salida de datos.  
   // Para ver si el ACK se produce en la direccion.
   SSPCON2bits.ACKSTAT=1;          
}

/*void I2C_Enviar(char dato)
{
 IdleI2C(); // Espera que este libre
 WriteI2C(dato);
}*/

void I2C_recibir(void)
{
  // Le dices que el maestro v a ser receptor
  SSPCON2bits.RCEN=1;
  IdleI2C();
   
  if (DataRdyI2C())
  {
   carac_recibido=getcI2C();  
  }
// return (carac_recibido);
}

void esperar_ACK(void)
{
// if (valor) AckI2C();
// else NotAckI2C();
// IdleI2C();
 while(SSPCON2bits.ACKSTAT)
       {
      PutsLcd(lin1,lin5);
       }
}







ESCLAVO:

#include <p18F452.h>
#include <tcepi2.h>
#include <i2c.h>  
#include <delays.h>
#include <string.h>
#include "esclavo_v1.h"

unsigned char i,j;
unsigned char p_enviada[5]="aHol";
unsigned char p_recibida[17]="nadaaaaaaaaa";
unsigned char carac_recibido;
//Prototipos de las funciones
void I2C_config(void);
void I2C_enviar(char);
unsigned char I2C_recibir(void);
void esperar_ACK(void);

char lin1[17]="SOY             ";
char lin2[17]="ESCLAVO         ";
char lin3[17]="colision  direcc";
char lin4[17]="colision  dato  ";
char lin5[17]="no ACK          ";
char lin6[17]="interrupcion    ";
char lin7[17]="paco1           ";
char lin8[17]="paco2           ";
char lin9[17]="paco3           ";
char lin10[17]="BUCLE          ";
char lin11[17]="INFINITO       ";
void main(void)
{
unsigned char Direccion=0x00;

// Configuracion del bus I2C

I2C_config();
   p0(WAIT_PUSH);
   PutsLcd(lin1,lin2);

/***********************************************************************************
                                  LECTURA
************************************************************************************/

// Inicializamos los contadores
  i=0;
  j=0;
   


while(1)
{
   while(PIR1bits.SSPIF==1)
   {
      p0(WAIT_PUSH);
      PutsLcd(lin10,lin11);

   };
   p0(WAIT_PUSH);
   PutsLcd(lin7,lin8);
   // Pongo esto para saber si detecta la dirección
   PIR1bits.SSPIF=1;
   // Esto nos lo podemos quitar
   IdleI2C();
   //Limpiamos el buffer  
   Direccion=SSPBUF;

   // Si lo que le ha llegado es un 0, es que va a recibir datos
    if (SSPSTATbits.R_W == 0 )
   {
      p0(WAIT_PUSH);
      PutsLcd(lin10,lin11);

       carac_recibido=I2C_recibir();
      /*PutsLcd(lin1,carac_recibido);
      p0(WAIT_PUSH);*/
       //Si se ha recibido, se genera el ACK.
       if(carac_recibido)
       {
         AckI2C();
         p_recibida=carac_recibido;
         p0(WAIT_PUSH);
         PutsLcd(lin1,lin2);
       }
       else
       {
         NotAckI2C();
       }
       
       i++;
      /*PutsLcd(lin1,carac_recibido);
      p0(WAIT_PUSH);*/
   }
    // Si va a escribir
    else
   {
   /* Mirar si puede haber problema con el clock Streching*/
   IdleI2C();
   // I2C_enviar(p_enviada[j]); // Envia el primer caracter
   SSPBUF=p_enviada[j];
   // Liberamos el reloj
   SSPCON1bits.CKP=1;
   // Miramos si hay colision de escritura del dato
    if(SSPCON1bits.WCOL)
    {
        PutsLcd(lin1,lin3);
       
    }
   j++;
    //esperar_ACK();        
  }


}
}
void I2C_config(void)
{
   // Inicializa el módulo del MSSP en modo esclavo
    //OpenI2C(SLAVE_7, SLEW_OFF);
   SSPCON1=0B00000110;   // seteo como SLAVE


    //
    SSPADD = 0x00;
    // ACKSTAT y ACKDT a 1 Inicialización delos ACK"s
    SSPCON2= 0x60;
    TXSTAbits.TXEN=1;
    INTCON=0xC0;
    // Configuramos los pines como entrada
    TRISCbits.TRISC3=1;
    TRISCbits.TRISC4=1;    
   SSPCON1bits.CKP = 1;     // Libera el clock
   SSPCON2bits.SEN = 0;
   PIE1bits.SSPIE = 1;    // Para habilitar interrupciones, esta en 0 por defecto.

         
}

void I2C_enviar(char dato)
{
 IdleI2C(); // Espera que este libre
 WriteI2C(dato);
}

unsigned char I2C_recibir(void)
{
unsigned char carac;
 IdleI2C();
// Mientras no este el dato disponible, no hace nada
 
if (DataRdyI2C())
   {
   carac=getcI2C();
   PutsLcd(lin1,lin2);
   p0(WAIT_PUSH);
   }

 return (carac);
}

void esperar_ACK(void)
{
// if (valor) AckI2C();
// else NotAckI2C();
 IdleI2C();
 if(SSPCON2bits.ACKSTAT)
       {
      PutsLcd(lin1,lin5);
       }
}


Desconectado Artifox

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 455
    • Quadbot
RE: Problemas con I2C
« Respuesta #1 en: 30 de Marzo de 2006, 22:05:00 »
Hola, pues me parece un poco pesadito tu codigo... yo recien estoy aprendiendo tambien en hacer comunicarse pic"s por i2c, logre hacer lo en basic, pero estoy pasandolo a C.

Te comento que en la misma carpeta donde se intala en CCS hay un ejemplo de un maestro-escalvo i2c que simulan el funcionamiento de una memoria i2c. Revisa bien la carpeta examples alli se encuantra(no me acuerdo bien el nombre)

Bueno, suerte... si encuentro algo que me funcione en esotos dias te lo mando...

Un abrazoSonrisa GiganteSonrisa GiganteSonrisa Gigante
Video Quadbot
Saludos desde mi querido Perú.
Si realmente queremos que el mundo cambie debemos empezar por nosotros mismos... ;)


 

anything