EEPROM I²C & PIC16F877A : Problème de communication
Répondre à la discussion
Affichage des résultats 1 à 8 sur 8

EEPROM I²C & PIC16F877A : Problème de communication



  1. #1
    inoskyh

    Question EEPROM I²C & PIC16F877A : Problème de communication


    ------

    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 :
    • 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.
    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)

    Voici la portion de code traitant la transmission. Aucun soucis à la compilation du programme.
    Code:
    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
    Et les routines I²C
    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
    Ci-joint, le code source en assembleur ainsi qu'un schéma du montage.

    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 !

    -----
    Images attachées Images attachées
    Fichiers attachés Fichiers attachés

  2. #2
    invitef86a6203

    Re : EEPROM I²C & PIC16F877A : Problème de communication

    ou sont les résistances de pull up sur clock et data ?

  3. #3
    invite5637435c

    Re : EEPROM I²C & PIC16F877A : Problème de communication

    Bonjour,

    et l'alimentation du PIC avec ses découplages?
    Tout doit apparaitre sur un schéma.
    Il aurait été plus judicieux de laisser libre RB6 et RB7 pour l'ICSP, et d'utiliser les entrées du portB détectables par les interruptions pour les BP.
    A+

  4. #4
    inoskyh

    Re : EEPROM I²C & PIC16F877A : Problème de communication

    Bonjour à vous,
    Citation Envoyé par freepicbasic Voir le message
    ou sont les résistances de pull up sur clock et data ?
    En effet, j'ai complètement oublié ce point, pensant que les pull ups étaient gérées en interne par le PIC (remise à 1 automatique de la ligne) ! Et pourtant effectivement, avec du recul, ces pull ups sont essentielles !!

    Citation Envoyé par HULK28 Voir le message
    Bonjour,

    et l'alimentation du PIC avec ses découplages?
    Tout doit apparaitre sur un schéma.
    Il aurait été plus judicieux de laisser libre RB6 et RB7 pour l'ICSP, et d'utiliser les entrées du portB détectables par les interruptions pour les BP.
    A+
    Mon alimentation est tirée d'un transformateur 220/5V (bidouillage d'un chargeur de téléphone) et de fait sans doute suffisamment stabilisée ? Le découplage est-il réelement (toujours?) nécessaire ?

    A propos des portB détetectable par les interruptions, tu veux sans doute parler des pins RB0 et RB4/RB7 ? En fait, dans l'idéal, j'aurais souhaité n'utiliser qu'une seule pin d'interruption, mais je ne vois pas comment gérer les 4 boutons poussoirs (et donc traiter les 4 commandes utilisateurs) avec une seule interruption !

    Merci pour vos réponse !
    Nicolas

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

    Re : EEPROM I²C & PIC16F877A : Problème de communication

    Pourquoi tu n'utilises pas l'EEPROM interne de ton micro ?

  7. #6
    inoskyh

    Re : EEPROM I²C & PIC16F877A : Problème de communication

    Citation Envoyé par fignon Voir le message
    Pourquoi tu n'utilises pas l'EEPROM interne de ton micro ?
    Je pourrais tout à fait utiliser l'EEPROM interne de mon PIC, mais étant débutant (et disposant d'une EEPROM externe), je souhaitais surtout m'initier à la communication série, et en l'occurrence ici, via le protocole I²C, ouvrant la porte à de nombreuses autres applications !

  8. #7
    inoskyh

    Re : EEPROM I²C & PIC16F877A : Problème de communication

    De retour, malheureusement pas pour annoncer une bonne nouvelle :
    J'ai ajouté les deux résistance de rappel permettant de maintenir la ligne à l'état haut. Mais le résultat est pire encore : le pic se fige désormais tout le temps, que ce soit pour lire ou écrire dans mon EEPROM, sans doute bloqué dans les routines de communications.
    J'ai essayé deux type de résistances, 2K2 et 4K4, ainsi que de multiples source (j'ai fais varier mes routines de communication)
    Je tend à désespérer...

  9. #8
    invite5637435c

    Re : EEPROM I²C & PIC16F877A : Problème de communication

    Citation Envoyé par inoskyh Voir le message
    Mon alimentation est tirée d'un transformateur 220/5V (bidouillage d'un chargeur de téléphone) et de fait sans doute suffisamment stabilisée ? Le découplage est-il réelement (toujours?) nécessaire ?
    Le découplage est INDISPENSABLE même avec une alim régulée ou une pile ou ce que tu veux.
    La règle est de placer un condensateur de 10µF céramique ou tantale au plus près des pattes Vdd et Vss du PIC avec une capa de 100nF céramique en parallèle.
    Le PIC comme tout circuit Cmos consomme lors des commutations internes qui se font selon la vitesse du quartz, ce qui provoque des appels de courant forts pendant des temps très courts donc des pointes de courants que la source doit fournir en toutes circonstances.
    Or la liaison entre la source et le µC est inductive par les différents câblages et pistes ce qui va créer des dv/dt qui peuvent être importants et faire 'décrocher' les circuits internes du µC ou provoquer des reset ou autres fonctionnements intempestifs.
    Le rôle de ces condensateurs est de fournir cette énergie transitoire au µC.

    Le routage et le câblage de ta maquette sont également importants, d'autant que tu utilises l'I2C dont les signaux sont fortement influencés par les capa de ligne sur SDA et SCL.
    En principe un scope est nécessaire pour voir ce qui se passe vraiment sur les lignes.
    En abaissant la résistance de tirage au 5V on diminue le temps de monté du signal et vice-versa.
    Si ta liaison entre le µC et l'EEPROM est de quelques cm au maximum, placer une résistance de 4,7K sur chaque ligne (SDA et SCL) doit être suffisant.
    Il va de soi que l'EEPROM doit être également découplée avec un 100nF au plus près de ses pattes d'alim.

    Je n'ai pas regardé tes routines, mais avant de se lancer dans le soft il faut déjà bien assurer le hard sans quoi tu ne seras sûr de rien et tu vas t'arracher les cheveux.
    Une petite photo de ta maquette avec un schéma complété serait un plus pour valider au moins le hard et regarder plus loin.
    A+

Discussions similaires

  1. Problème CAN avec un PIC16F877A
    Par invite5d1bc976 dans le forum Électronique
    Réponses: 5
    Dernier message: 09/05/2009, 15h58
  2. SPI & EEPROM : read status en continu
    Par Philou67 dans le forum Électronique
    Réponses: 5
    Dernier message: 01/05/2009, 22h42
  3. Tracking & Communication Satellite : initiation !
    Par invite6ac70709 dans le forum Astronautique
    Réponses: 0
    Dernier message: 26/09/2007, 01h10
  4. Lire & écrire dans un EEPROM 24CL64
    Par invite5f450736 dans le forum Électronique
    Réponses: 2
    Dernier message: 12/05/2007, 20h46
  5. probléme eeprom 16F628
    Par etronics dans le forum Électronique
    Réponses: 4
    Dernier message: 12/11/2003, 19h59
Dans la rubrique Tech de Futura, découvrez nos comparatifs produits sur l'informatique et les technologies : imprimantes laser couleur, casques audio, chaises gamer...