Autor Tema: Tratando de comunicar 2 pic's por i2c (noob)  (Leído 2337 veces)

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

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Tratando de comunicar 2 pic's por i2c (noob)
« en: 23 de Enero de 2010, 12:41:07 »
Hola,estoy tratando de realizar mi 1º programa en i2c.. quiero comunicar 2 pic; enviar de un master un solo dato el 2 al otro pic cuando se oprima un pulsador,en principio no funcionaba.. asiq andube estudiando con el osciloscopio del proteus las señales SDA y SCL parece ser q el pic esclavo no reconoce la direccion y me manda un NACK, ese es un problema no logro q reconozca la direccion le puse a0 asi q lo resolvi parando la transmision y dando un nuevo estar luego envio el 2 y sin capacitor en las pull-up(q son de 4 k)no transmite nada con cap de 0.01 µF recibe algo el esclavo pero no el 2,supongo q sera un problema de capacidad entonces alguien sabe q capacidad aproximada hay q colocarle a las pull-up?,habra otro problema?
dejo los códigos y las simulaciones,Grax
Master:

Código: [Seleccionar]

//Programa para el maestro;manda el dato almacenado en un contador cada vez que se oprime el pulsador 'enviar'
//este se muestra en pantalla y se 'pasa' al display conectado al pic esclavo cada vez q se oprime 'enviar'.

#include <16f877a.h>
#fuses HS,PUT,NOPROTECT,BROWNOUT,NOLVP,NOWDT
#use delay(clock=20000000)
#include<flex_lcd.c>
#use standard_io(c)
#use i2c(MASTER, SDA=PIN_C4, SLOW, SCL=PIN_C3, NOFORCE_SW)

int contador=0;

main()
{
   lcd_init();

   set_tris_b(0b00000011);
//   output_float(PIN_C3);
//   output_float(PIN_C4);
   enable_interrupts(GLOBAL);
   enable_interrupts(int_ext);
   lcd_putc ("Enviando..");
   while(TRUE)
   {
      if(!input(PIN_B1))                   //Manda el dato en contador si se presiona 'enviar'.
      {
      i2c_start();     
      if(!i2c_write(0xa0))
      i2c_write(2);
      else   
      i2c_stop();                       //se envia el dato y si no se reconoce se aborta la transmision.
           
      }   
   }
}
   
#int_ext
RSI()
{
while(!input(PIN_B0));
lcd_gotoxy(1,1);
printf(lcd_putc,"%d",contador++);      //Se muestra en pantalla la cuenta alcanzada cada vez q se actualiza.
}



Esclavo:
Código: [Seleccionar]

#include <16f877a.h>
#fuses HS,PUT,BROWNOUT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=20000000)
#include <flex_lcd.c>
#use standard_io(c)
#use I2C(SLAVE, SDA=PIN_C4 ,SLOW, SCL=PIN_C3, ADDRESS=0xa0, NOFORCE_SW)

int dato;
   main()
   {
   lcd_init();
//   output_float(PIN_C3);
//   output_float(PIN_C4);
   lcd_putc("Esperando");
      while(1)
      {
         if(i2c_poll())
         {
         dato=i2c_read();
         lcd_gotoxy(1,1);
         printf(lcd_putc,"%d",dato);
         }
      }
   }   
     
 

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Tratando de comunicar 2 pic's por i2c (noob)
« Respuesta #1 en: 23 de Enero de 2010, 13:36:02 »
He puesto un cap de 100 pF y he sacado el primer comando (el de la direccion) fuera del bucle principal ya q antes la 1º transmicion mandaba y las otras eran todas -96 quedando asi:

Código: [Seleccionar]

//Programa para el maestro;manda el dato almacenado en un contador cada vez que se oprime el pulsador 'enviar'
//este se muestra en pantalla y se 'pasa' al display conectado al pic esclavo cada vez q se oprime 'enviar'.

#include <16f877a.h>
#fuses HS,PUT,NOPROTECT,BROWNOUT,NOLVP,NOWDT
#use delay(clock=20000000)
#include<flex_lcd.c>
#use standard_io(c)
#use i2c(MASTER, SDA=PIN_C4, SLOW, SCL=PIN_C3, NOFORCE_SW)

int contador=0;

main()
{
   lcd_init();

   set_tris_b(0b00000011);
//   output_float(PIN_C3);
//   output_float(PIN_C4);
   enable_interrupts(GLOBAL);
   enable_interrupts(int_ext);
   lcd_putc ("Enviando..");
   i2c_start();
   if(!i2c_write(0xa0))
   i2c_stop();
   while(TRUE)
   {
      if(!input(PIN_B1))                   //Manda el dato en contador si se presiona 'enviar'.
      {
      i2c_start();     
//      if(!i2c_write(0xa0))
      i2c_write(contador-1);
//      else   
      i2c_stop();                       //se envia el dato y si no se reconoce se aborta la transmision.
           
      }   
   }
}
   
