Autor Tema: I2C esclavo fin de transmisión SOLUCIONADO  (Leído 5016 veces)

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

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
I2C esclavo fin de transmisión SOLUCIONADO
« en: 06 de Abril de 2010, 09:11:20 »
Hola compañeros:

He estado buscando en el foro pero no he encontrado nada de como el PIC a través de CCS poniendolo como esclavo sabe que ha recibido un i2c_stop(), es decir ha terminado la comunicación con el maestro.

Para ello la rutina de interrupción por i2c en el esclavo que uso es la siguiente, que es la típica.

Citar
BYTE address, bufferI2C[32];
#INT_SSP
void i2c_isr() {
   BYTE incoming, state;

   state = i2c_isr_state();
  
   if(state < 0x80)                     //Maestro está enviando datos
   {
       incoming = i2c_read();
       if(state == 0)                     //Primer byte recivido es la dirección o address
          address = incoming;
      if(state != 0)                     //Segundo byte recivido es data
      {
         bufferI2C[state-1] = incoming;
      }
   }

   if(state == 0x80) //Maestro esta requiriendo datos
   {
      i2c_write(0x05);
   }
}

Como se sabe...cuando el i2c_read(); o i2c_isr_state(); recibe un caracter especial o directamente viendo si los pines SCL y SDA pasan de low a high (primero el SCL y luego el SDA).

Vamos en general, quiero saber cuando el master ha acabado de enviar datos en la trama...

Un saludete y gracias.
« Última modificación: 07 de Abril de 2010, 07:08:03 por c4_esp_VR »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: I2C esclavo fin de transmisión
« Respuesta #1 en: 06 de Abril de 2010, 09:42:00 »
Según el DataSheet del 16F87X (lease 873/874/876/877) se genera una interrupción cuando hay activaidad en el bus, incluyendo la generación del Start y el Stop por parte de un dispositivo maestro.
El bit 4 del registro SSPSTAT es el flag del StopBit. Mientras que el bit 3 del SSPSTAT es el flag del StartBit.
Cuando el bit 4 está en uno indica que se detectó un Stop.
Entonces chequeando dicho bit prodrías saber cuando parar la transmisión. Me imagino que dentro de tu rutina de interrupción sería ese bit el primero a chequear, y así si está en 1, no transmitís datos.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: I2C esclavo fin de transmisión
« Respuesta #2 en: 06 de Abril de 2010, 11:00:31 »
Intentaré realizarlo como indicas AngelGris, pero me parece raro que CCS no tenga su propia rutina...pero por el momento como no tengo más opciones tiraré de datasheet ;D.

A ver si alguien se atreve con una solución mediante las rutinas propias de CCS  :D

Un saludete.

Desconectado stk500

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4919
Re: I2C esclavo fin de transmisión
« Respuesta #3 en: 06 de Abril de 2010, 12:00:17 »

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: I2C esclavo fin de transmisión
« Respuesta #4 en: 06 de Abril de 2010, 13:58:57 »
Hola compañeros:

Citar
Según el DataSheet del 16F87X (lease 873/874/876/877) se genera una interrupción cuando hay activaidad en el bus, incluyendo la generación del Start y el Stop por parte de un dispositivo maestro.
El bit 4 del registro SSPSTAT es el flag del StopBit. Mientras que el bit 3 del SSPSTAT es el flag del StartBit.
Cuando el bit 4 está en uno indica que se detectó un Stop.
Entonces chequeando dicho bit prodrías saber cuando parar la transmisión. Me imagino que dentro de tu rutina de interrupción sería ese bit el primero a chequear, y así si está en 1, no transmitís datos.

He intentado lo siguente y tampoco funciona, nunca imprime el 1 por pantalla, al menos en Proteus...

Código: [Seleccionar]
#byte SSPSTAT = 0xFC7
#bit BFBIT=SSPSTAT.0
#bit STOPBIT=SSPSTAT.4
#bit STARTBIT=SSPSTAT.3

BYTE address, bufferI2C[32], lastBuffer[32];
#INT_SSP
void i2c_isr() {
BYTE incoming, state;
if (STOPBIT)
{
printf("1");
}

state = i2c_isr_state();
   
if(state < 0x80)                     //Maestro está enviando datos
{
    incoming = i2c_read();
    if(state == 0)                     //Primer byte recivido es la dirección o address
    address = incoming;
if(state != 0)                     //Segundo byte recivido es data
{
bufferI2C[state-1] = incoming;
printf("%c",incoming);
}
}

if(state == 0x80) //Master esta requiriendo datos
{
i2c_write(0x05);
}

if(state > 0x80) //Master esta requiriendo datos
{
printf("ADIOS");
}
}


Citar
Pasaste por aqui http://www.todopic.com.ar/foros/index.php?topic=27517.msg226931#msg226931
Por otro lado compañero stk500, ya había visto este post, pero desgraciadamente no me soluciona como hacerlo...o al menos no lo he visto...ahora ya me he quedado sin ideas para continuar...please si alguna tiene algo más...yo lo intento...venga compañeros...bombardearme con ideas  :D

