<< 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

9. Le jeu d’instructions (Suite 2)

Index coursIndex du cours
Chapitre précédent9. Le jeu d’instructions (Suite 1)
Chapitre suivant10. Les modes d’adressage

 

9. Le jeu d’instructions (Suite 2)
9.25 L’instruction " SWAPF " (SWAP nibbles in F)

Nous pouvons traduire cette instruction par "inverser les quartets dans F ". Cette opération inverse simplement le quartet (demi-octet) de poids faible avec celui de poids fort.

Syntaxe

  swapf f , d ; inversion des b0/b3 de (f) avec b4/b7 -> (d)

Bit du registre STATUS affecté

Aucun : cette particularité nous sera très utile lorsque nous verrons les interruptions.

Exemple

  movlw 0xC5 ; charger 0xC5 dans w
  movwf mavariable ; placer dans mavariable
  swapf mavariable , f ; (mavariable) = 0x5C

 

9.26 L’instruction " CALL " (CALL subroutine)

Cette opération effectue un saut inconditionnel vers un sous-programme. Voyons ce qu’est un sous-programme. Et bien, il s’agit tout simplement d’une partie de programme qui peut être appelé depuis plusieurs endroits du programme dit " principal ".

Le point de départ est mémorisé automatiquement, de sorte qu’après l’exécution du sous-programme, le programme continue depuis l’endroit où il était arrivé. Cela paraît un peu ardu, mais c’est extrêmement simple. Voyez les exemples dans la description de l’instruction RETURN.

Syntaxe

  call etiquette ; appel de la sous-routine à l’adresse etiquette.

Mécanisme

Lors de l’exécution de l’instruction, l’adresse de l’instruction suivante est sauvegardée sur le sommet d’une pile (exactement comme une pile d’assiettes). Lorsque la sous-routine est terminée, l’adresse sauvegardée est retirée de la pile et placée dans le PC. Le programme poursuit alors depuis l’endroit d’où il était parti.

Notez que si le sous-programme (ou sous-routine) appelle lui-même un autre sous programme, l’adresse sera également sauvée au dessus de la pile. Attention, cette pile a une taille limitée à 8 emplacements. Il n’existe aucun moyen de tester la pile, vous devez donc gérer vos sous-programmes pour ne pas dépasser 8 emplacements, sinon, votre programme se plantera.

Notez que lorsque vous sortez d’un sous-programme, l’emplacement est évidemment libéré. La limite n’est donc pas dans le nombre de fois que vous appelez votre sous- programme, mais dans le nombre d’imbrications (sous-programme qui en appelle un autre qui en appelle un autre) etc.

Bit du registre STATUS affecté

Aucun

9.27 L’instruction " RETURN " (RETURN from subroutine)

Retour de sous-routine. Va toujours de pair avec une instruction call. Cette instruction indique la fin de la portion de programme considérée comme sous-routine (SR). Rappelez-vous que pour chaque instruction call rencontrée, votre programme devra rencontrer une instruction return.

Syntaxe

  Return   ; fin de sous-routine. Le PC est rechargé depuis la pile, le
      ; programme poursuit à l’adresse qui suit la ligne call.

Bit du registre STATUS affecté

Aucun

Exemples

