Autor Tema: Quemado con I2C  (Leído 1752 veces)

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

Desconectado juanelete

  • PIC12
  • **
  • Mensajes: 74
Quemado con I2C
« en: 05 de Marzo de 2005, 07:04:00 »
Hola a todos:

Estoy intentando comunicar dos PIC16F876 mediante I2C.

He estado dando unas vueltas por el foro bucando informacion y documentandome.

He preferido no utilizar el ejemplo que simula una eeprom y carga unos datos en un buffer. Porque no lo entiendo muy bien.., y porque yo lo que quiero es comunicar dos PIC.

He hecho los siguientes programitas:

El master:

//////////////////////////////////////////////////////////////////////////////////////////////////////
//                            INT_SSP_MASTER                                                                   //
//                                                                                                                          //
// Comunicacion I2C entre dos PIC 16F876                                                         //
//                                                                                                                          //
// Este es el que va a actuar como master. Enviara secuencialmente una serie //
// de numeros que iran incrementandose de uno en uno.                                  //
//                                                                                                                         //
////////////////////////////////////////////////////////////////////////////////////////////////////


#INCLUDE <16F876.H>

#fuses HS,NOWDT,NOPROTECT,NOLVP

#ORG 0x1F00,0x1FFF {}   //Necesario para bootloader

#use delay(clock=20000000)

#use I2C(master,sda=PIN_C4,scl=PIN_C3,FORCE_HW)

#define use_portb_lcd TRUE //Necesario si usamos el portB para el LCD, y que sea compatible con LCD.C
#include <LCD.C>


#DEFINE PIC2 0x02    //Direccion dispositivo PIC 2 (esclavo)

//Prototipos
int1 dispositivo_preparado();