#int_ext
RSI()
{
while(!input(PIN_B0));
lcd_gotoxy(1,1);
printf(lcd_putc,"\f%d",contador++);      //Se muestra en pantalla la cuenta alcanzada cada vez q se actualiza.
}


Código: [Seleccionar]

#include <flex_lcd.c>
#use standard_io(c)
#use I2C(SLAVE, SDA=PIN_C4 ,SLOW, SCL=PIN_C3, ADDRESS=0xa0, NOFORCE_SW)

int dato;
   main()
   {
   lcd_init();
//   output_float(PIN_C3);
//   output_float(PIN_C4);
   lcd_putc("Esperando");
      while(1)
      {
         if(i2c_poll())
         {
         dato=i2c_read();
         lcd_gotoxy(1,1);
         printf(lcd_putc,"\f%d",dato);
         }
      }
   }   
     
 

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Tratando de comunicar 2 pic's por i2c (noob)
« Respuesta #2 en: 31 de Enero de 2010, 20:57:20 »
Hola como va, ya logre comunicar 2 pic's ahora agregue un tercero..la comunicacion se da entre solo 2 pic's el otro esclavo no logro que me reconozca su direccion no se porque no da el ACK cosa q el otro si lo hace para el otro elegi 0xb0 y nada lei en la pag. 84 del data y dice de porque puede ser q no da el ACK este esclavo y dice:

There are certain conditions that will cause the MSSP
module not to give this ACK pulse. These are if either
(or both):
a) The buffer full bit BF (SSPSTAT<0>) was set
before the transfer was received.
b) The overflow bit SSPOV (SSPCON<6>) was set
before the transfer was received.
If the BF bit is set, the SSPSR register value is not
loaded into the SSPBUF, but bit SSPIF and SSPOV are
set. Table 9-2 shows what happens when a data transfer
byte is received, given the status of bits BF and
SSPOV. The shaded cells show the condition where
user software did not properly clear the overflow condition.
Flag bit BF is cleared by reading the SSPBUF register,
while bit SSPOV is cleared through software.

q por lo poco q entendi quiere decir q antes q se llene el buffer se han seteado el bit BF y el bit de overflow.. los limpie antes y nada sigue = alguna idea de lo q puede estar pasando?Grax.
Código: [Seleccionar]

#include <16f877a.h>
#fuses HS,PUT,NOPROTECT,BROWNOUT,NOLVP,NOWDT
#use delay(clock=20000000)
#include <flex_lcd.c>
#use standard_io(c)
#use i2c(MASTER, SDA=PIN_C4, SLOW, SCL=PIN_C3, NOFORCE_SW)

int contador=0;

main()
{
   lcd_init();

   set_tris_b(0b00000111);
   enable_interrupts(GLOBAL);
   enable_interrupts(int_ext);
   lcd_putc ("Enviando..");
   while(TRUE)
   {
      if(!input(PIN_B1))                   //Manda el dato en contador si se presiona 'enviar'.
      {
      while(!input(PIN_B1))
      {
      }
      i2c_start();
      if(i2c_write(0xa0))
         {
         i2c_stop();
         }
      else
         {
         i2c_write(contador-1);   
         i2c_stop();
         }
      }
      if(!input(PIN_B2))                   //Manda el dato en contador si se presiona 'enviar'.
      {
      #asm
      bcf 3,5
      bcf 91,6
      bcf 94,0
      #endasm
      while(!input(PIN_B2))
      {
      }
      i2c_start();
      if(i2c_write(0xb0))
         {
         i2c_stop();
         }
      else
         {
         i2c_write(contador-1);   
         i2c_stop();
         }
      }
   }
}   
#int_ext
RSI()
{
while(!input(PIN_B0))
{
}
lcd_gotoxy(1,1);
printf(lcd_putc,"\fDato a enviar:%d",contador++);      //Se muestra en pantalla la cuenta alcanzada cada vez q se actualiza.
}
Eslave1
Código: [Seleccionar]

#include <16f877a.h>
#fuses HS,PUT,BROWNOUT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=20000000)
#include <flex_lcd.c>
#use standard_io(c)
#use I2C(SLAVE, SDA=PIN_C4 ,SLOW, SCL=PIN_C3, ADDRESS=0xa0, NOFORCE_SW)

int dato;
   main()
   {
   lcd_init();
   lcd_putc("Esperando");
      while(1)
      {
         if(i2c_poll())
         {
         dato=i2c_read();
         lcd_gotoxy(1,1);
         printf(lcd_putc,"\fDato recibido:%d",dato);
         }
      }
   }   
     
 
Esclavo2
Código: [Seleccionar]

#include <16f877a.h>
#fuses HS,PUT,BROWNOUT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=20000000)
#include <flex_lcd.c>
#use standard_io(c)
#use I2C(SLAVE, SDA=PIN_C4 ,SLOW, SCL=PIN_C3, ADDRESS=0xb0, NOFORCE_SW)

int dato;
   main()
   {
   lcd_init();
   set_tris_c(0xff);
   lcd_putc("Esperando");
      while(1)
      {
      #asm
      bcf 3,5
      bcf 91,6
      bcf 94,0
      #endasm
         if(i2c_poll())
         {
         dato=i2c_read();
         lcd_gotoxy(1,1);
         printf(lcd_putc,"\fDato recibido:%d",dato);
         }
      }
   }   

Desconectado oteros2000

  • PIC10
  • *
  • Mensajes: 4
Re: Tratando de comunicar 2 pic's por i2c (noob)
« Respuesta #3 en: 02 de Febrero de 2010, 07:54:44 »
Hola,estoy tratando de realizar mi 1º programa en i2c.. quiero comunicar 2 pic; enviar de un master un solo dato el 2 al otro pic cuando se oprima un pulsador,en principio no funcionaba.. asiq andube estudiando con el osciloscopio del proteus las señales SDA y SCL parece ser q el pic esclavo no reconoce la direccion y me manda un NACK, ese es un problema no logro q reconozca la direccion le puse a0 asi q lo resolvi parando la transmision y dando un nuevo estar luego envio el 2 y sin capacitor en las pull-up(q son de 4 k)no transmite nada con cap de 0.01 µF recibe algo el esclavo pero no el 2,supongo q sera un problema de capacidad entonces alguien sabe q capacidad aproximada hay q colocarle a las pull-up?,habra otro problema?
dejo los códigos y las simulaciones,Grax
Master:

Código: [Seleccionar]


Perdona,

puedes explicarnos como solucionastes el problema??

Gracias.
//Programa para el maestro;manda el dato almacenado en un contador cada vez que se oprime el pulsador 'enviar'
//este se muestra en pantalla y se 'pasa' al display conectado al pic esclavo cada vez q se oprime 'enviar'.

#include <16f877a.h>
#fuses HS,PUT,NOPROTECT,BROWNOUT,NOLVP,NOWDT
#use delay(clock=20000000)
#include<flex_lcd.c>
#use standard_io(c)
#use i2c(MASTER, SDA=PIN_C4, SLOW, SCL=PIN_C3, NOFORCE_SW)

int contador=0;

main()
{
   lcd_init();

   set_tris_b(0b00000011);
//   output_float(PIN_C3);
//   output_float(PIN_C4);
   enable_interrupts(GLOBAL);
   enable_interrupts(int_ext);
   lcd_putc ("Enviando..");
   while(TRUE)
   {
      if(!input(PIN_B1))                   //Manda el dato en contador si se presiona 'enviar'.
      {
      i2c_start();     
      if(!i2c_write(0xa0))
      i2c_write(2);
      else   
      i2c_stop();                       //se envia el dato y si no se reconoce se aborta la transmision.
           
      }   
   }
}
   
#int_ext
RSI()
{
while(!input(PIN_B0));
lcd_gotoxy(1,1);
printf(lcd_putc,"%d",contador++);      //Se muestra en pantalla la cuenta alcanzada cada vez q se actualiza.
}



Esclavo:
Código: [Seleccionar]

#include <16f877a.h>
#fuses HS,PUT,BROWNOUT,NOLVP,NOWDT,NOPROTECT
#use delay(clock=20000000)
#include <flex_lcd.c>
#use standard_io(c)
#use I2C(SLAVE, SDA=PIN_C4 ,SLOW, SCL=PIN_C3, ADDRESS=0xa0, NOFORCE_SW)

int dato;
   main()
   {
   lcd_init();
//   output_float(PIN_C3);
//   output_float(PIN_C4);
   lcd_putc("Esperando");
      while(1)
      {
         if(i2c_poll())
         {
         dato=i2c_read();
         lcd_gotoxy(1,1);
         printf(lcd_putc,"%d",dato);
         }
      }
   }   
     
 

Desconectado Trev

  • PIC16
  • ***
  • Mensajes: 115
Re: Tratando de comunicar 2 pic's por i2c (noob)
« Respuesta #4 en: 03 de Febrero de 2010, 11:28:35 »
Hola,al de dos pic's te refieres?..

Hago esto:
Código: [Seleccionar]
i2c_start();
if(i2c_write(0xa0))                   // Es asi y no con ! me habia equivocado o sea q se interrumpe la transmicion si el slave no manda ACK
i2c_stop();
despues sigue bucle y mando datos

Eso soluciona el tema de los 2 pic's pero no basta con 2 esclavos y todavia no se porque..nos vemos


 

anything