Comme ceci est un concept très important, je vais détailler un peu plus. Imaginons un programme qui a besoin d’une petite temporisation (comme chaque instruction prend du temps, on peut s’arranger pour en faire perdre volontairement au programme afin de retarder son fonctionnement. Ecrivons-la :

  movlw 0xCA ; valeur du compteur
  movwf compteur ; initialiser compteur de boucles
boucle      
  decfsz compteur,f ; décrémenter compteur, sauter si 0
  goto boucle ; boucler si pas 0
  xxx   ; suite du programme

Imaginons maintenant que cette petite temporisation soit appelée régulièrement par notre programme principal. Ecrivons à quoi ressemble le programme principal :

  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  tempo   ; ici, on a besoin d’une tempo
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  tempo   ; ici aussi
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  tempo   ; et encore ici
  xxx   ; instruction quelconque

La première chose qui vient à l’esprit, est d’effectuer un copier/coller de notre temporisation. On obtient donc un programme comme ceci :

  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  movlw 0xCA ; valeur du compteur
  movwf compteur ; initialiser compteur de boucles
boucle      
  decfsz compteur,f ; décrémenter compteur, sauter si 0
  goto boucle ; boucler si pas 0
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  movlw 0xCA ; valeur du compteur
  movwf compteur ; initialiser compteur de boucles
boucle2      
  decfsz compteur,f ; décrémenter compteur, sauter si 0
  goto boucle2 ; boucler si pas 0
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  movlw 0xCA ; valeur du compteur
  movwf compteur ; initialiser compteur de boucles
boucle3      
  decfsz compteur,f ; décrémenter compteur, sauter si 0
  goto boucle3 ; boucler si pas 0
  xxx   ; instruction quelconque

Ceci n’est pas élégant, car, si nous devons changer la valeur de notre tempo, nous devons la changer partout dans le programme, sans oublier un seul endroit.

On peut également se dire : " utilisons une macro ", qui, rappelez-vous, effectue une substitution au moment de l’assemblage. C’est vrai, qu’alors, il n’y a plus qu’un endroit à modifier Mais, dans notre PIC, le code se retrouvera cependant autant de fois qu’on a utilisé la temporisation. Que de place perdue, surtout si la portion de code est grande et utilisée plusieurs fois.

Pour remédier à ceci, nous utiliserons la technique des sous-programmes.

Première étape, modifions notre temporisation pour en faire une sous-routine :

tempo     ; étiquette de début de la sous-routine
  movlw 0xCA ; valeur du compteur
  movwf compteur ; initialiser compteur de boucles
boucle      
  decfsz compteur,f ; décrémenter compteur, sauter si 0
  goto boucle ; boucler si pas 0
  return   ; fin de la sous-routine.

Deuxième étape, nous modifions notre programme principal pour que chaque fois que nous avons besoin d’une tempo, il appelle le sous-programme. Nous obtenons :

  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  call tempo ; appel du sous programme
  xxx   ; instruction quelconque, le programme continue ici
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  call tempo ; appel du sous programme
  xxx   ; instruction quelconque, le programme continue ici
  xxx   ; instruction quelconque
  call tempo ; appel du sous programme
  xxx   ; instruction quelconque, le programme continue ici

Dans ce cas, la routine tempo n’est présente qu’une seule fois en mémoire.

On peut améliorer : supposons que nous désirons une temporisation à durée variable. On modifie la sous-routine en supprimant la valeur d’initialisation, et on place celle-ci dans le programme principal. Cela s’appelle un sous-programme avec passage de paramètre(s).

Exemple, notre sous-programme devient :

tempo     ; étiquette de début de la sous-routine
  movwf compteur ; initialiser compteur de boucles
boucle      
  decfsz compteur,f ; décrémenter compteur, sauter si 0
  goto boucle ; boucler si pas 0
  return   ; fin de la sous-routine.

Quand à notre programme principal :

  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  movlw 0x25 ; charger w avec 0x25
  call tempo ; appel du sous programme tempo d'une durée de 0x25
  xxx   ; instruction quelconque, le programme continue ici
  xxx   ; instruction quelconque
  xxx   ; instruction quelconque
  movlw 0x50 ; charger w avec 0x50
  call tempo ; appel du sous programme tempo d'une durée de 0x50
  xxx   ; instruction quelconque, le programme continue ici
  xxx   ; instruction quelconque
  movlw 0x10 ; charger w avec 0x10
  call tempo ; appel du sous programme tempo d'une durée de 0x10
  xxx   ; instruction quelconque, le programme continue ici

Voilà, maintenant vous savez ce qu’est un sous-programme. Enfantin, n’est-ce pas ?

9.28 L’instruction " RETLW " (RETurn with Literal in W)

Retour de sous-routine avec valeur littérale dans W. C’est une instruction très simple : elle équivaut à l’instruction return, mais permet de sortir d’une sous-routine avec une valeur spécifiée dans W.

Syntaxe

  retlw k ; (w) = k puis return

Bit du registre STATUS affecté

Aucun

Exemple

test       ; étiquette de début de notre sous-programme
  btfss mavariable,0 ; teste le bit 0 de mavariable
  retlw 0 ; si vaut 0, fin de sous-programme avec (w)=0
  retlw 1 ; sinon, on sort avec (w) = 1

 

9.29 L’instruction " RETFIE " (RETurn From IntErrupt)

Cette instruction indique un retour d’interruption (nous verrons ultérieurement ce que sont les interruptions). Cette instruction agit d’une manière identique à RETURN, excepté que les interruptions sont remises automatiquement en service au moment du retour au programme principal.

Syntaxe

  retfie   ; retour d’interruption

Bit du registre STATUS affecté

Aucun

9.30 L’instruction " CLRF " (CLeaR F)

Cette instruction efface l’emplacement mémoire spécifié

Syntaxe

  clrf f ; (f) = 0

Bit du registre STATUS affecté

Z : Vaut donc toujours 1 après cette opération.

Exemple

  clrf mavariable ; (mavariable) = 0

 

9.31 L’instruction " CLRW " (CLeaR W)

Cette instruction efface w

Syntaxe

  clrw   ; (w) = 0

C’est une instruction qui n’est pas vraiment indispensable, car on pourrait utiliser l’instruction  " movlw 0 ". La différence est que dans ce cas, le bit Z n’est pas affecté.

Bit du registre STATUS affecté

Z : Vaut donc toujours 1 après cette opération.

9.32 L’instruction " CLRWDT " (CLeaR WatchDog)

Remet à 0 le chien de garde de votre programme. Nous aborderons le fonctionnement du watchdog ultérieurement. Sachez cependant que c’est un mécanisme très pratique qui permet de provoquer un reset automatique de votre PIC en cas de plantage du programme (parasite par exemple).

Le mécanisme est simple à comprendre : il s’agit pour votre programme d’envoyer cette instruction à intervalles réguliers. Si la commande n’est pas reçue dans le délai imparti, la PIC est redémarrée au début. C’est exactement le mécanisme utilisé par les conducteurs de train qui doivent presser un bouton à intervalle régulier. Si le bouton n’est pas pressé, le train s’arrête. On détecte ainsi si le conducteur est toujours correctement en train de travailler.

Syntaxe

  clrwdt   ; remet le timer du watchdog à 0

Bit du registre STATUS affecté

Aucun

9.33 L’instruction " COMF " (COMplement F)

Effectue le complément à 1 de l’emplacement mémoire spécifié. Donc, inverse tous les bits de l’octet désigné

Syntaxe

  comf f , d ; NOT (f) -> (d)

Bit du registre STATUS affecté

Z

Exemple

  movlw B’11001010’ ; charge valeur dans W
  movwf mavariable ; initialise mavariable
  comf mavariable,w ; charge l’inverse de mavariable dans W
      ; (W) = B’00110101’

En utilisant cette instruction, on peut également tester si mavariable vaut 0xFF. En effet, si c’est le cas, W vaudra 0 et Z vaudra donc 1.

9.34 L’instruction " SLEEP " (Mise en sommeil)

Place la PIC en mode de sommeil. Elle ne se réveillera que sous certaines conditions que nous verrons plus tard.

Syntaxe

  Sleep   ; arrêt de la PIC

Bit du registre STATUS affecté

Aucun

9. 35 L’instruction " NOP " (No Operation)

Comme vous devez être fatigués, et moi aussi, je vous présente l’instruction qui ne fait rien, qui ne positionne rien, et qui ne modifie rien. On pourrait croire qu’elle ne sert à rien. En fait elle est surtout utilisée pour perdre du temps, par exemple pour attendre une ou deux instructions, le temps qu’une acquisition ai pu se faire, par exemple. Nous l’utiliserons donc à l’occasion.

Syntaxe

  nop   ; tout simplement

Ceci termine l’analyse des 35 instructions utilisées normalement dans les PICs mid-range.

9.36 Les instructions obsolètes

Il reste 2 instructions qui étaient utilisées dans les précédentes versions de PICs. Elles sont encore reconnues par la PIC 16F84 mais leur utilisation est déconseillée par Microchip. En effet, leur compatibilité future n’est pas garantie.

Il s’agit de l’instruction OPTION, qui place le contenu du registre " W " dans le registre OPTION_REG, et de l’instruction TRIS, qui place le contenu de " W " dans le registre TRISA ou TRISB suivant qu’on utilise TRIS PORTA ou TRIS PORTB.

Ces instructions ne sont plus nécessaires actuellement, car ces registres sont désormais accessibles directement à l’aide des instructions classiques.
 

 

Index cours
Index du cours
Chapitre précédent
9. Le jeu d’instructions (Suite 1)
Chapitre suivant
10. Les modes d’adressage

 


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

Page http://fribotte.free.fr/bdtech/cours/pic16f84/PART1_cours09c.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