9.25 Linstruction " 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 Linstruction " CALL " (CALL subroutine) |
Cette opération effectue un saut inconditionnel vers un sous-programme. Voyons ce
quest un sous-programme. Et bien, il sagit tout simplement dune 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 quaprès
lexécution du sous-programme, le programme continue depuis lendroit où il
était arrivé. Cela paraît un peu ardu, mais cest extrêmement simple. Voyez les
exemples dans la description de linstruction RETURN.
Syntaxe
|
call |
etiquette |
; appel de la sous-routine à ladresse etiquette. |
Mécanisme
Lors de lexécution de linstruction, ladresse de linstruction
suivante est sauvegardée sur le sommet dune pile (exactement comme une pile
dassiettes). Lorsque la sous-routine est terminée, ladresse sauvegardée est
retirée de la pile et placée dans le PC. Le programme poursuit alors depuis
lendroit doù il était parti.
Notez que si le sous-programme (ou sous-routine) appelle lui-même un autre sous
programme, ladresse sera également sauvée au dessus de la pile. Attention, cette
pile a une taille limitée à 8 emplacements. Il nexiste 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 dun sous-programme, lemplacement est
évidemment libéré. La limite nest donc pas dans le nombre de fois que vous
appelez votre sous- programme, mais dans le nombre dimbrications (sous-programme qui
en appelle un autre qui en appelle un autre) etc.
Bit du registre STATUS affecté
Aucun
9.27 Linstruction " 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 à ladresse 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 dune petite temporisation (comme chaque instruction prend du
temps, on peut sarranger 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 dune 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 à lesprit, est deffectuer 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 nest 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 lassemblage. Cest vrai,
qualors, il ny a plus quun endroit à modifier Mais, dans notre PIC, le
code se retrouvera cependant autant de fois quon 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 dune 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 nest présente quune 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 dinitialisation, et on
place celle-ci dans le programme principal. Cela sappelle 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 quest un sous-programme. Enfantin, nest-ce
pas ?
9.28 Linstruction " RETLW " (RETurn with Literal in W) |
Retour de sous-routine avec valeur littérale dans W. Cest une instruction très
simple : elle équivaut à linstruction return, mais permet de sortir
dune 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 Linstruction " RETFIE " (RETurn From IntErrupt) |
Cette instruction indique un retour dinterruption (nous verrons ultérieurement
ce que sont les interruptions). Cette instruction agit dune manière identique à
RETURN, excepté que les interruptions sont remises automatiquement en service au moment
du retour au programme principal.
Syntaxe
|
retfie |
|
; retour dinterruption |
Bit du registre STATUS affecté
Aucun
9.30 Linstruction " CLRF " (CLeaR F) |
Cette instruction efface lemplacement mémoire spécifié
Syntaxe
Bit du registre STATUS affecté
Z : Vaut donc toujours 1 après cette opération.
Exemple
|
clrf |
mavariable |
; (mavariable) = 0 |
9.31 Linstruction " CLRW " (CLeaR W) |
Cette instruction efface w
Syntaxe
Cest une instruction qui nest pas vraiment indispensable, car on pourrait
utiliser linstruction " movlw 0 ". La différence est que
dans ce cas, le bit Z nest pas affecté.
Bit du registre STATUS affecté
Z : Vaut donc toujours 1 après cette opération.
9.32 Linstruction " CLRWDT " (CLeaR WatchDog) |
Remet à 0 le chien de garde de votre programme. Nous aborderons le fonctionnement du
watchdog ultérieurement. Sachez cependant que cest 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 sagit pour votre programme
denvoyer cette instruction à intervalles réguliers. Si la commande nest pas
reçue dans le délai imparti, la PIC est redémarrée au début. Cest exactement le
mécanisme utilisé par les conducteurs de train qui doivent presser un bouton à
intervalle régulier. Si le bouton nest pas pressé, le train sarrê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 Linstruction " COMF " (COMplement F) |
Effectue le complément à 1 de lemplacement mémoire spécifié. Donc, inverse
tous les bits de loctet désigné
Syntaxe
|
comf |
f , d |
; NOT (f) -> (d) |
Bit du registre STATUS affecté
Z
Exemple
|
movlw |
B11001010 |
; charge valeur dans W |
|
movwf |
mavariable |
; initialise mavariable |
|
comf |
mavariable,w |
; charge linverse de mavariable dans W |
|
|
|
; (W) = B00110101 |
En utilisant cette instruction, on peut également tester si mavariable vaut 0xFF. En
effet, si cest le cas, W vaudra 0 et Z vaudra donc 1.
9.34 Linstruction " 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
Bit du registre STATUS affecté
Aucun
9. 35 Linstruction " NOP " (No Operation) |
Comme vous devez être fatigués, et moi aussi, je vous présente linstruction
qui ne fait rien, qui ne positionne rien, et qui ne modifie rien. On pourrait croire
quelle ne sert à rien. En fait elle est surtout utilisée pour perdre du temps, par
exemple pour attendre une ou deux instructions, le temps quune acquisition ai pu se
faire, par exemple. Nous lutiliserons donc à loccasion.
Syntaxe
Ceci termine lanalyse 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 nest pas
garantie.
Il sagit de linstruction OPTION, qui place le contenu du registre
" W " dans le registre OPTION_REG, et de linstruction TRIS, qui
place le contenu de " W " dans le registre TRISA ou TRISB suivant
quon utilise TRIS PORTA ou TRIS PORTB.
Ces instructions ne sont plus nécessaires actuellement, car ces registres sont
désormais accessibles directement à laide des instructions classiques.
|