Bonjour!
Que faire lorsqu'une EEPROM I2C n'envoie pas l'ack après avoir envoyer son adresse. Connaissait vous les sources de conflits qui peuvent faire survenir ce problème?
PS juste avant j'avais su écrire et lire dedans .
Merci à tous
-----
Bonjour!
Que faire lorsqu'une EEPROM I2C n'envoie pas l'ack après avoir envoyer son adresse. Connaissait vous les sources de conflits qui peuvent faire survenir ce problème?
PS juste avant j'avais su écrire et lire dedans .
Merci à tous
Salut,
Essaye de provoquer un RESET du bus, et ensuite tu communiques à nouveau avec l'EEPROM...
Ce reset, n'est pas la solution, mais cela te permettra de savoir si ton code est buggé.
David.
OK merci david mais je ne comprends plus trop ce qu'il se passe. Lorsque que j'execute le programme il bloque apres avoir écrit et lu une premiere fois alors que lorsque j'execute le programme en mode mode pas à pas tout fonctionne correctement . J'ai pourtant bien mis des temporisations entre chaque evenement ( 100ms).
Quel est le type d'eeprom et quels sont les octets que tu envoies pour écrire un byte par exemple?
On peut voir ton schéma également pour des éventuels problèmes hard?
A+
tout d'abord merci Jack pour ta réponse, je travaille sur la carte PICDEM2 de chez microship donc niveau hard je pense que tout est ok il y a bien les résistance de pull up et tout ce qu'il faut. Je pense plutôt que cela doit provenir d'un soucis de pointeur interne à l'eeprom qui s'incrémente automatiquement. De plus je ne comprends pas que lorsque que je fait en pas à pas tout fonctionne alors qu'en fonctionnement normal apres un cycle d'écriture et de lecture l'eeprom ne semble plus accessible. veux tu voir mes fonctions d'écriture est de lecture pour plus de clarté elles sont lisibles et bien commentées... Merci encore pour on aide elle m'est précieuse après quelque mois de déboire et de désillusion.
N'étant pas familier de l'assembleur PIC, je ne t'aiderai efficacement que si tu écris en C.
D'après ce que tu me dis, je pense que ton problème se situe au niveau du test "registre d'émission vide". Il est probable que tu balances tous tes octets plus vite que le registre à décalage ne les envoie sur l'I2C.
A+
Très bien ca tombe plutot bien je code en C avec le compilateur HITEC PIC TOOLSUITE et l'eeprom est une 24LC256 de chez microship. Voici ma fonction de lecture, si quelque chose te semble suspect, fait mois signe. Merci encore pour ton aide.
Fonction d'écriture et fonction de lecture :
et la fonction de lecture :Code:void emis2_I2C(unsigned char composant,int adresse,unsigned char donnee) { unsigned char LSB=0; unsigned char MSB=0; LSB= adresse & 0xFF; // Pour init du poids faible de pointeur MSB= ( adresse & 0xFF00)>>8; // Pour init du poids fort de pointeur SEN=1; // Start condition while(SEN==1){;} // attente fin d'opération Start SSPBUF= ( composant | 0 );// charge adresse de l'EEPROM pour qu'elle se reconnaisse avec RW=0 écriture while(STAT_BF==1){;} // attente fin d'émission de l'adresse de l'EEPROM while(ACKSTAT==1) // attente du ACK de l'EEPROM { SEN=1; // Start condition while(SEN==1){;} // attente fin d'opération Start SSPBUF= ( composant | 0 );// charge adresse de l'EEPROM pour qu'elle se reconnaisse avec RW=0 écriture while(STAT_BF==1){;} // attente fin d'émission de l'adresse de l'EEPROM } SSPBUF=MSB; // initialisation poids fort du pointeur de l'EEPROM while(STAT_BF==1){;} // attente fin d'émission de l'adresse MSB while(ACKSTAT==1) { SSPBUF=MSB; while(STAT_BF==1){;} } // attente du ACK de l'EEPROM SSPBUF=LSB; // initialisation des poids faibles du pointeur de l'EEPROM while(STAT_RW==1){;} // attente fin d'émission de l'adresse LSB while(ACKSTAT==1) { SSPBUF=LSB; while(STAT_RW==1){;} } // attente du ACK de l'EEPROM SSPBUF=donnee; // on charge la donnée à enregistrer dans l'EEPROM while(STAT_RW==1){;} // on attends la fin d'émission de la donnée PEN=1; // envoi le stop condition while(PEN==1){;} // on attends la fin du stop condition, evoi terminé }
Merci encoreCode:unsigned char lect2_I2C(unsigned char composant,int adresse) { extern unsigned char a; unsigned char LSB=0; unsigned char MSB=0; LSB= adresse & 0xFF; // Pour init du poids faible de pointeur MSB= ( adresse & 0xFF00)>>8; // Pour init du poids fort de pointeur SEN=1; // Start condition while(SEN==1){;} // attente fin d'opération Start SSPBUF= (composant |0 ); // charge adresse de l'EEPROM pour qu'elle se reconnaisse avec RW=0 écriture while(STAT_BF==1){;} // attente fin d'émission de l'adresse de l'EEPROM while(ACKSTAT==1) { SSPBUF= (composant |0 ); // charge adresse de l'EEPROM pour qu'elle se reconnaisse avec RW=0 écriture while(STAT_BF==1){;} // attente fin d'émission de l'adresse de l'EEPROM } // attente du ACK de l'EEPROM SSPBUF=MSB; // initialisation poids fort du pointeur de l'EEPROM while(STAT_BF==1){;} // attente fin d'émission de l'adresse MSB while(ACKSTAT==1) { SSPBUF=MSB; while(STAT_BF==1){;} } // attente du ACK de l'EEPROM SSPBUF=LSB; // initialisation des poids faibles du pointeur de l'EEPROM while(STAT_RW==1){;} // attente fin d'émission de l'adresse LSB while(ACKSTAT==1) { SSPBUF=LSB; while(STAT_RW==1){;} } // attente du ACK de l'EEPROM RSEN=1; // envoi RE-start condition while(STAT_BF==1){;} // attente fin d'émission du repete startcondition SSPBUF= ( composant | 1 ); // charge adresse de l'EEPROM pour qu'elle se reconnaisse avec RW=1 lecture while(STAT_RW==1){;} while(ACKSTAT==1){;} // attente du ACK de l'EEPROM RCEN=1; // On valide la reception, clear automatiquement while(STAT_BF==1){;} // attente la fin de la reception, si BF=1, on a la donnnée dans SSPBUF ACKDT=1; // on envoi un NOACK pour dire, qu'on a bien recu l'octet ACKEN=1; // on valide l'emission du ACK en mode reception PEN=1; // envoi le stop condition while(PEN==1){;} // on attends la fin du stop condition, evoi terminé return(SSPBUF); // on renvoi la donnée lue }
Quelle est la référence du pic?
C'est un 16F877. Je travaille avec un quartz 4MHZ, voici la fonction d'initialisation j'ai un petit doute concernant la valeur du SSPAD car en effectuant le calcul je devrais inscrire 1,5 pour sa valeur mais ne pouvant pas mettre de flottant j'ai mis la valeur 1 . En vérifiant à l'osscilloscope je ne suis vraiment pas à 400KHz... Mais bon, si le programme s'execute bien une fois pourquoi pas deux sachant qu'après la fonction de lecture les registres sont dans le même état qu'au départ, et aucun drapeau mis à part le NOACK envoyé par l'eeprom juste après avoir envoyé son adresse pour qu'elle se reconnaisse.
Code:void init_I2C(void) { TRISC3=1; TRISC4=1; STAT_SMP=0; // SCL cadencé à 400kHz STAT_CKE=0; // mode I2C et non SMBUS SSPADD=1; // SSPAD=2 pour le cadencement de SCL avec Fclk=4MhZ SSPEN=1; // module en service valid SCA et SCL SSPCON= (SSPCON | 0b00001000); // I2C Mode Master }
Je viens de regarder la doc.
Le fait que ça fonctionne en pas à pas prouve que la config est bonne et qu'il s'agit d'une problème de timing.
Je pensais à une mauvaise gestion du bit BF, mais non, ton code semble correct. Tu a vérifié à l'oscillo si tes trames sont correctes?
A+
Oui. J'ai fait pour tester la fonction d'écriture un programme qui apele juste la fonction avec une tempo de 100ms le tout dans un while 1 . A l'osccilloscope tout est correct le programme ne plante pas et les trames sont bonnes, l'eeprom est toujours pretes à être réécrites. Par contre j'ai essayer la même chose MAIS avec la fonction de lecture et la le programme ne s'execute qu'une seule fois. Pourtant la ligne SDA se remet bien un position de repos ( 1 ), et le dernier bit détecté est bien le bit de Stop.
Où le programme bloque-t-il à la seconde écriture?
Juste après avoir envoyé l'adresse de l'eeprom , au lieu d'envoyer son aqcuitement comme elle le faisait pendant l'écriture et la lecture précédente elle envoi un NOACK comme pour dire qu'elle n'est pas prête à recevoir des donnée.
Salut,
La vitesse de ton BUS est bien trop loin des 400Khz, et il est fort possible que l'EEPROM plante.
Essaye déjà avec SSPAD à deux, tu n'auras plus qu'une erreur de 67khz à la place de l'erreur actuelle de 100Khz.
P.S. je ne connais pas l'erreur maximale en fréquence que supporte l'EEPROM, mais 25% d'erreur me paraît bien trop pour ce genre de composant.
Si cela ne fonctionne pas mieux, il faut changer de quartz pour ton PIC afin de se caler au plus prêt des 400Khz.
David.
Pourquoi voulez-vous viser le 400kHz qui est la fréquence de bus maxi de la mémoire?
Salut,
Avec sa config, il est à 500Khz et donc hors plage de fonctionnement de l'EEPROM, d'où un fonctionnement aléatoire du composant...
En repassant à 333Khz (SSPAD=2) il rentre à nouveau dans la plage d'utilisation de l'EEPROM.
Il faudra se caler sur 400Khz, si il s'agit de vrai composant I2C, par contre vu qu'ici c'est compatible I2C, la fréquence du BUS est libre à la condition de ne pas dépasser 400Khz, mais la config empêchera l'utilisation de composant I2C si on ne se cale pas sur le 400Khz.
Donc pour repsecter la norme I2C, il faut se caler sur 400Khz (ou 100Khz)...
David.
Très bien merci david pour ces renseignements suplémentaires. Je vasi voir tout ca demain mais il me semble que lorsque je faisait mes mesures à l'oscilloscope avec SSPAD à 1, j'avais une fréquence d'à peine 170KHz. De plus, tu as surement raison, si je ne suis pas calibrer dans la plage des 400KHz la valeur du bit STAT SMP vas devoir changer... Je test tout ca au plus vite et vous remercie encore pour vos suggerstions.
Florian