Pic 18f4550 et erreur I2C
Répondre à la discussion
Affichage des résultats 1 à 6 sur 6

Pic 18f4550 et erreur I2C



  1. #1
    invite593714e3

    Post Pic 18f4550 et erreur I2C


    ------

    Bonjour à tous,

    je suis en train de réaliser une carte comportant un PIC 18f4550 relié à un accéléromètre LIS3LV02DL. J'ai écrit le code sous C18 la compilation se fait sans problème mais lors du debugage le logiciel MPLAB plante .
    Une fois arrivé à la ligne StartI2C() il reste dans la boucle infinie mais je n'arrive pas à comprendre pourquoi. Par contre il exécute le IdleI2C() sans problème.

    De plus le code est similaire à celui d'un collègue qui utilise un PIC18f2550 sauf que sur sa carte il n'y a aucun problème.

    Voici mon code:
    Code:
    //fichier de déclaration des registres internes du microcontrôleur
    #include <p18f4550.h>
    #include <i2c.h>
    
    // Configuration des données du PIC
    #pragma config FOSC = HS //Oscillateur externe 20Mhz
    #pragma config WDT = OFF // watchdog OFF
    #pragma config LVP = OFF
    #pragma config MCLRE = OFF
    
    void initialisation(void)
    {
        //désactiver le convertisseur analogique numerique
    	ADCON1=0x0F;
    	
    	//désactiver le module CCP
        CCP1CON=0;
        
        //Configuration de l'I2C
        SSPSTAT=0b10000000; 
        SSPCON1=0b00101000;
        SSPCON2=0x00;
        SSPADD=0x01100011;
        
        //direction des ports 0=Output, 1= Input 
        TRISBbits.TRISB0=1; //SDA
    	TRISBbits.TRISB1=1; //SCL
    	TRISAbits.TRISA0=0;//LED verte
    	TRISAbits.TRISA1=0;//LED rouge
    	TRISAbits.TRISA2=0;//LED orange
    	TRISAbits.TRISA3=0;//LED jaune
    	PORTAbits.RA0=0;
    	PORTAbits.RA1=0;
    	PORTAbits.RA2=0;
    	PORTAbits.RA3=0;
    	OpenI2C(MASTER,SLEW_OFF); //Ouverture de l'I2C en master mode
    
    } 
    
    /***************************************************************************************************/
    unsigned char ReadAccelerometre(unsigned char Registre)
    {
    unsigned char bRet = 0x00;
    
    IdleI2C(); //Attente du bus OK
    StartI2C(); //Envoi de message de début(envoie du ST)
    IdleI2C(); //Attente de la disponibilité du bus
    WriteI2C(0x3A); //Envoi de l'adresse de l'accéléromètre (0011101)+0(écrire)
    IdleI2C(); //Attente de la disponibilité du bus
    WriteI2C(Registre); //Envoi du registre a lire 
    IdleI2C();
    RestartI2C();//SR
    WriteI2C(0x3B);//Envoi de l'adresse de l'accéléromètre (0011101)+1(lire)
    
    	if (SSPCON2bits.ACKSTAT) //Si AckStat == 1, on n'a pas reçu d'acquittement
    	{
    		PORTBbits.RB4 = 1;
    		StopI2C(); //Envoi de la condition de stop
    		return bRet;
    	}
    
    bRet = ReadI2C(); //Lecture I2C
    NotAckI2C();//Pas d'acquittement car on lit qu'un seul caractère
    IdleI2C();
    
    StopI2C(); //Envoi du stop
    return bRet; //Retour de la valeur lue
    } 
    
    
    /***************************************************************************************************/
    unsigned char WriteAccelerometre(unsigned char Adresse , unsigned char Value) 
    {
       unsigned char bRet = 0x00;
       IdleI2C();	 //Attente du bus OK
       StartI2C();	 //Envoi de message de début 
       IdleI2C();	 //Attente de la disponibilité du bus
       WriteI2C(0x3A); //Envoi de l'adresse de l'accéléromètre
       IdleI2C();	//Attenre de la disponibilité du bus
       WriteI2C(Adresse);//Envoi de l'adresse du registre
       IdleI2C();
       WriteI2C(Value);	//On écrit la valeur
       IdleI2C();			//Attente de disponibilité du bus
      
       if (!SSPCON2bits.ACKSTAT ) //Si on reçoit un acquitement, on retourne 1
       {
          bRet = 0x01;
       }
       StopI2C();
       return bRet;
    }
    
    
    /***************************************************************************************************/
    void main ()
    {
    	
        initialisation();        //initialisation du PIC
    	PORTAbits.RA0=1;
        WriteAccelerometre(0xA0,0xC7);//On active l'accéléromètre en écrivant dans CTRL_REG1
        ReadAccelerometre(0x28);//ici 0+OUTX_L(0101000);   
        
    }
    Et voici ce qu'il y a dans la commande StartI2C()
    Code:
    #if defined (I2C_V1)
    #undef StartI2C
    void StartI2C( void )
    {
      SSPCON2bits.SEN = 1;            // initiate bus start condition
    }
    
    #endif
    Si jamais quelqun peut m'aider ça m'arrangerait, ça fait trois jour que je sèche..

    Merci d'avance.

    -----

  2. #2
    RISC

    Re : Pic 18f4550 et erreur I2C

    Salut,

    J'ai déjà vu un PB soft qui a déjà été traité des centaines fois sur les forums.... :

    Quand on fait de la bit manipulation de broches en SORTIE IL FAUT ABSOLUMENT UTILISER LATx et SURTOUT PAS PORTx
    Code:
    version fausse :
    	PORTAbits.RA0=0;
    	PORTAbits.RA1=0;
    	PORTAbits.RA2=0;
    	PORTAbits.RA3=0;
    
    version correcte :
    	LATAbits.LATA0=0;
    	LATAbits.LATA1=0;
    	LATAbits.LATA2=0;
    	LATAbits.LATA3=0;
    Pour TOUTES les broches en sortie TOUJOURS utiliser LATx au lieu de PORTx.
    Pour l'explication tu lis la doc ou tu cherches les forums

    a+

  3. #3
    invite593714e3

    Re : Pic 18f4550 et erreur I2C

    En faisant mes recherches j'avais vu ça, j'ai changé depuis mais rien n'y fait. L'I2C ne marche toujours pas MPLab plante toujours lorsqu'il arrive dans le StartI2C()...

    Quelqun a le même problème sur le site de Microchip mais il n'a pas de réponse..

    Si jamais je trouve la solution je transmettrais et si quequn a une idée je suis preneur.

    A++

  4. #4
    inviteac751535

    Re : Pic 18f4550 et erreur I2C

    salut,

    ton probleme provient peut etre du startI2C ()

    car normalement tu as une boucle de test while (sspcon2.sen0;

    de plus ton SSPADD est faux c'est 0b00110001 ou 0x31 pour 100khz a 20mhz

    a+

    au fait es tu sur de la config de l'oscillateur car moi j'ai un probleme sur la configuarion que je n'arrive pas a resoudre?

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

    Re : Pic 18f4550 et erreur I2C

    Salut,

    merci pour le conseil, mais le problème ne venait pas de là.

    J'ai enfin trouvé la solution, lors de la réalisation de la carte un bout de cuivre est venu se coller entre 3 broches de l'accéléromètre, du coup ça court-circuitait les résistances de pull-up.

    Pour le SSPADD j'ai changé depuis, tout marche nickel.
    Je reçois sur mon hyperterminal les accélérations sur les 3 axes ainsi
    que la valeur de l'angle associé.

    Je laisse mon code pour ceux qui en aurait besoin:

    Code:
    /********************************************************************************************************************************/
    /*****	Montage avec PIC18f4550 et accéléromètre MEM LIS3LV02DL de chez STMicroelectronique									*****/
    /***** Le programme permet d'acquérir les accélérations sur les 3 axes puis de calculer l'angle autour de l'axe Y			*****/
    /***** Les données sont transmises du PIC vers un MAX232 via les broches Tx/Rx (25 et 26 du 18f4550)						*****/									
    /***** Ce programme est conçu pour tourner avec le Quartz externe 20Mhz mais avec quelques modifications j'ai pu le faire    *****/
    /***** tourner avec un quartz 8Mhz en interne.
    /*****
    /********************************************************************************************************************************/
    
    #include <p18f4550.h>
    #include <usart.h>
    #include <stdio.h>
    #include <math.h>
    #include <i2c.h>
    
    #define pi 3.14159265
    
    #pragma config WDT = OFF 		 //Watchdog désactivé
    #pragma config MCLRE = OFF       //désactiver la pin de Reset
    #pragma config LVP = OFF  		 //Low Voltage Programming désactivé => RB5 I/O normale
    #pragma config FOSC = HS
    
    void initialisation(void);
    void init_RS232(void);
    unsigned char ReadAccelerometre(unsigned char Registre);
    unsigned char WriteAccelerometre(unsigned char Adresse , unsigned char Value);
    void tempo(unsigned int compte);
    
    int acc_X=0;
    int acc_Y=0;
    int acc_Z=0;
    float pitch=0;
    float pitch_degr=0;
    float racine=0;
    float equation=0;
    signed char acc_XH=0;
    signed char acc_YH=0;
    signed char acc_ZH=0;
    unsigned char acc_XL=0;
    unsigned char acc_YL=0;
    unsigned char acc_ZL=0;
    unsigned char bRet=0;
    float form_X=0;
    float form_Y=0;
    float form_Z=0;
    char accel_X[40]={0};
    char accel_Y[40]={0};
    char accel_Z[40]={0};
    char pitch_X[40]={0};
    
    /********************************************************************************************************************************************/	
    /*************************************	Programme I2C avec Quartz 20Mhz		   **************************************************************/	
    /********************************************************************************************************************************************/	
    
    void main ()
    {
        initialisation();        //initialisation du PIC
    	init_RS232();
    	putrsUSART("\n \r ****** Calcul de l'angle  ****** \n \r");	
    	while(1)
    	{
    
    /********************************************************************************************************************************************/
    /****	Accélération suivant X		*********************************************************************************************************/	
    
    		putrsUSART("Lecture I2C: \n \r");
    		WriteAccelerometre(0xA0,0xC7);
    
    	// Accélération suivant X
    		// Lecture de l'accélération sur X
    		acc_XH=ReadAccelerometre(0x29);
    		acc_XL=ReadAccelerometre(0x28);
    		// Calcul de l'accélération sur X
    		acc_X=(int)acc_XH*256+(int)acc_XL;
    		// Ecriture de l'accélération sur X
    		sprintf(accel_X,"%d",acc_X);
    		// Affichage de la valeur X sur hyperterminal
    		WriteUSART(accel_X[0]);
        	tempo(10000);
    		WriteUSART(accel_X[1]);
        	tempo(10000);
    		WriteUSART(accel_X[2]);
        	tempo(10000);
    		WriteUSART(accel_X[3]);
        	tempo(10000);
    		WriteUSART(accel_X[4]);
        	tempo(10000);
    		putrsUSART("          ");
    
    /********************************************************************************************************************************************/	
    /****	Accélération suivant Y		*********************************************************************************************************/
    
    		WriteAccelerometre(0xA0,0xC7);
    	// Accélération suivant Y
    		// Lecture de l'accélération sur Y
    		acc_YH=ReadAccelerometre(0x2B);
    		acc_YL=ReadAccelerometre(0x2A);
    		// Calcul de l'accélération sur Y
    		acc_Y=(int)acc_YH*256+(int)acc_YL;
    		// Ecriture de l'accélération sur X
    		sprintf(accel_Y,"%d",acc_Y);
    		// Affichage de la valeur Y sur hyperterminal
    		WriteUSART(accel_Y[0]);
        	tempo(10000);
    		WriteUSART(accel_Y[1]);
        	tempo(10000);
    		WriteUSART(accel_Y[2]);
        	tempo(10000);
    		WriteUSART(accel_Y[3]);
        	tempo(10000);
    		WriteUSART(accel_Y[4]);
        	tempo(10000);
    		putrsUSART("          ");
    
    /********************************************************************************************************************************************/
    /****	Accélération suivant Y		*********************************************************************************************************/	
    
    		WriteAccelerometre(0xA0,0xC7);
    	// Accélération suivant Z
    		// Lecture de l'accélération sur Z
    		acc_ZH=ReadAccelerometre(0x2D);
    		acc_ZL=ReadAccelerometre(0x2C);
    		// Calcul de l'accélération sur Z
    		acc_Z=(int)acc_ZH*256+(int)acc_ZL;
    		// Ecriture de l'accélération sur X
    		sprintf(accel_Z,"%d",acc_Z);
    		// Affichage de la valeur Z sur hyperterminal
    		WriteUSART(accel_Z[0]);
        	tempo(10000);
    		WriteUSART(accel_Z[1]);
        	tempo(10000);
    		WriteUSART(accel_Z[2]);
        	tempo(10000);
    		WriteUSART(accel_Z[3]);
        	tempo(10000);
    		WriteUSART(accel_Z[4]);
        	tempo(10000);
    		putrsUSART("          ");
    
    /********************************************************************************************************************************************/
    /****	Calcul de l'angle autour de l'axe X   ***********************************************************************************************/	
    
    		form_X=(float)acc_X/1024;				// Change l'accélération suivant X en G
    		form_Y=(float)acc_Y/1024;				// Change l'accélération suivant Y en G 
    		form_Z=(float)acc_Z/1024;				// Change l'accélération suivant Z en G
    		
    		racine=sqrt(pow(form_Y,2)+pow(form_Z,2));	// Calcul de l'angle en fonction des accélérations
    		equation=form_X/racine;
    		pitch=atan(equation);
    		pitch_degr=180*(pitch)/pi;
    		// Stockage de la valeur dans un tableau puis envoi vers le MAX232 
    		//	(Les tempos sont nécessaires afin d'avoir les caractères correctement affichés à l'écran)
    		sprintf(pitch_X,"%d.%02u", (int)pitch_degr , ((int) (((pitch_degr)-(int)pitch_degr) * 100)) ); // Solution afin d'avoir l'affichage avec virgule
    		WriteUSART(pitch_X[0]);
        	tempo(10000);
    		WriteUSART(pitch_X[1]);
        	tempo(10000);
    		WriteUSART(pitch_X[2]);
        	tempo(10000);
    		WriteUSART(pitch_X[3]);
        	tempo(10000);
    		WriteUSART(pitch_X[4]);
        	tempo(10000);
    		WriteUSART(pitch_X[5]);
        	tempo(10000);
    
    /********************************************************************************************************************************************/	
    	putrsUSART("\n \r");
        tempo(100000);
    	}
    }
    
    /********************************************************************************************************************************************/	
    /********************************************************************************************************************************************/	
    
    void initialisation(void)
    {
        //configuration horloge interne du pic à 32 MHz
        OSCCON = 0x70;        //pas de prédiviseur => 8MHz
        //OSCTUNE = 0x40;        //
        
        //désactiver le convertisseur analogique numerique
    	ADCON1=0x0F;
    	
    	//désactiver le module CCP
        CCP1CON=0;
        
        //Configuration de l'I2C
        SSPSTAT=0b10000000; 
        SSPCON1=0x28;
        SSPCON2=0x00;
        SSPADD=0x31;				// Liaison I2C en 100kHz
        
        //direction des ports 0=Output, 1= Input 
        TRISBbits.TRISB0=0; //SDA
    	TRISBbits.TRISB1=0; //SCL
    	TRISAbits.TRISA1 = 0;//LED verte
    	OpenI2C(MASTER,SLEW_OFF); //Ouverture de l'I2C en master mode
    } 
    
    /********************************************************************************************************************************************/	
    /********************************************************************************************************************************************/	
    /* Configuration de la liaison RS232 */
    void init_RS232(void)
    {
    OpenUSART ( USART_TX_INT_OFF &
                USART_RX_INT_OFF &
                USART_ASYNCH_MODE &
                USART_EIGHT_BIT &
                USART_CONT_RX &
                USART_BRGH_HIGH,
                129 );					// 51 si en osc interne
    }
    
    /********************************************************************************************************************************************/	
    /********************************************************************************************************************************************/	
    
    void tempo(unsigned int compte)
    {
    while(compte--);
    }
    
    /********************************************************************************************************************************************/	
    /********************************************************************************************************************************************/	
    /* Lecture du registre de l'accéléromètre */
    unsigned char ReadAccelerometre(unsigned char Registre)
    {
    unsigned char bRet = 0x00;
    
    IdleI2C(); //Attente du bus OK
    StartI2C(); //Envoi de message de début(envoie du ST)
    IdleI2C(); //Attente de la disponibilité du bus
    WriteI2C(0x3A); //Envoi de l'adresse de l'accéléromètre (0011101)+0(écrire)
    IdleI2C(); //Attente de la disponibilité du bus
    WriteI2C(Registre); //Envoi du registre a lire 
    IdleI2C();
    RestartI2C();//SR
    WriteI2C(0x3B);//Envoi de l'adresse de l'accéléromètre (0011101)+1(lire)
    	if (SSPCON2bits.ACKSTAT) //Si AckStat == 1, on n'a pas reçu d'acquittement
    	{
    		PORTBbits.RB4 = 1;
    		StopI2C(); //Envoi de la condition de stop
    		return bRet;
    	}
    bRet = ReadI2C(); //Lecture I2C
    NotAckI2C();//Pas d'acquittement car on lit qu'un seul caractère
    IdleI2C();
    StopI2C(); //Envoi du stop
    return bRet; //Retour de la valeur lue
    } 
    
    /********************************************************************************************************************************************/	
    /********************************************************************************************************************************************/	
    /* Activation de la lecture I2C sur l'accéléromètre */
    unsigned char WriteAccelerometre(unsigned char Adresse , unsigned char Value) 
    {
       bRet = 0x00;
       IdleI2C();	 //Attente du bus OK
       StartI2C();	 //Envoi de message de début
       IdleI2C();	 //Attente de la disponibilité du bus
       WriteI2C(0x3A); //Envoi de l'adresse de l'accéléromètre
       IdleI2C();	//Attenre de la disponibilité du bus
       WriteI2C(Adresse);//Envoi de l'adresse du registre
       IdleI2C();
       WriteI2C(Value);	//On écrit la valeur
       IdleI2C();			//Attente de disponibilité du bus
      
       if (!SSPCON2bits.ACKSTAT ) //Si on reçoit un acquitement, on retourne 1
       {
          bRet = 0x01;
       }
       StopI2C();
       return bRet;
    }
    J'utilise l'affichage sur l'hyperterminal pour suivre l'évolution du programme et avoir les valeurs mais il faut bien faire attention aux tempos entre l'affichage de chaque valeur sinon il n'y a rien à l'écran.

    Bonne continuation à tous...

  7. #6
    RISC

    Re : Pic 18f4550 et erreur I2C

    Salut,

    Un petit conseil....attention à l'usage des floats dans les PIC18...
    Tu vas mettre à plat le micro

    a+

Discussions similaires

  1. Transaction I2C entre deux pics 18f4550 (maître-esclave)
    Par invite29cca51d dans le forum Électronique
    Réponses: 9
    Dernier message: 12/04/2011, 15h17
  2. Pic 18f4550
    Par invitee0468afd dans le forum Électronique
    Réponses: 4
    Dernier message: 18/06/2009, 00h39
  3. 18f4550 i2c
    Par invite89f152fc dans le forum Électronique
    Réponses: 5
    Dernier message: 29/04/2008, 16h29
  4. Pic 18f4550
    Par inviteb6ec96f1 dans le forum Électronique
    Réponses: 0
    Dernier message: 07/04/2008, 21h48
  5. Pic 18f4550
    Par Gérard dans le forum Électronique
    Réponses: 8
    Dernier message: 07/06/2006, 00h42
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...