Bonjour à vous qui me lisez,
Ayant lu, comme beaucoup de monde ici semble t-il, les cours de Bigonoff sur la programmation des PIC, je me suis fixé l'objectif de réaliser un simple chronomètre doté d'une fonction mémoire.
Pour ce faire, j'utilise le matériel suivant :
- PIC 16F877A
- Driver LCD 7 segments 4_1/2 MM5452 et son LCD VI502DP
- 4 boutons poussoir
- EEPROM BR24C16
Souhaitant implanter la fonction mémoire, j'ai codé en assembleur des routines de communication avec mon EEPROM branchée sur RC3/RC4. Lorsque le compteur est en route, une pression sur le 4eme bouton poussoir lance la mémorisation, tandis que lorsque le compteur est éteint, une pression sur ce même bouton charge le temps mémorisé et l'affiche.
Remarque : souhaitant enregistrer qu'un et un seul chrono, j'utilise uniquement les deux premiers octets de ma mémoire sur la page b'000'
Cependant, impossible de faire fonctionner ce module, et même après avoir retourné mon code dans tous les sens et tenté de nombreuses variantes.
Voici les symptômes :J'ai songé au fait que comme ma liaison avec l'EEPROM ne fonctionnait pas (pour je ne sais quelle(s) raison(s)), cette valeur était en faite la valeur W chargé à cet instant précis. (en effet, les octets reçu de l'EEPROM sont stockée dans W, donc si ces octets ne sont pas reçu, W peut valoir n'importe quoi)
- Lorsque j'ajoute dans mon code une fonction qui permet d'attendre un ACK (par exemple lors de l'écriture), le PIC reste figé, sans doute dans cette boucle d'attente de ce ACK.
- lorsque j'enlève cette vérification de mon code, l'ensemble du pic et de ses fonctions fonctionne de nouveau : lors d'un enregistrement, les données semblent envoyée normalement (mais aucun moyen de vérifier puisque pas de vérification des ACK et/ou NOACK de mon EEPROM). Mais lors d'une lecture, les valeurs sont incohérentes. Mon LCD affiche la plupart du temps la même valeur '-5-5' (signifiant que mes variables minute et seconde sont supérieures à 100) mais de temps à autre d'autres valeurs incohérentes.
Voici la portion de code traitant la transmission. Aucun soucis à la compilation du programme.
Et les routines I²CCode:FWAIT macro REGISTRE,BIT ; Permet de temporiser en attendant la validation d'un bit btfsc REGISTRE,BIT ; Le bit est nul ? goto $-1 ; NON : attendre bcf STATUS,RP0 ; OUI : Banque 00 (0) active endm ; Commandes de sauvegarde ; ----------------------- comMEM btfsc T2CON,TMR2ON ; Chrono ON ? goto comMEMSave ; OUI : enregistrer chrono goto comMEMLoad ; NON : charger chrono enregistrer comMEMSave btfsc MEMORY ; Mémoire pleine ? return ; OUI : retour ; NON : enregistrement bcf INTCON,GIE ; Suspension des interruptions call i2c_start ; Envoyer le start-condition movlw ADR_EEPROM ; Charger adresse EEPROM en écriture call i2c_write ; Envoyer adresse EEPROM movf fsr_eeprom ; Charger pointeur EEPROM call i2c_write ; Envoyer pointeur EEPROM movlw mCmptr ; Charger mCmptr call i2c_write ; Envoyer ; call i2c_waitACK ; Attendre validation EEPROM movlw sCmptr ; Charger sCmptr call i2c_write ; Envoyer ; call i2c_waitACK ; Attendre validation EEPROM call i2c_stop ; Fin du transfert bsf INTCON,GIE ; Autorisation des interruptions bsf MEMORY ; Positionner flag 'mémoire pleine' return ; Retour comMEMLoad bcf INTCON,GIE ; Suspension des interruptions call i2c_start ; Envoyer le start-condition movlw ADR_EEPROM ; Charger adresse EEPROM en écriture call i2c_write ; Envoyer adresse EEPROM movf fsr_eeprom ; Charger pointeur EEPROM call i2c_write ; Envoyer pointeur EEPROM call i2c_rstart ; Envoyer le repeated start-condition movlw ADR_EEPROM+1 ; Charger adresse EEPROM en lecture call i2c_write ; Envoyer adresse EEPROM ; call i2c_waitACK ; Attendre validation EEPROM call i2c_read ; Lecture de l'octet, placé dans (w) movwf mCmptr ; (w) => mCmptr ; call i2c_waitACK ; Attendre validation EEPROM call i2c_read ; Lecture de l'octet, placé dans (w) movwf sCmptr ; (w) => sCmptr call i2c_stop ; Fin du transfert bsf INTCON,GIE ; Autorisation des interruptions bcf MEMORY ; Reinitialiser flag 'mémoire pleine' bsf TIME1S ; Déclencher un affichage return ; Retour
Ci-joint, le code source en assembleur ainsi qu'un schéma du montage.Code:; Routines de communication I²C ; ----------------------------- ;--- i2c_start -------------------------------------------------------- ; Permet d'envoyer le start-condition ;---------------------------------------------------------------------- i2c_start BANK1 ; Banque 01 (1) active bsf SSPCON2,SEN ; Lancer le start-condition FWAIT SSPCON2,SEN ; Attendre fin start-condition return ; Retour ;--- i2c_rstart ------------------------------------------------------- ; Permet d'envoyer le repeated start-condition ;---------------------------------------------------------------------- i2c_rstart BANK1 ; Banque 01 (1) active bsf SSPCON2,RSEN ; Lancer le repeated start-condition FWAIT SSPCON2,RSEN ; Attendre fin repeated start-condition return ; Retour ;--- i2c_waitACK ------------------------------------------------------ ; Permet d'attendre jusqu'a reception d'un ACK ;---------------------------------------------------------------------- i2c_waitACK BANK1 ; Banque 01 (1) active FWAIT SSPCON2,ACKSTAT ; Attendre ACK bcf STATUS,RP0 ; Banque 00 (0) active return ; Retour ;--- i2c_stop --------------------------------------------------------- ; Permet d'envoyer le repeated stop-condition ;---------------------------------------------------------------------- i2c_stop BANK1 ; Banque 01 (1) active bsf SSPCON2,PEN ; Lancer le stop-condition FWAIT SSPCON2,PEN ; Attendre fin stop-condition return ; Retour ;--- i2c_ack ---------------------------------------------------------- ; Permet d'envoyer le ACK ;---------------------------------------------------------------------- i2c_ack BANK1 ; Banque 01 (1) active bcf SSPCON2,ACKDT ; Le bit envoyé vaut 0 bsf SSPCON2,ACKEN ; Lancer l'ACKnowledge (ACKDT = 0 = ACK) FWAIT SSPCON2,ACKEN ; Attendre fin ACK return ; Retour ;--- i2c_noack -------------------------------------------------------- ; Permet d'envoyer le NOACK ;---------------------------------------------------------------------- i2c_noack BANK1 ; Banque 01 (1) active bsf SSPCON2,ACKDT ; Le bit envoyé vaut 1 bsf SSPCON2,ACKEN ; Lancer l'acknowledge (ACKDT = 1 = NOACK) FWAIT SSPCON2,ACKEN ; Attendre fin NOACK return ; Retour ;--- i2c_write -------------------------------------------------------- ; Permet d'envoyer un octet ; Entrée : W (octet à envoyer) ;---------------------------------------------------------------------- i2c_write movwf SSPBUF ; Lancer l'émission de l'octet BANK1 ; Banque 01 (1) active FWAIT SSPSTAT,R_W ; Attendre fin d'émission return ; Retour ;--- i2c_read --------------------------------------------------------- ; Permet de lire un octet ; Sortie : W (octet reçu) ;---------------------------------------------------------------------- i2c_read BANK1 ; Banque 01 (1) active bsf SSPCON2,RCEN ; Lancer la lecture FWAIT SSPCON2,RCEN ; Attendre fin de réception movf SSPBUF,w ; Charger octet reçu dans (w) return ; Retour
J'ai essayé de décrire mon problème du mieux que je peux, en identifiant les symptômes. Si vous souhaitez d'autres précision, n'hésitez pas. Si par ailleurs vous avez une quelconque remarque quand au fonctionnement général du programme, n'hésitez surtout pas : étant novice, je ne demande qu'à apprendre !
-----