Les instructions sont détaillées à partir de la page 57 du datasheet. Il peut donc
sembler inutile de les reprendre dans ce cours. Mais jai finalement opté pour une
explication pratique de ces instructions. Jai choisi en effet de les expliquer avec
des petits exemples concrets, plutôt que de simplement traduire le datasheet.
Bien entendu, vous pouvez expérimenter ces instructions avec MPLAB et son simulateur,
en insérant ces instructions après létiquette " start " de
votre programme.
Je vais donc expliquer ces instructions dans un ordre qui me facilite les explications,
en commençant par celles déjà vues, dans le but final dobtenir toutes les
références aux instructions dans le même document.
9.1 Linstruction " GOTO " (aller à) |
Cette instruction effectue ce quon appelle un saut inconditionnel, encore appelé
rupture de séquence synchrone inconditionnel.
Rappelez-vous que linstruction goto contient les 11 bits de lemplacement de
destination. Les 2 bits restants sont chargés depuis le registre PCLATH. Rappelez-vous en
effet la manière dont est construit le PC dans le cas des sauts. On ne peut sauter
quà lintérieur dune même PAGE de 211,
soit 2048 Kmots.
Ceci na aucune espèce dimportance pour la 16F84, qui ne dispose que de
1Kmots de mémoire programme, mais devra être considéré pour les pics de plus grande
capacité (16F876). Nous en reparlerons à ce moment.
Voici donc en résumé le fonctionnement du goto :
- Ladresse de saut sur 11 bits est chargée dans le PC.
- Les 2 bits manquants sont chargés depuis PCLATH (b3 et b4), pas pour la 16F84.
- Le résultat donne ladresse sur 13 bits (10 bits pour la 16F84)
- La suite du programme seffectue à la nouvelle adresse du PC.
Souvenez-vous, que pour la 16F84 : Adresse de saut = adresse réelle. Vous ne
devez donc vous préoccuper de rien. Pour les autres, en cas de débordement, MPLAB vous
le signalera.
Syntaxe
Exemple :
Start |
|
|
|
|
goto |
plusloin |
; le programme saute à linstruction qui suit létiquette |
|
xxxx |
xxxx |
; plusloin |
|
xxxx |
xxxx |
|
plusloin |
|
|
|
|
xxxx |
xxxx |
; instruction exécutée après le saut : le programme se poursuit ici |
Remarquez que vous pouvez sauter en avant ou en arrière.
goto nécessite 2 cycles dhorloge, comme pour tous les sauts
9.2 Linstruction " INCF " (INCrement File) |
Cette instruction provoque lincrémentation de lemplacement spécifié
(encore appelé File).
Syntaxe
Comme pour toutes les instructions, f représente File, cest à dire
lemplacement mémoire concerné pour cette opération. d représente la Destination.
Sauf spécification contraire, d vaut toujours, au choix :
- F (la lettre f) : dans ce cas le résultat est stocké dans lemplacement
mémoire.
- W (la lettre w) : dans ce cas, le résultat est laissé dans le registre de
travail, et le contenu de lemplacement mémoire nest pas modifié.
La formule est donc (f) + 1 -> (d) : Les parenthèses signifient " le
contenu de "
Bit du registre STATUS affecté
Le seul bit affecté par cette opération est le bit Z.
Etant donné que la seule manière, en incrémentant un octet, dobtenir 0, est de
passer de 0xFF à 0x00. Le report nest pas nécessaire, puisquil va de soi.
Si, après une incrémentation, vous obtenez Z=1 , cest que vous avez
débordé. Z vaudra donc 1 si (f) avant lexécution valait 0xFF.
Exemples
|
incf |
mavariable , f |
; le contenu de ma variable est augmenté de 1 |
|
|
|
; le résultat est stocké dans mavariable. |
|
incf |
mavariable , w |
; Le contenu de mavariable est chargé dans w et |
|
|
|
; augmenté de 1. W contient donc le contenu de |
|
|
|
; mavariable + 1. mavariable nest pas modifié |
9.3 Linstruction " DECF " (DECRement File) |
Decrémente lemplacement spécifié. Le fonctionnement est strictement identique
à linstruction précédente.
Syntaxe
|
decf |
f,d |
; (f) 1 -> (d) |
Bit du registre STATUS affecté
Le seul bit affecté par cette opération est le bit Z.
Si avant linstruction, (f) vaut 1, Z vaudra 1 après lexécution (1-1 = 0)
Exemples
|
decf |
mavariable , f |
; décrémente mavariable, résultat dans mavariable |
|
decf |
mavariable , w |
; prends (mavariable) 1 et place le résultat dans w |
9.4 Linstruction " MOVLW " (MOVe Literal to W) |
Cette instruction charge la valeur spécifiée (valeur littérale, ou encore valeur
immédiate), dans le registre de travail W.
Syntaxe
|
movlw |
k |
; k représente une valeur de 0x00 à 0xFF. |
Bit du registre STATUS affecté
Aucun ( donc même si vous chargez la valeur 0.)
Exemple
|
movlw |
0x25 |
; charge 0x25 dans le registre w |
9.5 Linstruction " MOVF " (MOVe File) |
Charge le contenu de lemplacement spécifié dans la destination
Syntaxe
Bit du registre STATUS affecté
Une fois de plus, seul le bit Z est affecté (si f vaut 0, Z vaut 1).
Exemple 1
Pour cette instruction, je vais me montrer beaucoup plus explicite. Vous allez
comprendre pourquoi
|
movf |
mavariable,w |
; charge le contenu de mavariable dans w. |
ATTENTION
Il est impératif ici de bien faire la distinction entre movlw k et movf f,w. Dans le
premier cas, cest la VALEUR qui est chargée dans w, dans le second cest le
CONTENU de lemplacement spécifié. Si nous nous rappelons, dans la leçon
précédente que mavariable représentait ladresse 0x0E de notre zone de RAM.
Supposons maintenant que mavariable contienne 0x50.
Si nous exécutons linstruction suivante :
Lassembleur va traduire en remplaçant mavariable par sa VALEUR. Attention, la
valeur, ce nest pas le contenu. Lassembleur va donc réaliser la substitution
suivante :
Après linstruction, nous aurons 0x0E dans le registre W. Nous parlerons dans ce
cas dun ADRESSAGE IMMEDIAT. Le déroulement est du type f -> (d) (f nest
pas entre parenthèses).
Si nous exécutons par contre linstruction suivante :
Lassembleur va traduire également en remplaçant mavariable par sa valeur. Nous
obtenons donc :
Ce qui signifie : charger le CONTENU de lemplacement 0x0E dans w. Nous
parlerons ici dun ADRESSAGE DIRECT. Je rappelle quil est primordial de ne pas
confondre, sinon, vous ne comprendrez plus rien lors de la réalisation des programmes.
Après cette instruction, W contient donc 0x50. Le déroulement est du type (f) -> (d).
Exemple 2
Que fait cette instruction ? Si vous avez tout suivi, elle place le CONTENU de
mavariable dans mavariable. Dire que cela ne sert à rien est tentant mais prématuré.
En effet, si le contenu de mavariable reste bien inchangé, par contre le bit Z est
positionné. Cette instruction permet donc de vérifier si (mavariable) = 0.
9.6 Linstruction " Movwf " (MOVe W to File) |
Permet de sauvegarder le contenu du registre de travail W dans un emplacement mémoire.
Syntaxe
Bit du registre STATUS affecté
Aucun
Exemple
|
movlw |
0x50 |
; charge 0x50 dans W |
|
movwf |
mavariable |
; ma variable contient maintenant 0x50. |
9.7 Linstruction " ADDLW " (ADD Literal and W) |
Cette opération permet dajouter une valeur littérale (adressage immédiat) au
contenu du registre de travail W.
Syntaxe
Bits du registre STATUS affectés
- Z Si le résultat de lopération vaut 0, Z vaudra 1
- C Si le résultat de lopération est supérieur à 0xFF (255) , C vaudra 1
- DC Si le résultat de lopération entraîne en report du bit 3 vers le bit 4, DC
vaudra 1
Ne vous inquiétez pas trop pour DC, il nest utilisé que pour les opérations sur
les quartets, par exemple, les nombres Binary Coded Decimal
Exemple
|
movlw |
253 |
; charger 253 en décimal dans W |
|
addlw |
4 |
; Ajouter 4. W contient 1, Z vaut 0, C vaut 1(déborde) |
|
addlw |
255 |
; ajouter 255 W vaut 0, C vaut 1, Z vaut 1 |
9.8 Linstruction " ADDWF " (ADD W and F) |
Ne pas confondre avec linstruction précédente. Une nouvelle fois, il
sagit ici dun ADRESSAGE DIRECT. Le CONTENU du registre W est ajouté au
CONTENU du registre F
Syntaxe
|
addwf |
f , d |
; (w) + (f) -> (d) |
Bits du registre STATUS affectés
C, DC, et Z
Exemple
|
movlw |
12 |
; charger 12 dans W |
|
movwf |
mavariable |
; mavariable vaut maintenant 12 |
|
movlw |
25 |
; charger 25 dans W |
|
addwf |
mavariable,f |
; résultat : (W) + (mavariable), donc 25+12 |
|
|
|
; résultat = 37 sauvé dans mavariable (,f) |
9.9 Linstruction " SUBLW " (SUBtract W from Literal) |
Attention, ici il y a un piège. Linstruction aurait du sappeler SUBWL. En
effet, on soustrait W de la valeur littérale, et pas linverse.
Syntaxe
Bits du registre STATUS affectés
C, DC, Z
Notez ici que le bit C fonctionne de manière inverse que pour laddition. Ceci
est commun à la plupart des microprocesseurs du marché.
Si le résultat est positif, donc, pas de débordement : C =1. S il y a
débordement, C devient 0.
Ceci est logique, et sexplique en faisant une soustraction manuelle. Le bit C
représente le 9ème bit ajouté doffice à la valeur initiale. Si on
effectue une soustraction manuelle donnant une valeur <0, on obtient donc une valeur
finale sur 8 bits, le report obtenu venant soustraire le bit C. Si le résultat est >0,
il ny a pas de report, le résultat final reste donc sur 9 bits. La formule de la
soustraction est donc : k précédé dun neuvième bit à 1 contenu
de W = résultat sur 8 bits dans W avec 9ème bit dans C.
Exemple 1
|
movlw |
0x01 |
; charger 0x01 dans W |
|
sublw |
0x02 |
; soustraire W de 2 |
|
|
|
; résultat : 2 (W) = 2-1 = 1 |
|
|
|
; Z = 0, C = 1, donc résultat positif |
Effectuons cette opération manuellement :
|
C |
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
Dec |
|
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
010 |
2 |
- |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
01 |
1 |
1 |
= |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
Comment procéder ? Et bien, comme pour une soustraction décimale. On commence
par les bits de droite : 0-1, ça ne passe pas, donc on emprunte 10 (noté en
exposant vert), et on soustraira évidemment une unité supplémentaire au bit b1. On a
donc :B 10 B1, car souvenez-vous quon a
emprunter 10 en BINAIRE. Résultat 1. On soustrait ensuite les b1 : on aura 1
0 lemprunt, donc 1-0-1 = 0. On continue de droite à gauche jusquau 9ème
bit qui est le carry. Résultat final : B00000001 et carry à 1, cqfd.
Exemple 2
|
movlw |
0x02 |
; charger 0x02 dans W |
|
sublw |
0x02 |
; soustraire 2 (w) = 2 2 = 0 |
|
|
|
; Z = 1 , C = 1 : résultat nul |
|
C |
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
Dec |
|
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
2 |
- |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
2 |
= |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
On procède toujours de la même manière.
Exemple 3
|
movlw |
0x03 |
; charger 0x03 dans W |
|
sublw |
0x02 |
; soustraire 2 (W) = 2 3 = -1 |
|
|
|
; Z = 0, C = 0, résultat négatif |
|
C |
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
Dec |
|
1 |
010 |
010 |
010 |
010 |
010 |
010 |
110 |
010 |
2 |
- |
01 |
01 |
01 |
01 |
01 |
01 |
01 |
11 |
1 |
3 |
= |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
-1 |
Procédons de la même manière, et nous obtenons B11111111, avec le bit C
à 0. Et là, me dites-vous, B11111111, cest FF, pas 1. Et bien,
rappelez-vous ceci : Vous DEVEZ lire le bit C pour interpréter le résultat de votre
soustraction.
Comme ce dernier vaut 0, vous êtes AVERTIS que le résultat de lopération est
négatif. Or, comment savoir la valeur absolue dun nombre négatif ? En
prenant son complément à 2. Rappelez-vous :
Complément à 1 de B11111111 = B00000000 (on inverse tous les
bits)
Complément à 2 = complément à 1 + 1, donc B00000001.
Donc, le complément à 2 de 0xFF vaut 0x01. cqfd.
La preuve, si vous ajoutez 1 à 1, vous obtenez B11111111 +
B00000001 = B00000000 = 0.
Vous maîtrisez maintenant les soustractions. Certains auront sans doute pensé que
jexpliquais trop en détail, mais mon expérience ma appris que les
soustractions représentaient souvent un écueil dans la réalisation de trop de
programmes.
Encore un dernier détail : Pour effectuer une soustraction de 1, vous pouvez bien
entendu effectuer une addition de 1. Le résultat sera strictement le même, à
votre charge dinterpréter les bits Z et C. Je vous laisse le faire vous-même pour
vous convaincre.
9.10 Linstruction " SUBWF " (SUBtract W from F) |
Nous restons dans les soustractions, mais, cette fois, au lieu dun adressage
immédiat, nous avons un ADRESSAGE DIRECT.
Syntaxe
|
subwf |
f , d |
; (f) (W) -> (d) |
Bits du registre STATUS affectés
C , DC , Z
Exemple
|
movlw |
0x20 |
; charger 0x20 dans w |
|
movwf |
mavariable |
; mettre w dans (mavariable) (0x20) |
|
movlw |
0x1F |
; charger 0x1F dans w |
|
subwf |
mavariable,w |
; (mavariable) - (w) -> (w) |
|
|
|
; 0x20 0x1F = 0x01 |
|
|
|
; résultat dans w, C=1, Z=0 |
|
movwf |
autrevariable |
; sauver 0x01 dans une autre variable |
|