<< The Fribotte Homepage >>
Un club de passionnés en robotique participant à la coupe de France E=M6.
[Accueil] [Qui sommes-nous ?] [Robots] [Coupe e=m6] [BD Technique] [Forum] [Reportages] [Liens] [WiKiFri]

Fribotte

 

La Programmation des pics
par Bigonoff
Premiere partie - pic 16f84 - Révision 4

Téléchargement des fichiers originels ici
Publié le 26/10/2001

14. Les accès en mémoire " eeprom " (Suite)

Index coursIndex du cours
Chapitre précédent14. Les accès en mémoire " eeprom "
Chapitre suivant15. Le watchdog

 

14. Les accès en mémoire " eeprom " (Suite)
14.8 Accès en lecture dans la mémoire " eeprom "

Pour lire une donnée en eeprom, il suffit de placer l’adresse concernée dans le registre EEADR. Ensuite, vous positionnez le bit RD à 1. Vous pouvez ensuite récupérer la donnée lue dans le registre EEDATA. Il ne faut pas bien sûr oublier les différents changements de banques.

Comme cette procédure est courte et toujours la même, nous allons créer une macro à cette intention. Comme la macro doit contenir l’adresse de lecture, nous réaliserons une macro avec passage de paramètre. Voici la macro à ajouter. Vous devrez être dans la banque0 pour appeler cette macro, et elle vous retourne la valeur lue dans le registre W.

READEE macro adeeprom ; macro avec 1 paramètre (argument)
  movlw adeeprom ; charger adresse eeprom (argument reçu)
  movwf EEADR ; adresse à lire dans registre EEADR
  bsf STATUS , RP0 ; passer en banque1
  bsf EECON1 , RD ; lancer la lecture EEPROM
  bcf STATUS , RP0 ; repasser en banque0
  movf EEDATA , w ; charger valeur lue dans W
  endm   ; fin de la macro

Vous remarquez que vous passez un argument à la macro. Vous désignez cet ou ces arguments après la directive macro. Nous avons utilisé ici l’argument adeeprom pour indiquez l’adresse eeprom. Chaque utilisation de adeeprom dans notre macro sera remplacée par l’argument reçu au moment de l’appel de la macro.

Pour utiliser cette macro, nous devons donc lui passer un argument. Par exemple :

  READEE eereload ; lecture de l’adresse eereload de l’eeprom

Lira l’eeprom à l’adresse eereload, c’est à dire l’adresse 0x00.

Cette macro, comme toutes les modifications principales, seront ajoutées à votre fichier m16f84.asm. Je vous le fournis modifié sous la dénomination " m16f84_n2.asm " [ NDLR : Fichiers exemples ici ]. A partir de la prochaine leçon, il remplacera votre fichier " m16F84.asm " actuel.

Revenons à notre ordinogramme. Nous devons donc ajouter la lecture de l’eeprom dans l’initialisation, et placer cette valeur lue dans reload ET dans cmpt. Voici la routine modifiée :

  ; initialisations variables
  ; ----------------------------
  READEE eereload ; lire emplacement eeprom 0x00
  movwf reload ; placer dans reload
  movwf cmpt ; et initialiser compteur de passages
  goto start ; sauter programme principal

Compilez votre programme et placez-le dans la PIC. La LED doit maintenant clignoter à une fréquence de 1Hz. Si cela ne fonctionne pas, vérifiez ou consultez le fichier " eep_test1.asm " fourni avec cette leçon.

14.9 L’accès en écriture à la zone eeprom

Maintenant vous allez me dire avec raison que cela ne sert à rien de lire en eeprom si on n’arrive pas à y écrire. Notre programme ne présente donc rien de plus que ce que nous avions auparavant. C’est tout à fait justifié. Aussi allons-nous étudier la méthode d’écriture. Comme vous vous en doutez, cette méthode utilise les mêmes registres.

La procédure à suivre consiste d’abord à placer la donnée dans le registre EEDATA et l’adresse dans EEADR. Ensuite une séquence spécifique (il n’y a rien à comprendre, c’est imposé par le constructeur) doit être envoyée à la PIC.

Remarques

  • Microchip recommande que cette procédure spécifique ne soit pas interrompue par une interruption, donc nous couperons les interruptions durant cette phase.
  • A la fin de la procédure d’écriture, la donnée n’est pas encore enregistrée dans l’eeprom. Elle le sera approximativement 10ms plus tard (ce qui représente tout de même pas loin de 10.000 instructions). Vous ne pouvez donc pas écrire une nouvelle valeur en eeprom, ou lire cette valeur avant d’avoir vérifié la fin de l’écriture précédente.
  • La fin de l’écriture peut être constatée par la génération d’une interruption (si le bit EEIE est positionné), ou par la lecture du flag EEIF (s’il avait été remis à 0 avant l’écriture), ou encore par consultation du bit WR qui est à 1 durant tout le cycle d’écriture.

