Bonjour,
Je suis en train de mettre en place une liaison I2C entre 2 Pics et j'ai quelques problème avec l'esclave. J'utilise un PIC 18F4431. Ce dernier ne permet pas l'utilisation des fonction de la bibliothèque MCC18.
Mon problème est que l'esclave ne déclenche pas l'interruption de réception d'une trame I2C aussi rapidement que prévus.
Je joint une photo de l'oscillo. Sur la voie 1 on visualise la broche RD1 du pic qui change d'état à chaque passage dans la routine d'interruption I2C. Sur la voie 2 on visualise le SCL de l'I2C. Il n'y a que 2 trames car un NACK est émis sur le seconde trame. On voit que le passage dans la routine d'interruption à lieu pratiquement un trame trop tard (soit environ 800 cycles machine après la fin de la première trame). Le buffer est lu trop tard donc l'esclave envoi un NACK sur la ligne lorsqu'il reçoit la deuxième trame. Le second changement d'état est encore plus en retard.
Voici le code C de gestion de l'interruption :
- Initialisation des interruptions :
- Initialisation de l'I2C :Code:void Interrupt_Init(void) { RCONbits.IPEN = 1; // On autorise les niveaux de priorité INTCONbits.GIEH = 1; // On autorise toutes les interruptions INTCONbits.GIEL = 1; // """""""""""""""""""""""""""""""""""" // I2C PIE1bits.SSPIE = 1; // autorisation de l'interruption de l'i2c IPR1bits.SSPIP = 0; // Interruption de l'I2C en basse proirité }
- Routine d'interruption :Code:void I2C_Init(void) { TRIS_SDA = 1; // SDA en entrée TRIS_SCL = 1; // SCL en entrée SSPCON = 0x36; // I2C Slave mode, 7-bit address SSPADD = ADRESSE<<1; // Adresse de la carte moteur SSPCONbits.CKP = 1; // Libère la ligne d'horloge }
- Main :Code:void Low_Interrupt(void); #pragma code low_vector=0x18 void Interrupt_at_low_vector(void) { _asm goto Low_Interrupt _endasm } #pragma code #pragma interrupt Low_Interrupt void Low_Interrupt(void) { if (PIR1bits.SSPIF) { I2C_Interrupt(); } } void I2C_Interrupt(void) { PIR1bits.SSPIF = 0; PORTDbits.RD1 = ~PORTDbits.RD1; // Change l'état de RD1 if (SSPSTATbits.D_A == 1) // Donnée { if (SSPSTATbits.R_W == 0) // Maitre en écriture -> Esclave en lecture { I2C_Data = SSPBUF; I2C_Read(); // Méthode d'interprétation de l'octet reçu } else { I2C_Write(); // Méthode de chargement de l'octet à envoyer SSPBUF = I2C_Data; SSPCONbits.CKP = 1; // Libère la ligne d'horloge } I2C_Octets_Restants--; } else // Adresse { I2C_Data = SSPBUF; } }
Voila, Je suis bloqué parce que je pense avoir tout fait comme il faut et j'ai aucune idée d'où peut venir l'erreur.Code:void main(void) { ANSEL0 = 0x00; // Entrées analogiques désctivées Interrupt_Init(); I2C_Init(); PORTDbits.RD1 = 0; while (1) { } }
Si quelqu'un voit quelque chose que je ne vois pas, je serai très reconnaissant.
Merci d'avance pour votre aide.
A bientôt.
Julien
-----