Autor Tema: Comunicacion I2C multi-slave  (Leído 4242 veces)

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

Desconectado JumppingJack

  • PIC10
  • *
  • Mensajes: 2
Comunicacion I2C multi-slave
« en: 05 de Julio de 2006, 17:47:31 »
Excuse me, friends. Although my English is very bad, I wrote in English because my Spanish is worse yet. But I can read in Spanish.  I want that a PIC 16f877 (master) reads bytes from two slaves 16f877.  I use Proteus to simulate it. When the master reads from only slave, my routine works perfectly. When I use the routine below, the master reads the first byte from the first slave called. Next, the master only read 0xFF.  Might anybody help me?



//Master Code
#include <16f877>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,SLOW,FORCE_HW)
void main(void){
   byte buffer1=0, buffer2=0, dado1,dado2;

   while(TRUE){

      i2c_start();
      i2c_write(0xa0);
      delay_ms(10);
      i2c_write(buffer1);
      delay_ms(10);
      i2c_start();
      i2c_write(0xa1);
      delay_ms(10);
      dado1=i2c_read(0);
      i2c_stop();
      printf("\n Escravo 1 buffer %i %u\r",buffer1,dado1);
      if(++buffer1==10) buffer1=0;
      delay_ms(2000);

      /*
      i2c_start();
      i2c_write(0xb0);
      delay_ms(10);
      i2c_write(buffer2);
      delay_ms(10);
      i2c_start();
      i2c_write(0xb1);
      delay_ms(10);
      dado2=i2c_read(0);
      i2c_stop();
      printf("\n Escravo 2 buffer %i %u\r",buffer2,dado2);
      if(++buffer2==10) buffer2=0;
      delay_ms(2000);
      */
   }
}

// Slave address 0xA0
#include <16f877>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#include <lcd>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0, slow)
typedef enum {NOTHING, CONTROL_READ,
             ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;
I2C_STATE fState;
BYTE address, buffer[0x10];

#INT_SSP
void ssp_interupt(){
   BYTE incoming;
      if (i2c_poll() == FALSE){
      if (fState == ADDRESS_READ){  //i2c_poll() returns false on the
        i2c_write (buffer[address]);//interupt receiving the second
        fState = NOTHING;           //command byte for random read operation
      }
   }
   else{
     incoming = i2c_read();
     if (fState == NOTHING){
         fState = CONTROL_READ;
     }
     else
         if (fState == CONTROL_READ) {
            address = incoming;
            fState = ADDRESS_READ;
         }
         else
            if (fState == ADDRESS_READ) {
               buffer[address] = incoming;
               fState = NOTHING;
            }
   }
}

void main ()
{
  int i=0;
  fState = NOTHING;
  address = 0x00;
  do{
      buffer = i;
      i+=1;
  }while (i<10);
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_SSP);
  while (TRUE) {

  }
}


//Slave Address 0x0B
#include <16f877>
#fuses XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
#use delay(clock=4000000)
#include <lcd>
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xb0, slow)
typedef enum {NOTHING, CONTROL_READ,
             ADDRESS_READ, READ_COMMAND_READ} I2C_STATE;
I2C_STATE fState;
BYTE address, buffer[0x10];

#INT_SSP
void ssp_interupt(){
   BYTE incoming;
   output_bit (pin_b0, true);
   if (i2c_poll() == FALSE){
      if (fState == ADDRESS_READ){  //i2c_poll() returns false on the
        i2c_write (buffer[address]);//interupt receiving the second
        fState = NOTHING;           //command byte for random read operation
      }
   }
   else{
     incoming = i2c_read();
     if (fState == NOTHING){
         fState = CONTROL_READ;
     }
     else
         if (fState == CONTROL_READ) {
            address = incoming;
            fState = ADDRESS_READ;
         }
         else
            if (fState == ADDRESS_READ) {
               buffer[address] = incoming;
               fState = NOTHING;
            }
   }
}

void main ()
{
  int i=0;
  fState = NOTHING;
  address = 0x00;
  do{
      buffer = 2*i;
      i+=1;
  }while (i<10);
  enable_interrupts(GLOBAL);
  enable_interrupts(INT_SSP);
  while (TRUE) {

  }
}
« Última modificación: 06 de Julio de 2006, 11:31:30 por JumppingJack »

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Comunicacion I2C multi-slave
« Respuesta #1 en: 06 de Julio de 2006, 09:23:49 »
Excuse me, friends. I write in English because my Spanish is wrost. But I can read in Spanish.  I want that a PIC 16f877 (master) reads bytes from two slaves 16f877.  I use Proteus to simulate. When does the master read from only a slave, does my routine work perfectly. When I use the routine below, the master read the first byte from the first slave called. Next, the master only read 0xFF.  Might anybody help me?

Mis experiencias con el proteus no son 100% satisfactorias.  Casualmente hice un firmware para un 18F452 que grababa una eeprom i2c. 

El software "en el mundo real" funciona de maravillas hace mucho tiempo. 

En proteus... el pic hacia cosas extrañas y no logré hacerlo funcionar.  Es muy probable que el problema sea que yo no lo sé configurar bien, pero tal vez esto también esté relacionado con tu problema.

Más allá de eso, tu dices:

"When does the master read from only a slave, does my routine work perfectly. "

Has probado 'repetidos' accesos al esclavo 0xA0 ? O solo 1 vez?  La diferencia es importante.

Puedes probar esto? Es decir, acceder muchas veces solo al 0xA0 ?


- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado JumppingJack

  • PIC10
  • *
  • Mensajes: 2