Nous allons écrire une macro d’écriture en eeprom. Cette fois, nous devrons passer 2 paramètres, à savoir la donnée à écrire (mais nous supposerons que nous l’avons placée dans W), et l’adresse d’écriture.

WRITEE macro addwrite ; la donnée se trouve dans W
  LOCAL loop ; étiquette locale
  movwf EEDATA ; placer data dans registre
  movlw addwrite ; charger adresse d'écriture
  movwf EEADR ; placer dans registre
loop      
  bcf INTCON , GIE ; interdire interruptions
  btfsc INTCON , GIE ; tester si GIE bien à 0
  goto loop ; non, recommencer
  bsf STATUS , RP0 ; passer en banque1
  bcf EECON1,EEIF ; effacer flag de fin d'écriture
  bsf EECON1,WREN ; autoriser accès écriture
  movlw 0x55 ; charger 0x55
  movwf EECON2 ; envoyer commande
  movlw 0xAA ; charger 0xAA
  movwf EECON2 ; envoyer commande
  bsf EECON1 , WR ; lancer cycle d'écriture
  bcf EECON1,WREN ; verrouiller prochaine écriture
  bsf INTCON , GIE ; réautoriser interruptions
  bcf STATUS , RP0 ; repasser en banque0
  endm    

Remarques

  • J’ai utilisé ici 3 instructions pour mettre GIE à 0. Ceci était nécessaire à cause d’un bug dans la 16C84, mais a été corrigé dans la 16F84. Le test de vérification n’est plus nécessaire à partir de cette version. Mais ceci me donnait l’occasion de vous montrer les étiquettes locales. Laissez-le donc pour exemple.
  • La directive LOCAL précise que le symbole utilisé dans cette macro n’existera qu’à l’intérieur de celle-ci. Sans cette directive, si vous utilisiez un seul appel de la macro WRITEE dans votre programme, aucun problème. Si maintenant vous utilisiez 2 fois cette macro, pour chaque appel MPASM remplacerait WRITEE par toute la liste d’instructions contenues jusque la directive endm. Vous auriez donc dans votre programme réel 2 fois l’étiquette " loop " à 2 emplacements différents. Ceci générerait une erreur. La directive LOCAL informe MPASM que chaque utilisation de la macro travaille avec une étiquette " loop " différente. Il n’y a donc plus double emploi.
  • Toute la partie surlignée de jaune contient la séquence imposée par Microchip pour l’écriture en eeprom.
  • La procédure d’écriture en eeprom est relativement longue et prend énormément de temps. Pensez que pour remplir la zone complète de 64 octets, il faudra plus de 6/10ème de seconde.
  • Le nombre de cycle d’écritures en eeprom est limité. La durée de vie de l’eeprom est d’environ 10 millions de cycles. Si votre programme comporte une erreur et qu’il écrit sans arrêt des données dans l’eeprom, votre PIC sera hors service en un peu moins de 28 heures. Soyez donc vigilants et vérifiez votre programme.
  • Avant d’écrire dans l’eeprom, vous devez vérifier qu’une autre écriture n’est en cours. Utilisez le bit WR du registre EECON1. S’il vaut 0, il n’y a pas d’écriture en cours.
14.10 Utilisation pratique de la mémoire " eeprom "

Maintenant, nous allons de nouveau modifier notre programme pour qu’il écrive dans l’eeprom. Nous allons incrémenter la durée de temporisation tous les 16 clignotements de la LED (donc tous les 32 passages dans la routine d’interruption), et sauvegarder cette nouvelle valeur dans l’eeprom.

Nous n’aurons pas besoin des interruptions eeprom ici, mais vous devez avoir compris le principe des interruptions suffisamment bien pour pouvoir vous en servir en cas de besoin.

Nous allons donc procéder à la modification de notre routine d’interruption. Nous devons ajouter un second compteur (cmpt2) en zone RAM. Déclarons donc cette variable.

    cmpt2 : 1 ; compteur de passages 2

Oui, je sais, il y avait moyen d’optimiser tout ça pour n’utiliser qu’un compteur. Ce n’est pas le but de cet exercice. Autant rester clair et centrer notre attention sur le sujet de ce chapitre.

La modification est très simple, en réalité. Dans la routine d’interruption timer, nous incrémenterons le compteur 2 qui sera utilisé dans le programme principal.

Voici le nouvel ordinogramme obtenu.

Et la routine d’interruption timer :

;**********************************************************************
; INTERRUPTION TIMER 0
;**********************************************************************
inttimer      
  ; tester compteur de passages
  ; --------------------------
  decfsz cmpt , f ; décrémenter compteur de passages
  return   ; pas 0, on ne fait rien
  ; inverser LED
  ; ------------
  BANK0   ; par précaution
  movlw b'00000100' ; sélectionner bit à inverser
  xorwf PORTA , f ; inverser LED
  ; recharger compteur de passages
  ; ------------------------------
  movf reload , w ; charger valeur contenue dans reload
  movwf cmpt ; dans compteur de passages
  ; incrémenter compteur de passages 2
  ; ----------------------------------
  incf cmpt2 , f ; incrémenter compteur de passages2
  return   ; fin d'interruption timer