void main()
{

   int8 dato=0;

   delay_ms(500);

   lcd_init();
   lcd_putc("fPreparado...
");

   delay_ms(500);

   while(1)
   {
      lcd_putc("fEsperando...
");
      delay_ms(2000);

      while(!dispositivo_preparado());

      i2c_start();    // Inicio

      i2c_write(PIC2);// Direccion dispositivo

      i2c_write(dato);// envio dato

      i2c_write(dato+1);// envio dato

      i2c_stop();     // Stop

      printf(lcd_putc,"fDato enviado=%U",dato);

      delay_ms(3000);

      dato++;

    }

}


int1 dispositivo_preparado()
{
   int1 ack;
   i2c_start();            // If the write command is acknowledged,
   ack = i2c_write(PIC2);  // then the device is ready.
   i2c_stop();
   return !ack;
}


Y el esclavo:


///////////////////////////////////////////////////////////////////////////////////////////////////////
//                            INT_SSP_SLAVE                                                                      //
//                                                                                                                           //
// Comunicacion I2C entre dos PIC 16F876                                                           //
//                                                                                                                           //
// Este es el que va a actuar como ESCLAVO. Recibira secuencialmente una serie//
// de numeros que iran incrementandose de uno en uno y los mostrara en        //
// pantalla del PC                                                                                                   //
///////////////////////////////////////////////////////////////////////////////////////////////////////

#INCLUDE <16F876.H>

#fuses HS,NOWDT,NOPROTECT,NOLVP

#ORG 0x1F00,0x1FFF {}   //Necesario para bootloader

#use delay(clock=20000000)

#DEFINE PIC2 0x02  //Direccion dispositivo

#use I2C(slave,sda=PIN_C4,scl=PIN_C3,address=PIC2,FORCE_HW)

#use RS232(BAUD=9600,XMIT=PIN_C6,PARITY=N,BITS=8,STREAM=STR_PC)


//GLOBALES
int8 dato1=0, dato2=0;
int1 recibido=0;

#int_ssp
void int_sspi2c()
{
   while(!i2c_poll());
   dato1= i2c_read();

   while(!i2c_poll());
   dato2= i2c_read();

   recibido=1;
}



void main()
{
   delay_ms(50);

   fprintf(STR_PC,"ESPERANDO.....
");

   enable_interrupts(int_ssp);
   enable_interrupts(global);


   while(1)
   {
      if(recibido==1)
      {
         fprintf(STR_PC,"dato1=%u  dato2=%u
",dato1,dato2);

         recibido=0;
      }
   }
}


Si en ambos ejemplos quito las lineas que envian y leen el segundo dato, el programa funciona perfectamente, osea que enviando un solo dato cada vez el eslave lo recibe y lo muestra correctamente.

Pero si lo pruebo como esta ahora enviando dos datos seguidos, el slave no recibe
nada de nada.

Alguien sabria decirme que puñetas estoy haciendo mal...

Estoy mas quemado que "la pipa de un indio" .

Saludos a tod@s.

Desconectado J1M

  • Moderadores
  • PIC24H
  • *****
  • Mensajes: 1960
RE: Quemado con I2C
« Respuesta #1 en: 05 de Marzo de 2005, 07:25:00 »
prueba a cambiar la forma de envio, en vez de esto:
i2c_start(); // Inicio
i2c_write(PIC2);// Direccion dispositivo
i2c_write(dato);// envio dato
i2c_write(dato+1);// envio dato
i2c_stop(); // Stop


prueba con algo asi:

funcion enviodato(dato){
i2c_start(); // Inicio
i2c_write(PIC2);// Direccion dispositivo
i2c_write(dato);// envio dato
i2c_stop(); // Stop
}

y mandas dato a dato, con un for, el cual va cogiendo los datos del string.

for (i=0;i<tamaño_cadena;i++){
enviodato( dato [ i ] );
}

para calcular el tamaño del string tienes q incluir la cabezera string.h .. y creo q se usaba la funcion.. strleng

dato [ ] = {0 , 1, 3, 4, 5, 7, 8}


Salu2!

Desconectado Amarice_BA

  • PIC10
  • *
  • Mensajes: 25
RE: Quemado con I2C
« Respuesta #2 en: 07 de Marzo de 2005, 04:02:00 »
Yo he hecho otro programam con el I2C y mis dos grandes dudas son:

con los "fuses", que no sé cuáles debo utilizar, y

con el direccionamiento del dispositivo ¿?
por ejemplo, juanelete pone i2c_write(PIC2);// Direccion dispositivo
en mi caso es un convertidor digital analógico que está en la pata PIN_B1 ¿?
¿debo poner algo?


///  Descripcion del programa

///  1. Comunica con DAC, saca un valor (400) y enciende led correspondiente
///  2. Espera dos minutos
///  3. Comunica con DAC, saca un valor (340) y enciende led correspondiente
///  4. Espera a las entradas: conmutador de tres posiciones (arriba, inicial, abajo)
///  5. Arriba: Comunica con DAC, saca un valor superior y enciende led correspondiente
///     Abajo: Comunica con DAC, saca un valor inferior y enciende led correspondiente



/// Configuracion ///


#include <16F87.h>  // Libreria del pic

#fuses HS,WDT,NOPUT,NOWRT,NOPROTECT,NOLVP,NOBROWNOUT  // Fusibles

#use delay(clock=20000000)              // Velocidad reloj
#use I2C(MASTER,SDA=PIN_B1,SCL=PIN_B4)  // Comunicacion serie

#use fast_io(B)  // Da por buena la configuaracion del puerto B
#use fast_io(A)  // Da por buena la configuaracion del puerto A



/// Programa Principal ///


void main()

    {


    // Declaracion de Variables

    int nivel;
    int const tension[6]={0x1800,0x196A,0x19FD,0x1AAB,0x1B6E,0x1C4F};


    // Configura puertos

    set_tris_b(0x00);       // Puerto B configurado como salida
    output_b(0x00);         // Limpia B

    set_tris_a(0x02);       // Puerto A configurado RA6 y RA7 como entrada y el resto como salida
    output_a(0x00);         // Limpia A


    // Inicio

    nivel=0x00;
 
    output_low(PIN_B0);  // Comunica con DAC

    i2c_start();
    i2c_write(tension[nivel]>>8);  // Escribe la parte alta del dato (400)
    i2c_write(tension[nivel]);     // Escribe la parte baja del dato (400)
    i2c_stop();

    output_a(nivel);  // Enciende el led rojo de RA0

    nivel++;


    delay_ms(120000);  // Espera 2 minutos


    output_low(PIN_B0);  // Comunica con DAC

    i2c_start();
    i2c_write(tension[nivel]>>8);  // Escribe la parte alta del dato (340)
    i2c_write(tension[nivel]);     // Escribe la parte baja del dato (340)
    i2c_stop();

    output_a(nivel);  // Enciende el led amarillo de RB1


    while(input(PIN_A6) || input(PIN_A7));  // Espera si el conmutador no está en posición inicial


    while(TRUE)  // Bucle infinito

        {

        if((nivel>1) && (input(PIN_A6))) // Si no esta dando el máximo y el conmutador arriba

            {

            nivel++;

            output_low(PIN_B0);  // Comunica con DAC

            i2c_start();
            i2c_write(tension[nivel]>>8);  // Escribe la parte alta del dato
            i2c_write(tension[nivel]);     // Escribe la parte baja del dato
            i2c_stop();

            output_a(nivel);  // Enciende el led amarillo del nivel correspondiente

            while(input(PIN_A6));  // Espera a que el conmutador pase a posición inicial

            }



        if((nivel<5) && (input(PIN_A7))) // Si no esta dando el minimo y el conmutador abajo

            {

            nivel--;

            output_low(PIN_B0);  // Comunica con DAC

            i2c_start();
            i2c_write(tension[nivel]>>8);  // Escribe la parte alta del dato
            i2c_write(tension[nivel]);     // Escribe la parte baja del dato
            i2c_stop();

            output_a(nivel);  // Enciende el led amarillo del nivel correspondiente

            while(input(PIN_A7));  // Espera a que el conmutador pase a posición inicial

            }


        }


    }

Desconectado juanelete

  • PIC12
  • **
  • Mensajes: 74
RE: Quemado con I2C
« Respuesta #3 en: 07 de Marzo de 2005, 15:40:00 »
Hola

J1M:

Si..., pero no. No me parece la forma mas correcta el ir enviando los datos de uno
en uno abriendo y cerrando la comunicacion cada vez.


Amarice_BA:

Los fuses no tienen relacion directa con I2C.

En cuanto al direccionamiento de los dispositivos, tienes que mirar el datasheet de cada uno de ellos. Los hay que tiene una direccion fija e inmutable, otros una parte fija y la otra seleccionable y hay otros que puedes asignarle una direccion a voluntad.

Yo en mi ejemplo, al esclavo le asigno la direccion 0x02, fijate que al principio hay un define donde al indentificador PIC2 le asigno el valor  0x02.
#define PIC2 0x02

Saludos Sonrisa)

Nota: Ya he descubierto como hacer para que funcione bien. Como creo que habra otras personas interesadas, lo expongo en otro post, para que la busqueda sea mas facil.