I2C - Primeros pasos

Hola a todos,

Quería saber si alguien podia hecharme una mano comentandome cómo funcionan las funciones i2c de CCS C. La teoría ya la tengo aprendida.

  • Por ejemplo ¿cuándo salta exactamente la interrupción #INT_SSP?, en la guia solo pone “I2C or SPI activity”, pero no tengo claro si salta cuando llega un START, cuando coincide con la dirección del esclavo, cuando llega un STOP, o cada vez que se envía o llega un dato.

  • Cada pic tiene una dirección, pero si queremos escribir o leer del esclavo, el byte a enviar es diferente a la dirección del mismo. Desde el maestro qué tenemos que enviar, ¿los 7 bits de dirección del esclavo más el bit de lectura/escritura de menos peso, que el modulo MSSP del esclavo sabrá interpretar la dirección y generar una interrupción?
    Es decir, si el esclavo B tiene la dirección de 7bits ‘0000010’ en #use i2c pondré address=0x02. Para Leer de B tengo que mandar i2c_write(0x04); que es la dirección de 7bits más el de lectura ‘00000100’.
    Si quiero escribir mando i2c_write(0x05); que es la dirección de 7bits más el de lectura ‘00000101’.
    ¿Correcto?

Gracias de antemano,
Spike

Hola Spike!,

La explicación algo más completa está en la ayuda de la función i2c_isr_state (asumo que trabajas en I2C).


Cada vez que salta la interrupción debes llamarla, y comprobar el resultado:

[ul]
[li] 0 - Address match received with R/W bit clear[/li][li] 1-0x7F - Master has written data; i2c_read() will immediately return the data[/li][li] 0x80 - Address match received with R/W bit set; respond with i2c_write()[/li][li] 0x81-0xFF - Transmission completed and acknowledged; respond with i2c_write()[/li][/ul]
Es decir, el puerto SSP (si no recuerdo mal), discrimina la dirección, y salta la interrupción:

Si era una lectura, primero recibirás un 0x80, luego un 0x81, 0x82, 0x83… así hasta que el master termine de leer. Te recomiendo mirar este post de dani (está en inglés) I2C Protocol - Clock Stretching Daniel Álvarez’s Blog -> Si tardas en responder hay que activarlo para que el master espere a que esté tu resultado listo. Deberás responder con i2c_write cada vez.

Si era una escritura, primero recibirás un 0x00, luego un 0x01, y así sucesivamente. Podrás leer lo que te mandó el master con i2c_read().

El ejemplo de la gente de CCS es algo así,



  #INT_SSP
    void i2c_isr() {
       state = i2c_isr_state();
       if(state >= 0x80)
          i2c_write(send_buffer[state - 0x80]);
       else if(state > 0)
          rcv_buffer[state - 1] = i2c_read();
 }
  

El mio (del PWM y los servos de la araña http://www.foroselectronica.es/f57/control-servos-robot-hexapodo-woody-679.html#post2025) es algo distinto, utilizo el protocolo de las memorias I2C de 256 bytes:


BYTE address, buffer[0x20];

#INT_SSP
void ssp_interupt ()
{
   BYTE incoming, state;

    state = i2c_isr_state();

    if(state < 0x80)                            //Master is sending data
    {
        incoming = i2c_read();
        if(state == 1)                            //First received byte is address
            address = incoming;
        if(state>= 2)                            //Second received byte is data
            buffer[address++] = incoming;
    }
    if(state >= 0x80)                            //Master is requesting data
    {
        i2c_write(buffer[address++]);
    }

   address = address & 0xF;

No se si habré sido muy claro, si te queda alguna duda aquí estamos :slight_smile:

Un saludo! :slight_smile:

Se me olvidó responder a esto. Creo que es completamente correcto lo que comentas, aunque no he probado a utilizar los pic como master i2c, o al menos no lo recuerdo :-).

Suerte!, ya nos contarás qué tal va :slight_smile:

[quote=ajo;6561]Se me olvidó responder a esto. Creo que es completamente correcto lo que comentas, aunque no he probado a utilizar los pic como master i2c, o al menos no lo recuerdo :-).

Suerte!, ya nos contarás qué tal va :-)[/quote]

De acuerdo, provaré las direcciones siguiendo esta filosofia.