Nous allons écrire dans l’eeprom depuis notre programme principal. Il y a deux raisons à ne pas écrire dans l’eeprom depuis notre routine d’interruption timer.

  • Il faut, dans la mesure du possible, quitter le plus rapidement possible une routine d’interruption, celles-ci étant en général dans un programme, réservées aux traitements urgents des informations. Tout ce qui peut être facilement placé ailleurs doit l’être.
  • Nous ne pouvons par remettre les interruptions en service (GIE) depuis une routine d’interruption. Or, notre macro d’écriture eeprom remet GIE à 1. Si vous vouliez utiliser cette macro dans une routine d’interruption, vous devriez au préalable supprimer la remise en service de GIE.

Voyons donc notre programme principal :

;*********************************************************************
; PROGRAMME PRINCIPAL
;*********************************************************************
start      
  ; tester si 16 inversions de LED
  ; -------------------------------------
  btfss cmpt2 , 5 ; tester si 32 passages
  goto start ; non, attendre
  clrf cmpt2 ; oui, effacer compteur2
  ; incrémenter reload
  ; ------------------------
  incf reload , f ; incrémenter reload
  incf reload , f ; incrémenter 2 fois c'est plus visible
  ; Tester si écriture précédente eeprom terminée
  ; --------------------------------------------------------
      ; facultatif ici, car le temps écoulé
      ; est largement suffisant
  BANK1   ; passer banque1
wait      
  btfsc EECON1 , WR ; tester si écriture en cours
  goto wait ; oui, attendre
  BANK0   ; repasser en banque 0
  ; écrire contenu de reload en eeprom
  ; --------------------------------------------
  movf reload , w ; charger reload
  WRITEE eereload ; écrire à l'adresse 0x00
  goto start ; boucler
  END   ; directive fin de programme

Compilez le programme et chargez-le dans la PIC. Placez le montage sur votre platine d’essais. Remarquez que la LED clignote à une fréquence approximative de 1Hz. Au 17ème allumage, la fréquence de clignotement diminue légèrement, et ainsi de suite tous les 16 passages.

Estimez la fréquence de clignotement en cours, et coupez l’alimentation de la PIC. Attendez quelques secondes, et remettez la PIC sous tension. La LED clignote à la fréquence précédente, car le paramètre a été sauvegardé en EEPROM .

Le fichier tel qu’il devrait être à la fin de cette leçon est disponible sous la dénomination " eep_test.asm"

14.11 Sécurisation des accès en mémoire " eeprom "

Lorsque vous écrivez dans la zone eeprom d’une PIC, vous ne pouvez jamais être sûr qu’une coupure de courant ne va pas interrompre la procédure. En conséquence, vous devez vous assurer que les données dans l’eeprom sont bien valides avant de les utiliser au redémarrage suivant.

Voici une procédure qui permet d’en être certain.

  • Placez un en-tête dans le premier ou les premiers octets de votre eeprom. Par exemple, nous placerons 0x55 dans l’octet 0.
  • Lors de l’écriture de nouvelles valeurs dans l’eeprom, nous commençons par effacer notre en-tête.
  • Puis nous écrivons notre ou nos donnée(s) dans l’eeprom
  • Pour finir, nous réinscrivons notre en-tête dans l’eeprom.
  • Lors d’un démarrage de la PIC, si l’en-tête est présent, cela signifie que les données eeprom sont valides. Dans le cas contraire, le cycle d’écriture a été interrompu. A vous alors de réagir en conséquence, par exemple en réinscrivant dans l’eeprom les valeurs par défaut.
  • Pour augmenter la sécurité du système pour les données critiques, vous pouvez placer plusieurs octets d’en-tête.
14.12 Conclusion

Voici encore une nouvelle étape franchie dans votre connaissance de la 16F84. Vous pouvez maintenant utiliser la zone eeprom de votre PIC pour y stocker vos données rémanentes. N’hésitez pas à expérimenter, mais n’oubliez pas de vérifier votre programme pour éviter les écritures inutiles et trop fréquentes dans votre eeprom.

 

 

Index cours
Index du cours
Chapitre précédent
14. Les accès en mémoire " eeprom "
Chapitre suivant
15. Le watchdog

 


Complétez cette page, posez vos questions et remarques ici : WiKiFri

Page http://fribotte.free.fr/bdtech/cours/pic16f84/PART1_cours14b.html modifiée le 14/10/2002.
Copyright fribotte@free.fr, libre de droit pour toute utilisation non commerciale.
Reproduction autorisée par simple mail