Re: Comunicacion I2C multi-slave
« Respuesta #2 en: 06 de Julio de 2006, 11:14:51 »
Yes, Maunix.
When  the master reads from only a slave (no matter wich one),  my routine repeatedly works fine. 
To block a specific slave, I  use /* and */ and test my code.
For example:
Slave 1 Buffer´s: [0xC7 0x23 0x56 0xA9]
Slave 2 Buffer´s: [0x45 0x32 0xAF 0xDE]
If I block the Slave 2, the master continually reads from Slave 1:
0xC7, 0x23, 0x56, 0xA9, 0xC7, 0x23, 0x56, 0xA9,0xC7...
If I block the Slave 1, the master continually reads from Slave 2:
0x45, 0x32, 0xAF, 0xDE,0x45, 0x32, 0xAF, 0xDE,0x45...
But if I block none of them, the master read:
0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF...
  Thanks.


Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Comunicacion I2C multi-slave
« Respuesta #3 en: 06 de Julio de 2006, 11:45:45 »
Como "bloqueas" a tus slave?

a) Comentas el código en el master?
b) quitas la conexión física en el simualdor?
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Desconectado JumppingJack

  • PIC10
  • *
  • Mensajes: 2
Re: Comunicacion I2C multi-slave
« Respuesta #4 en: 08 de Julio de 2006, 21:18:50 »
Si, Mauricio.
Comento el código.

Desconectado maunix

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4751
    • Mi Sitio Web Personal
Re: Comunicacion I2C multi-slave
« Respuesta #5 en: 10 de Julio de 2006, 08:22:31 »
Si, Mauricio.
Comento el código.

Puedes 'capturar errores' ?   He observado que en tu código asumes siempre que se conectarán bien y no habrá error alguno.

Errores pueden ser (por citar algunos)

1) Que no puedas tomar el bus
2) Que no recibas el Acknowledge (porque el esclavo no interpretó que el comando era para él)
3) Que haya una colisión en el lado del master
etc.

Si 'capturas' los posibles errores, tal vez descubras algo que sea importante a tener en cuenta y estés muy crítico con algunos tiempos.

Otra cosa que he observado es que no esperas a que se ponga IDLE el bus, simplemente esperas 2 segundos, pero tal vez solo debas comprobar el estado IDLE sin esa demora.

Saludos
- La soberbia de un Einstein es entendible.. la de un salame es intolerable (A.Dolina)
- En teoría no hay diferencia entre la teoría y la práctica. En la práctica... si la hay.
- Lee, Lee, Lee y luego pregunta.(maunix)
- Las que conducen y arrastran al mundo no son las máquinas, sino las ideas (V. Hugo)
- Todos los hombres se parecen por sus palabras; solamente las obras evidencian que no son iguales.(Moliere)
- Todo debería ser hecho tan simple como sea posible pero no mas simple que eso.(A.Einstein)

Deimos

  • Visitante
Re: Comunicacion I2C multi-slave
« Respuesta #6 en: 10 de Julio de 2006, 11:08:43 »
Dentro del MPLab hay dos rutinas, la i2c.h y la sw_i2c.h. La primera es para hacer un i2c normal, utilizando los registros internos del pic. La otra es para hacer un protocolo i2c con cualquier puerto digital del integrado. No te compliques y utiliza las librerias que ya estan hechas, que seguro que funcionan. La velocidad se la puedes cambiar, ya que dentro del fuente hay notas indicando que se puede modificar.

Atentamente

Deimos

http://www.astroelectronica.iespana.es/

Desconectado Artifox

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 455
    • Quadbot
Re: Comunicacion I2C multi-slave
« Respuesta #7 en: 14 de Julio de 2006, 17:11:28 »
Hola dandole una mirada al codigo me parecio ver un error en el codigo del PIC maestro, pues al analizarlo inicia la comunicacion con el primer esclavo, hace un delay de 10ms y escribe el dato en él sin terminar la comunicacion, empezando la comunicacion con el otro pic, me parece que ese es el error
//Master Code
......
   while(TRUE){
      i2c_start();
      i2c_write(0xa0);
      delay_ms(10);
      i2c_write(buffer1);
      delay_ms(10);
      i2c_start();
      i2c_write(0xa1);
      delay_ms(10);
      dado1=i2c_read(0);
      i2c_stop();
....

Pienso que puede quedar asi:
Código: [Seleccionar]
   while(TRUE){
      i2c_start();
      i2c_write(0xa0);
//      delay_ms(10);  // no veo que sea necesario esperar tanto tiempo para mandar otro dato
      i2c_write(buffer1);
      I2C_STOP();   // Aca termina la comunicacion con el 1er esclavo
      delay_ms(10);
      i2c_start();
      i2c_write(0xa1);
//      delay_ms(10);  // no veo que sea necesario esperar tanto tiempo para recibir un dato
      dado1=i2c_read(0);
      i2c_stop();

Espero les ayude. Bye  :-/
Video Quadbot
Saludos desde mi querido Perú.
Si realmente queremos que el mundo cambie debemos empezar por nosotros mismos... ;)

Desconectado boadacr

  • PIC10
  • *
  • Mensajes: 3
Re: Comunicacion I2C multi-slave
« Respuesta #8 en: 04 de Mayo de 2012, 11:05:09 »
Hola señores, se que han pasado 6 años desde este post pero, habría la posibilidad de poder tener contacto con alguien que sepa este problema que le paso al compañero JumpingJack, ya que me esta pasando a mi exactamente lo mismo y no se ya que variar en el código para que funcione. Agradecería muchísimo la posible ayuda que me podáis ofrecer y yo encantado de escuchar posibles ideas para arreglar el problema.

Gracias de antemano.

Saludos