Un saludete.

Desconectado c4_esp_VR

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 735
    • www.muchotrasto.com
Re: I2C esclavo fin de transmisión
« Respuesta #5 en: 07 de Abril de 2010, 07:07:36 »
Hola de nuevo compañeros:

Después de muchas horas de simulaciones y prubas, otras tantas buscando por la red (lo cual no encontré nada de nada) y otras tantas chapandome el datasheet del micro y los registros...lo he conseguido  :-/ :-/ :-/

Código del maestro
Código: [Seleccionar]
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,FAST,FORCE_HW)
void main(void)
{
      delay_ms(1000);      //retardo, por si no se ha iniciado el esclavo

      while(TRUE)
      {
            i2c_start();
            i2c_write(0xA0);//direccion del esclavo con el que haremos la comunicacion, A6 A5 A4 A2 A1 A0 R/W  -> R/W = 0 modo escritura; 1 modo lectura
            i2c_write('H');
            i2c_write('O');
            i2c_write('L');
            i2c_write('A');
            i2c_stop();    //finalizacion de la comunicacion
            delay_ms(1000);
        }
}

Código del esclavo
Código: [Seleccionar]
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(SLAVE, SDA=DISPLAY_SDA, SCL=DISPLAY_SCL, ADDRESS=0xA0, FORCE_HW, FAST)//FAST, FORCE_HW
...
...
#byte SSPSTAT = 0xFC7
#bit BFBIT=SSPSTAT.0
#bit STARTBIT=SSPSTAT.3
#bit STOPBIT=SSPSTAT.4

#byte SSPCON1=0xFC6
...
...
BYTE address, bufferI2C[32];
#INT_SSP
void i2c_isr() {

BYTE state;

state = i2c_isr_state();
  
if(state < 0x80)                     //Maestro está enviando datos
{
//Para SSPCON1 = 0x3E;//0b00111110;//Si no se pone esta registro así no entra aquí para el bit de start y de stop
if (state == 0) //O bien es el bit de start o es el Address
{
if (!BFBIT) //Si no hay datos, el BFBIT=0 y por tanto es el START, el STARTBIT está a 1 en toda la trama menos cuando se eleva el STOPBIT
{
//Si ponemos antes el i2c_read(); vaciaremos el buffer y por BFBIT se pondrá a cero y no sabremos si es el address o el BITSTART
printf("0");
}
else
{
address = i2c_read();
printf("1");
}
}
else if (state > 0)                     //Más bytes recividos, es data
{
if(!STOPBIT)
{
bufferI2C[state-1] = i2c_read();
printf("%c",bufferI2C[state-1]);
}
else
{
//Entra aqui si es el bit de stop, fin de trama de datos
printf("2");
SSPSTAT=0x00; //Reseteamos el registro...no me digais...el compilador no lo hace solo con SSPCON1=0b00111110
}
}
}

if(state == 0x80) //Master esta requiriendo datos
{
// received a START + ( I2C_ADR | 1)
// i2c_write(data) must be used to write a byte
i2c_write(0x05);
printf("3");
}

if(state > 0x80) //Master esta requiriendo datos
{
// master has read the byte sent by the slave.
// i2c_write(data) must be used to write a byte
printf("4");
}
}
...
...
void main(void) {
SSPCON1 = 0x3E;//0b00111110;
  enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
   while (TRUE)
   {
        }
}

Al final de esto vemos como cada segundo se muestra en el terminal un 01HOLA2...al cabo de 2 segundo 01HOLA201HOLA2... de 3 segundos 01HOLA201HOLA201HOLA2...

Bueno muchachos espero que les sirva...creo que es un buen aporte para esta nuestra comunidad  :D :D :D...que bien se siente uno...que después de 2 dias luchando más de 15 horas y después se consigue lo que uno se propone...eso si con mucho sudor y esfuerzo y todo lo que aprende uno luchando contra la naturaleza del PIC  :mrgreen: :mrgreen: :mrgreen:

Lo dicho, espero que os sirva a todos.

un saludete.
« Última modificación: 07 de Abril de 2010, 07:14:17 por c4_esp_VR »

Desconectado stk500

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4919
Re: I2C esclavo fin de transmisión SOLUCIONADO
« Respuesta #6 en: 07 de Abril de 2010, 07:47:17 »
 :D :D pues me alegro, porque de verdad sigue siendo un tabu el I2c , nunca he visto un jemplo que te lleve a algo concreto ni en pic ni en Atmel que es lo que uso  :mrgreen:
 lo que me deseo que al menos gente como tu hagan un tutorial  con pruebas , tiene razon hay pocas informacion aqui en el foro sobre i2c.

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: I2C esclavo fin de transmisión SOLUCIONADO
« Respuesta #7 en: 07 de Abril de 2010, 10:53:21 »
Que bueno!!!
Yo todavía no hice nada con I2C. Sí hice rutinas por soft (para el compilador HiTech) para manejo de SPI y las probé en el Proteus.

De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything