Bonjour,
Actuellement sur un projet avec afficheur LCD, je me sers d'un tableau de caractère que j'ai besoin d'entrer dans une EEPROM 24LC64 avec un pic 16F877 cadencé à 4MHz.
Pour cela je suis parti d'une routine de Bigonoff que j'ai modifié avec mon tableau de caractère.
J'envoie les données par page de 32 octets (ce qui correspond à 4 caractères)et je constate que la première page est bien écrite mais pas la fin des suivantes.
On peut le constater sur la photo jointe où on voit qu'après la première page (ABCD), les autres pages ne contiennent que 2 caractères corrects puis des FF ou 00 (suivant l'eeprom) sur les deux caractères suivants.
Comme on peut le voir sur ma routine (raccourcie, ici, juste à quelques caractères), j'ai essayé de rajouter des tempo de 2ms à chaque fois qu'une page est écrite avant de passer à la suivante. J'ai même essayé des tempo de 250ms.
Code:;***************************************************************************** ; ASSIGNATIONS SYSTEME * ;***************************************************************************** ; REGISTRE OPTION_REG (configuration) ; ----------------------------------- OPTIONVAL EQU B'10000000' ; RBPU b7 : 1= Résistance rappel +5V hors service ;***************************************************************************** ; ASSIGNATIONS PROGRAMME * ;***************************************************************************** ADRESSEEP EQU B'10100000' ; adresse eeprom = 1010 A2 A1 A0 R/W(0) ; l'adresse est déjà décalée (0xA0) ; REGISTRE ADCON1 (ANALOGIQUE/DIGITAL) ; ------------------------------------ ADCON1VAL EQU B'00000110' ; PORTA et PORTE en mode digital ; DIRECTION DES PORTS I/O ; ----------------------- DIRPORTA EQU B'11111110' ; Direction PORTA (1=entrée) ;***************************************************************************** ; DEFINE * ;***************************************************************************** #DEFINE LEDV PORTA,0 ; Led verte ;***************************************************************************** ; MACRO * ;***************************************************************************** WBUF macro octet,offset ; place l'octet "octet" dans buffer+offset movlw octet ; charger octet movwf buffer+offset ; placer dans le buffer endm ;***************************************************************************** ; VARIABLES BANQUE 0 * ;***************************************************************************** ; Zone de 80 bytes ; ---------------- CBLOCK 0x20 ; Début de la zone (0x20 à 0x6F) buffer : 0x20 ; 32 octets de buffer buflen : 1 ; longeur utilisée du buffer eepa : 2 ; valeur pour le pointeur d'adresse eeprom CmptTempo1 : 1 ; Compteur Haut boucles Tempos CmptTempo2 : 1 ; Compteur Bas boucles Tempos ENDC ; Fin de la zone ;***************************************************************************** ; DEMARRAGE SUR RESET * ;***************************************************************************** org 0x000 ; Adresse de départ après reset goto init ; Initialiser ; //////////////////////////////////////////////////////////////////////////// ; P R O G R A M M E ; //////////////////////////////////////////////////////////////////////////// ;***************************************************************************** ; INITIALISATIONS * ;***************************************************************************** init ; initialisation PORTS ; -------------------- BANKSEL PORTB ; passer banque 0 clrf PORTA clrf PORTB ; sorties PORTB à 0 bsf STATUS,RP0 ; passer en banque1 movlw ADCON1VAL ; PORTA en mode digital/analogique movwf ADCON1 ; écriture dans contrôle A/D movlw DIRPORTA ; Direction PORTA movwf TRISA ; écriture dans registre direction clrf TRISB ; PORTB en sortie, les autres en entrée movlw OPTIONVAL ; charger masque movwf OPTION_REG ; initialiser registre option ; initialiser I2C ; --------------- ; clrf SSPSTAT ; slew rate control en service, mode I²C ; movlw D'02' ; valeur de recharge du BRG (400 Kbauds) ; movwf SSPADD ; dans registre de recharge ; bcf STATUS,RP0 ; passer banque 0 ; movlw B'00101000' ; module MSSP en service en mode I²C master ; movwf SSPCON ; dans registre de contrôle clrf SSPSTAT clrf SSPCON2 bsf SSPSTAT,SMP ; 1 = active le filtre si la fréquence et comptise entre 100 KHz ou de 1 MHz bcf SSPSTAT,CKE ; 0 = compatible du protocole I²C movlw B'00001001' ; (SSPADD) = ((4 000 000 / (4*100 000)) - 1) = 9 = B'00001001' movwf SSPADD ; bcf STATUS,RP0 ; passer banque 0 movlw B'00101000' ; module MSSP en service en mode I²C master movwf SSPCON goto start ; programme principal ;***************************************************************************** ;***************************************************************************** ; ROUTINES EEPROM * ;***************************************************************************** ;***************************************************************************** ;***************************************************************************** ; ENVOYER LE BUFFER DANS L'EEPROM * ;***************************************************************************** ;----------------------------------------------------------------------------- ; Envoie le buffer dans l'eeprom ; buffer contient les données à envoyer ; buflen contient le nombre d'octets à envoyer (détruit après l'exécution) ; eepa contient l'adresse d'écriture ;----------------------------------------------------------------------------- eep_sendbuf call eep_adress ; initialiser pointeur adresse movlw buffer ; charger adresse buffer movwf FSR ; dans pointeur eep_sendb1 movf INDF,w ; charger un octet call i2c_write ; l'envoyer incf FSR,f ; incrémenter pointeur buffer decfsz buflen,f ; décrémenter nbre d'octets restants goto eep_sendb1 ; pas fini, suivant call i2c_stop ; fin du transfert return ; et retour ;***************************************************************************** ; INITIALISER LE POINTEUR D'ADRESSE ;***************************************************************************** ;----------------------------------------------------------------------------- ; envoie le start-condition, puis l'adresse de l'eeprom ; ensuite, teste le ACK ; Si NOACK, on envoie le repeated start-condition, puis de nouveau l'adresse ; si toujours NOACK, on recommence ; Si ACK, on envoie les 2 octets d'adresse contenus dans eepa ;----------------------------------------------------------------------------- eep_adress ; envoyer adresse circuit tant que pas ACK ; ---------------------------------------- call i2c_start ; envoyer start-condition eep_adress1 movlw ADRESSEEP ; charger adresse eeprom + écriture call i2c_write ; écrire adresse eeprom bsf STATUS,RP0 ; passer en banque1 btfss SSPCON2,ACKSTAT ; tester ACK reçu goto eep_adressok ; oui, poursuivre OK call i2c_rstart ; non, envoyer repeated start-condition goto eep_adress1 ; recommencer test ; placer 2 octets d'adresse dans pointeur ; --------------------------------------- eep_adressok bcf STATUS,RP0 ; repasser banque 0 movf eepa,w ; charger poids fort adresse call i2c_write ; écrire poids fort movf eepa+1,w ; charger poids faible adresse call i2c_write ; écrire poids faible return ; et retour ;***************************************************************************** ;***************************************************************************** ; ROUTINES I2C * ;***************************************************************************** ;***************************************************************************** ;----------------------------------------------------------------------------- ; On attend que chaque commande soit terminée avant de sortir de la ; sous-routine correspondante ;----------------------------------------------------------------------------- IWAIT macro REGISTRE,BIT ; attendre effacement du bit du registre clrwdt ; effacer watchdog btfsc REGISTRE,BIT ; bit effacé? goto $-2 ; non, attendre bcf STATUS,RP0 ; repasser en banque 0 endm ; fin de macro ;***************************************************************************** ; ENVOYER LE START-CONDITION * ;***************************************************************************** i2c_start bsf STATUS,RP0 ; passer en banque 1 bsf SSPCON2,SEN ; lancer le start-condition IWAIT SSPCON2,SEN ; attendre fin start-condition return ; et retour ;***************************************************************************** ; ENVOYER LE REPEATED START-CONDITION * ;***************************************************************************** i2c_rstart bsf STATUS,RP0 ; passer en banque 1 bsf SSPCON2,RSEN ; lancer le repeated start-condition IWAIT SSPCON2,RSEN ; attendre fin repeated start-condition return ; et retour ;***************************************************************************** ; ENVOYER LE STOP-CONDITION * ;***************************************************************************** i2c_stop bsf STATUS,RP0 ; passer en banque 1 bsf SSPCON2,PEN ; lancer le stop-condition IWAIT SSPCON2,PEN ; attendre fin stop-condition return ; et retour ;***************************************************************************** ; ENVOYER LE ACK * ;***************************************************************************** i2c_ack bsf STATUS,RP0 ; passer en banque 1 bcf SSPCON2,ACKDT ; le bit qui sera envoyé vaudra " 0 " bsf SSPCON2,ACKEN ; lancer l'acknowledge (= ACKDT = 0 = ACK) IWAIT SSPCON2,ACKEN ; attendre fin ACK return ; et retour ;***************************************************************************** ; ENVOYER LE NOACK * ;***************************************************************************** i2c_noack bsf STATUS,RP0 ; passer en banque 1 bsf SSPCON2,ACKDT ; le bit qui sera envoyé vaudra " 1 " bsf SSPCON2,ACKEN ; lancer l'acknowledge (= ACKDT = 1 = NOACK) IWAIT SSPCON2,ACKEN ; attendre fin NOACK return ; et retour ;***************************************************************************** ; ENVOYER UN OCTET * ;***************************************************************************** ;----------------------------------------------------------------------------- ; L'octet est passé dans W ;----------------------------------------------------------------------------- i2c_write movwf SSPBUF ; lancer l'émission de l'adresse en mode écriture bsf STATUS,RP0 ; passer en banque 1 IWAIT SSPSTAT,R_W ; attendre émission terminée return ; et retour ;***************************************************************************** ; LIRE UN OCTET * ;***************************************************************************** ;----------------------------------------------------------------------------- ; L'octet est retourné dans W ;----------------------------------------------------------------------------- ;i2c_read ; bsf STATUS,RP0 ; passer en banque 1 ; bsf SSPCON2,RCEN ; lancer la lecture ; IWAIT SSPCON2,RCEN ; attendre réception terminée ; movf SSPBUF,w ; charger octet reçu ; return ; et retour ;********************************************************************* ; SOUS-ROUTINE TEMPO de 2ms (2.06ms) * ;********************************************************************* Tempo2ms bcf STATUS,RP0 ; repasser en banque 0 movlw 0x02 movwf CmptTempo2 ; ajuster à 249,564 ms BclTempo4 clrf CmptTempo1 ; effacer compteur 2 BclTempo5 nop decfsz CmptTempo1,f ; décrémenter compteur1 goto BclTempo5 ; si pas 0, boucler decfsz CmptTempo2,f ; si 0, décrémenter compteur 2 goto BclTempo4 ; si cmpt2 pas 0, recommencer boucle1 return
Merci de votre aide si vous avez une idée car je ne sais plus trop où chercher !
Je mets la suite de la routine sur le post suivant...
-----