Antes de eso quiero asegurarme de haber entendido el tema de las interrupciones.
Voy a poner un ejemplo para explicarme mejor. Tenemos un pic master y dos slaves. El master quiere escribir en uno de los dos slaves, y la secuencia de bits del bus i2c seria la siguiente:

  • Master manda START ( i2c_start() )
  • Master manda dirección esclavo + bit R/W ( i2c_write(data) )
  • En el esclavo salta la interrupción INT_SSP
  • Dentro de la Int. vemos que state es 0x00 y
    a partir de ahora empiezan a llegar los datos ( i2c_isr_state() )
  • Leo el dato para vaciar SSPBUF y envio ACK ( i2c_read() )
  • Salgo de la Interrupción
  • Master manda el primer byte de información ( i2c_write(data) )
  • En el esclavo salta la interrupción INT_SSP
  • Dentro de la Int. vemos que state es 0x01 ( i2c_isr_state() )
  • Leo el dato, vacio SSPBUF y envio ACK ( i2c_read() )
  • Salgo de la Interrupción
  • Master manda STOP ( i2c_stop() )
  • En el esclavo salta la interrupción INT_SSP
  • ¿cómo se que es un STOP?,¿mirando en cada Int
    el bit P de SSPSTAT?
  • ¿Si el master envia un START, state vuelve a
    valer 0x00? Esto supongo que si.

He visto algunos códigos y me salta la duda del flujo o stream. He visto en en
algunos códigos ponen #use i2c(…stream = i2cM) y luego en las funciones lo pasan por
parámetro i2c_start(i2cM). ¿Sabe alguien de qué se trata?

Saludos y gracias!!

He visto algunos códigos y me salta la duda del flujo o stream. He visto en en
algunos códigos ponen #use i2c(…stream = i2cM) y luego en las funciones lo pasan por parámetro i2c_start(i2cM). ¿Sabe alguien de qué se trata?

Buenas :slight_smile:

Esto se usa por si quieres usar dos streams de i2c al mismo tiempo: por ejemplo, que un mismo PIC haga de maestro y de esclavo a la vez, de ese modo tendrías el stream i2cM (master) e i2cS (slave). Y cuando llamas a las funciones i2c del CCS le indicas como parámetro en cuál de los dos streams (maestro / esclavo) quieres leer o escribir.

Saludos,
Dani

¡hola dani! :slight_smile:

Supongo que también servirá cuando quieras tener un segundo master “por software” en pines estandar sin función I2C.

O cuando tengas varios puertos SSP en tu pic.

Un saludo! :slight_smile:

Hola a todos!!

Supongo que la secuencia que he puesto en el mensaje anterior es correcta, aunque no me queda claro cómo detecta el stop el cliente. Lo probaré y ya os contaré que tal va.

Lo del stream de momento no lo utilizaré, pero ya me queda más claro cómo funciona.
Saludos!

[quote=Spike;6559]Hola a todos,

Quería saber si alguien podia hecharme una mano comentandome cómo funcionan las funciones i2c de CCS C. La teoría ya la tengo aprendida.

  • Por ejemplo ¿cuándo salta exactamente la interrupción #INT_SSP?, en la guia solo pone “I2C or SPI activity”, pero no tengo claro si salta cuando llega un START, cuando coincide con la dirección del esclavo, cuando llega un STOP, o cada vez que se envía o llega un dato.

  • Cada pic tiene una dirección, pero si queremos escribir o leer del esclavo, el byte a enviar es diferente a la dirección del mismo. Desde el maestro qué tenemos que enviar, ¿los 7 bits de dirección del esclavo más el bit de lectura/escritura de menos peso, que el modulo MSSP del esclavo sabrá interpretar la dirección y generar una interrupción?
    Es decir, si el esclavo B tiene la dirección de 7bits ‘0000010’ en #use i2c pondré address=0x02. Para Leer de B tengo que mandar i2c_write(0x04); que es la dirección de 7bits más el de lectura ‘00000100’.
    Si quiero escribir mando i2c_write(0x05); que es la dirección de 7bits más el de lectura ‘00000101’.
    ¿Correcto?

Gracias de antemano,
Spike[/quote]

Me podrías explicar la teoria que ya tienes aprendida?? x3, es que necesito saber como se usan las funciones de i2c y por que se les dan esos parámetros, por favor alguien ayudeee x3

Holaaa!!

Me podian explicar la teoría de i2c sobre las funciones?? :3, es que necesito saber como se utilizan, que parámetros se envian, etc.

Tmb quisiera saber si alguien tiene algún ejemplo sobre I2c :s

saluditooss x3

Como es que se programa el “Master” para obtener los datos del slave??
Ejemplo:
El maestro desea obtener datos del slave y vienen en forma de vector: como los leo desde le master?