I2C : bus collision
Répondre à la discussion
Affichage des résultats 1 à 16 sur 16

I2C : bus collision



  1. #1
    invite182d641b

    I2C : bus collision


    ------

    Bonjour,

    je travaille avec un PIC18f4580 en langage C.
    Mon but est la création d'un bus I2C. J'ai programmé mon micro comme il est indiqué dans la datasheet.
    Seulement dès que j'envoie la condition de start , j'ai le flag BCLIF qui se met à 1. Il s'agit du bus collision Interrupt Flag bit. Ma condition de start est donc avortée et je ne peux pas envoyer des données sur le bus. Avec mon oscilloscope je me suis aperçu que la ligne SDA était toujours à 0 alors qu'elle devrait être à 1 au départ.

    Quelqu'un a t'il un indice pour m'aider à résoudre mon problème.

    Merci

    -----

  2. #2
    invite182d641b

    Re : I2C : bus collision

    Voici mon programme d'initialisation du bus I2C :

    void config_I2C(void)
    {

    SSPSTAT=0b10000000;
    SSPCON1=0b00101000; //Autorisation du I2C module et en master mode
    SSPCON2=0b00000000;
    SSPADD=Clockvalue;
    }

    avec

    #define Fosc 4000000 //Quartz de 4MHz
    #define I2C_Clock 100000 //Horloge du I2C : 100kHz (10µs)
    #define Clockvalue (((Fosc/I2C_Clock)/4)-1)

    J'ai mis les pins RC3 et RC4 pour SDL et SDA en sortie.

    J'attends vos réponses. Merci

  3. #3
    Seb.26

    Re : I2C : bus collision

    Pas grand monde on dirait ... j'avais codé ça sur un 18F4550, si tu veux, je pourrais te filer des bouts de code ... ... c'est du maitre ...

    [Edit] Si tu prefère, j'ai aussi fait un periph I2C à base de 18F2525 ... donc en esclave

    Tu veux être maitre ou esclave ?
    ( j'avais pas vu ton 2nd post ... tu veux du maitre ... )
    Dernière modification par Seb.26 ; 25/10/2007 à 10h48.

  4. #4
    Seb.26

    Re : I2C : bus collision

    PS: ton "hard" est correct ?
    ( je crois me souvenir qu'il faut des pullup ou pulldown, je sais plus ... )

  5. A voir en vidéo sur Futura
  6. #5
    invite182d641b

    Re : I2C : bus collision

    Merci pour ta réponse.

    oui je veux coder en maître.

    Au niveau du hard,en sortie de mes ports, j'ai bien mis des pull up.

    Si tu as des morceaux de soft, ça m'interesse aussi. Peut être que j'ai mal configurer mon bus.

  7. #6
    invite182d641b

    Re : I2C : bus collision

    Si tu as qq morceau de code, je te donne mon mail :############
    ça me permettrait d'avancer dans mon projet surtout que c'est la seule chose qui me manque et qui me donne du fil à retordre.

    Merci pour ton aide.

    Grrrrr! pas d'email, les mp sont là pour çà
    Dernière modification par Jack ; 25/10/2007 à 14h14.

  8. #7
    Seb.26

    Re : I2C : bus collision

    Lol ... Ton email est passé à la trappe, pas grave : je posterais ici, si je te les donne, c'est que c'est pas top-secret ...

    ... Je vais fouiller mes archives ...

  9. #8
    Seb.26

    Re : I2C : bus collision

    Bon, j'ai trouvé ça ...

    Fichier Hard_I2C.c
    Code:
    #include "global.h"
    #include "Hard_I2C.h"
    
    // i2c_ack : Generate an ack bit
    void i2c_ack(void)
    {
      SSPCON2bits.ACKDT = 0;
      SSPCON2bits.ACKEN = 1;
    }
    
    // i2c_readchar : Read a single char on I2C, don't wait full
    unsigned char i2c_readchar_nowait(void)
    {
      SSPCON2bits.RCEN = 1;
      return ( SSPBUF );
    }
    
    // i2c_readchar : Read a single char on I2C
    // /!\ blocking on bugs
    unsigned char i2c_readchar(void)
    {
      SSPCON2bits.RCEN = 1;
      while( !I2C_DRDY() );
      return ( SSPBUF );
    }
    
    // i2c_idle : Idle the I2C (blocks I2C until it's free)
    void i2c_idle(void)
    {
      while((SSPCON2 & 0x1f) | (SSPSTATbits.R_W));
    }
    
    // i2c_drdy : Return 1 if data is ready to be read
    unsigned char i2c_drdy(void)
    {
      if(SSPSTATbits.BF)
         return (+1);
      else return (0);
    }
    
    // i2c_close : Close the I2C bus
    void i2c_close(void)
    {
      SSPCON1 &= 0xdf;
    }
    
    // i2c_stop : Stop the bus usage
    void i2c_stop(void)
    {
      SSPCON2bits.PEN = 1;
    }
    
    // i2c_writechar : Write a single char on the bus
    char i2c_writechar(unsigned char dat)
    {
    
      SSPBUF = dat;
      if( SSPCON1bits.WCOL ) { // if the I2C bus is busy
        return -1;
      } else {
        while( I2C_DRDY() );
        return 0;
      }
    }
    
    // i2c_writechar_nowait : Write a single char on the bus, don't wait free
    char i2c_writechar_nowait(unsigned char dat)
    {
      SSPBUF = dat;
      if( SSPCON1bits.WCOL )
         return -1;
      return 0;
    }
    
    // i2c_writestr : Write a string on the bus
    char i2c_writestr(unsigned char *ptr)
    {
      while( *ptr )
     {
        if( SSPCON1bits.SSPM3 )
        {
          if(i2c_writechar( *ptr ))
             return (-3);
          I2C_IDLE();
          if( SSPCON2bits.ACKSTAT )
             return (-2);
        }
        else
        {
          PIR1bits.SSPIF = 0;
          SSPBUF = *ptr;
          SSPCON1bits.CKP = 1;
          while( !PIR1bits.SSPIF );
          
          if((!SSPSTATbits.R_W) && ( !SSPSTATbits.BF ))
             return (-2);
        }
        
        ptr++;
      }
    
      return 0;
    }
    
    // i2c_writestr : Write a string on the bus with length
    char i2c_writestrWithLength(unsigned char ptr[], int length)
    {
    int i;
    
     for(i=0; i < length; i++ )
     {
        if( SSPCON1bits.SSPM3 )
        {
          if(i2c_writechar( ptr[i] ))
             return (-3);
          I2C_IDLE();
          if( SSPCON2bits.ACKSTAT )
             return (-2);
        }
        else
        {
          PIR1bits.SSPIF = 0;
    
          SSPBUF = ptr[i];
          SSPCON1bits.CKP = 1;
          while( !PIR1bits.SSPIF );
          
          if((!SSPSTATbits.R_W) && ( !SSPSTATbits.BF ))
             return (-2);
        }
      }
    
      return 0;
    }
    
    
    // i2c_start : Start the I2C bus
    void i2c_start(void)
    {
      SSPCON2bits.SEN = 1;
    }
    
    // i2c_restart : Restart the bus
    void i2c_restart(void)
    {
      SSPCON2bits.RSEN = 1;
    }
    
    // i2c_readstr : Read a string of length 'len' on the bus
    char i2c_readstr(unsigned char *ptr, unsigned char len)
    {
      unsigned char count=0;
      
      while( len-- ) {
        *ptr++ = i2c_readchar();
        
        while(SSPCON2bits.RCEN) {
          if(PIR2bits.BCLIF)return (-1);
          count++;
        
          if(len) {
            I2C_ACK();
            while(SSPCON2bits.ACKEN);
          }
        }
      }
      
      return count;
    }
    
    // i2c_open : Open the I2C bus with the current parameters. See #define in "DriverI2C.h" for definitions
    // mode : 
    //	0x0f	I2C_SLAVE10B_INT :	slave 10 bits, start stops bit interrupt enabled
    //	0x0e	I2C_SLAVE7B_INT :	slave 7 bits, start stops bit interrupt enabled
    //	0x0b	I2C_SLAVE_IDLE :	slave idle
    //	0x08	I2C_MASTER :		master, ck = Fosc/*(SSPADD+1)
    //	0x07	I2C_SLAVE10B :		slave 10 bits
    //	0x06	I2C_SLAVE7B :		slave 7 bits
    //
    // slew : slew mode on/off
    //	I2C_SLEW_OFF (0xc0) :			100kHz to 1MHz
    //	I2C_SLEW_ON	 (0x00) :			400kHz
    // addr_brd: to use in master mode, speed
    void i2c_open(unsigned char mode, unsigned char slew, unsigned char addr_brd)
    {
      SSPSTAT &= 0x3f;
      SSPCON1 = 0;
      SSPCON2 = 0;
      SSPCON1 |= mode;
      SSPSTAT |= slew;
      
    #if defined (pic18f2455) || defined (pic18f2550) || defined(pic18f4455) || defined (pic18f4550)
    
      TRISBbits.TRISB1 = 1;
      TRISBbits.TRISB0 = 1;
    
    #else	/* all other devices */
    
      TRISCbits.TRISC3 = 1;
      TRISCbits.TRISC2 = 1;
    
    #endif
    
      SSPADD = addr_brd;
    
      SSPCON1 |= 0x20;
    }
    
    // i2c_nack : generate non ack
    void i2c_nack(void)
    {
      SSPCON2bits.ACKDT = 0; // Enable Acknowledge
      SSPCON2bits.ACKEN = 1; // Initiate ack sequence on SDA & SDL pins and transmit ACKDT. Auto cleared by hardware.
    }
    Fichier Hard_I2C.h
    Code:
    #ifndef __Hard_I2C_H__
    #define __Hard_I2C_H__
    
    /* link the I/O library */
    //#pragma library io
    
    #define _I2CPARAM_SPEC	__data
    
    //Comment this definition to test with an another Microchip 18Fxxx (ex. : 18F458)
    //else, for using the 18F4550 : nothing to do !
    #define pic18f4550
    
    /* I2C modes of operation */
    #define I2C_SLAVE10B_INT	0x0f
    #define I2C_SLAVE7B_INT		0x0e
    #define I2C_SLAVE_IDLE		0x0b
    #define I2C_MASTER			0x08
    #define I2C_SLAVE10B		0x07
    #define I2C_SLAVE7B			0x06
    
    
    /* slew rate control */
    #define I2C_SLEW_OFF	0xc0
    #define I2C_SLEW_ON		0x00
    
    /* macros to generate hardware conditions on I2C module */
    
    /* generate stop condition */
    #define I2C_STOP()	SSPCON2bits.PEN=1
    
    /* generate start condition */
    #define I2C_START()	SSPCON2bits.SEN=1
    
    /* generate restart condition */
    #define I2C_RESTART()	SSPCON2bits.RSEN=1
    
    /* generate not acknoledge condition */
    #define I2C_NACK()	SSPCON2bits.ACKDT=1; SSPCON2bits.ACKEN=1
    
    /* generate acknoledge condition */
    #define I2C_ACK()	SSPCON2bits.ACKDT=0; SSPCON2bits.ACKEN=1
    
    /* wait until I2C is idle */
    #define I2C_IDLE()	while((SSPCON2 & 0x1f) | (SSPSTATbits.R_W));
    
    /* is data ready from I2C module ?? */
    #define I2C_DRDY()	(SSPSTATbits.BF)
    
    
    /* function equivalent to macros for generating hardware conditions */
    
    /* stop */
    void i2c_stop(void);
    
    /* start */
    void i2c_start(void);
    
    /* restart */
    void i2c_restart(void);
    
    /* not acknoledge */
    void i2c_nack(void);
    
    /* acknoledge */
    void i2c_ack(void);
    
    /* wait until I2C goes idle */
    void i2c_idle(void);
    
    /* is character ready in I2C buffer ?? */
    unsigned char i2c_drdy(void);
    
    // i2c_readchar : Read a single char on I2C, don't wait full
    unsigned char i2c_readchar_nowait(void);
    
    /* read a character from I2C module */
    unsigned char i2c_readchar(void);
    
    /* read a string from I2C module */
    //char i2c_readstr(_I2CPARAM_SPEC unsigned char *ptr, unsigned char len);
    char i2c_readstr(unsigned char *ptr, unsigned char len);
    
    // i2c_writechar_nowait : Write a single char on the bus, don't wait free
    char i2c_writechar_nowait(unsigned char dat);
    
    /* write a character to I2C module */
    char i2c_writechar(unsigned char dat);
    
    /* write a string on the bus with lenght */
    char i2c_writestrWithLength(unsigned char *ptr, int length);
    
    /* write a string to I2C module */
    char i2c_writestr(unsigned char *ptr);
    
    /* configure I2C port for operation */
    void i2c_open(unsigned char mode, unsigned char slew, unsigned char addr_brd);
    
    void i2c_close(void);
    
    #endif	/* __I2C_H__ */
    En esperant que cela t'aidera ...

  10. #9
    DavidDB

    Re : I2C : bus collision

    Salut,

    J'ai mis les pins RC3 et RC4 pour SDL et SDA en sortie.
    Même en mode maître, sachant que c'est le hardware qui gère les I/O, il faut impérativement éviter de configurer les I/O en sorties...
    C'est en contradiction totale avec l'interface I2C du PIC : c'est la raison pour laquel SDA est à zéro, car avec l'I/O en sortie le triger imposse un niveau zéro sur cette sortie et bloque l'I2C...

    Il faut laisser ces deux I/O en entrée comme pour le mode esclave.

    David.

  11. #10
    Seb.26

    Re : I2C : bus collision

    Et la lumière fut ...

    ( Tu pouvais pas passer par là plus tot DavidDB, ça m'aurais eviter de fouiller mes vieilles sauvegardes ... )

  12. #11
    invite182d641b

    Re : I2C : bus collision

    Je vais regarder cela de plus prêt, j'espère que cela m'aidera.
    Je te remercie en tout cas.

    je sais bien que ce n'est pas top secret mais je pensais que ce serait plus facile pour envoyer le code.

  13. #12
    invite182d641b

    Re : I2C : bus collision

    Hello,


    j'avais testé les pins RC3 et RC4 en entrée mais rien n'avait changé. J'ai même changé les timing mais ça ne bouge pas plus pour autant.
    J'ai toujours une collision sur le bus.

  14. #13
    DavidDB

    Re : I2C : bus collision

    j'avais testé les pins RC3 et RC4 en entrée mais rien n'avait changé
    C'est déjà une erreur en moins...
    Il faut que SDA et SCL soit en entrée.

    Retire ton esclave du bus et vérife les niveaux de SDA et SCL, ils doivent être à 1.

    David.

  15. #14
    invite182d641b

    Re : I2C : bus collision

    J'ai testé ce que tu m'as dit. J'ai retiré l'esclave de ma carte.
    Seulement SDL est bien à 1 mais SDA reste à 0. Donc dès que j'envoie le bit de start, le bus entre en collision.

  16. #15
    invite182d641b

    Re : I2C : bus collision

    Est ce qu'une erreur de timing entre le maître et l'esclave pourrait être la cause de mon problème ?

    J'utilise le composant PCA9554 comme esclave.

  17. #16
    invite182d641b

    Re : I2C : bus collision

    Je viens de résoudre mon problème de collision. C'était une erreur toute bête. En tout cas merci pour votre aide.

    Mary

Discussions similaires

  1. bus I2C
    Par inviteedcf41c6 dans le forum Électronique
    Réponses: 2
    Dernier message: 30/06/2008, 00h28
  2. Electronique : bus I2C
    Par invite6e39a71f dans le forum TPE / TIPE et autres travaux
    Réponses: 0
    Dernier message: 10/10/2007, 11h37
  3. Bus I2C
    Par Eleomir dans le forum Électronique
    Réponses: 15
    Dernier message: 15/04/2007, 11h58
  4. Bus I2c
    Par invite66afc259 dans le forum Électronique
    Réponses: 6
    Dernier message: 30/10/2005, 14h53
  5. création bus I2C?
    Par invite1c009f16 dans le forum Électronique
    Réponses: 1
    Dernier message: 05/10/2005, 16h51
Découvrez nos comparatifs produits sur l'informatique et les technologies.