Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
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 j’ai finalement opté pour une explication pratique de ces instructions. J’ai
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 d’obtenir toutes les références aux instructions dans le même document.
Cette instruction effectue ce qu’on appelle un saut inconditionnel, encore appelé rupture de séquence
synchrone inconditionnel.
Rappelez-vous que l’instruction goto contient les 11 bits de l’emplacement 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’à l’intérieur d’une même PAGE de 211, soit 2048 Kmots.
Ceci n’a aucune espèce d’importance 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.
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
goto etiquette
Exemple :
Start
goto plusloin ; le programme saute à l’instruction 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.
Syntaxe
incf f,d
Comme pour toutes les instructions, f représente File, c’est à dire l’emplacement 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 l’emplacement mémoire.
W (la lettre w) : dans ce cas, le résultat est laissé dans le registre de travail, et le contenu de
l’emplacement mémoire n’est pas modifié.
La formule est donc (f) + 1 -> (d) : Les parenthèses signifient " le contenu de "
Etant donné que la seule manière, en incrémentant un octet, d’obtenir 0, est de passer de 0xFF à 0x00. Le
report n’est pas nécessaire, puisqu’il va de soi. Si, après une incrémentation, vous obtenez Z=1 , c’est que
vous avez débordé. Z vaudra donc 1 si (f) avant l’exécution valait 0xFF.
Exemples
Syntaxe
decf f,d ; (f) – 1 -> (d)
Exemples
Cette instruction charge la valeur spécifiée (valeur littérale, ou encore valeur immédiate), dans le registre de
travail W.
Syntaxe
Exemple
Syntaxe
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
ATTENTION
Il est impératif ici de bien faire la distinction entre movlw k et movf f,w. Dans le premier cas, c’est la
VALEUR qui est chargée dans w, dans le second c’est le CONTENU de l’emplacement spécifié. Si nous
nous rappelons, dans la leçon précédente que mavariable représentait l’adresse 0x0E de notre zone de
RAM. Supposons maintenant que mavariable contienne 0x50.
movlw mavariable
L’assembleur va traduire en remplaçant mavariable par sa VALEUR. Attention, la valeur, ce n’est pas le
contenu. L’assembleur va donc réaliser la substitution suivante :
movlw 0x0E
Après l’instruction, nous aurons 0x0E dans le registre W. Nous parlerons dans ce cas d’un ADRESSAGE
IMMEDIAT. Le déroulement est du type f -> (d) (f n’est pas entre parenthèses).
mavariable ,
movf
w
L’assembleur va traduire également en remplaçant mavariable par sa valeur. Nous obtenons donc :
movf 0x0E , w
Ce qui signifie : charger le CONTENU de l’emplacement 0x0E dans w. Nous parlerons ici d’un
ADRESSAGE DIRECT. Je rappelle qu’il 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
movf mavariable , f
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.
Syntaxe
Aucun
Exemple
Cette opération permet d’ajouter une valeur littérale (adressage immédiat) au contenu du registre de travail
W.
Syntaxe
Exemple
Ne pas confondre avec l’instruction précédente. Une nouvelle fois, il s’agit ici d’un ADRESSAGE
DIRECT. Le CONTENU du registre W est ajouté au CONTENU du registre F
Syntaxe
C, DC, et Z
Exemple
Syntaxe
C, DC, Z
Notez ici que le bit C fonctionne de manière inverse que pour l’addition. Ceci est commun à la plupart des
microprocesseurs du marché.
Ceci est logique, et s’explique en faisant une soustraction manuelle. Le bit C représente le 9ème bit ajouté
d’office à 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 n’y a pas
de report, le résultat final reste donc sur 9 bits. La formule de la soustraction est donc : k précédé d’un
neuvième bit à 1 – contenu de W = résultat sur 8 bits dans W avec 9ème bit dans C.
Exemple 1
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’ – B’1’, car souvenez-vous qu’on a emprunter 10 en BINAIRE.
Résultat 1. On soustrait ensuite les b1 : on aura 1 – 0 – l’emprunt, donc 1-0-1 = 0. On continue de droite à
gauche jusqu’au 9ème bit qui est le carry. Résultat final : B’00000001’ et carry à 1, cqfd.
Exemple 2
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
Exemple 3
Procédons de la même manière, et nous obtenons B’11111111’, avec le bit C à 0. Et là, me dites-vous,
B’11111111’, c’est 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 l’opération est négatif. Or, comment
savoir la valeur absolue d’un nombre négatif ? En prenant son complément à 2. Rappelez-vous :
Vous maîtrisez maintenant les soustractions. Certains auront sans doute pensé que j’expliquais trop en
détail, mais mon expérience m’a 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 d’interpréter les bits Z et C. Je vous
laisse le faire vous-même pour vous convaincre.
Nous restons dans les soustractions, mais, cette fois, au lieu d’un adressage immédiat, nous avons un
ADRESSAGE DIRECT.
Syntaxe
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
Cette instruction effectue une opération " AND " BIT A BIT entre le contenu de W et la valeur littérale qui
suit.
Syntaxe
Exemple
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 0 1 1 0 1
And 1 1 1 1 0 0 0 0
= 1 1 0 0 0 0 0 0
Rappelez-vous qu’on effectue un AND entre chaque bit de même rang. Seuls restent donc positionnés à 1
les bits dont les 2 opérandes valent 1. Donc, le fait d’effectuer un AND avec la valeur B’11110000’
MASQUE les bits 0 à 3, et ne laisse subsister que les bits 4 à 7.
Tant que vous ne jonglerez pas avec l’hexadécimal, je vous conseille de toujours traduire les nombres en
binaires pour toutes les instructions concernant les bits.
Syntaxe
Exemple
Et oui, les mêmes instructions, mais pour le OU inclusif. Inclusif signifie simplement le contraire
d’exclusif, c’est à dire que le bit de résultat vaudra 1 si un des bits, OU LES DEUX BITS, opérandes =1.
Syntaxe
Exemple
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 0 0 0 1 1
OR 0 0 0 0 1 1 1 1
= 1 1 0 0 1 1 1 1
Donc, avec un ou inclusif (OR), on peut FORCER n’importe quel bit à 1 (pour rappel, avec AND, on peut
forcer n’importe quel bit à 0).
Effectue un OR entre (w) et l’emplacement spécifié. C’est donc une instruction en ADRESSAGE DIRECT.
Je ne donnerais pas d’exemple, vous devriez avoir compris.
Syntaxe
Par opposition au ou inclusif, voici maintenant le OU EXCLUSIF. Sa table de vérité est la même que le ou
inclusif, excepté que lorsque les 2 bits sont à 1, le résultat est 0.
Cette instruction va donc servir à INVERSER n’importe quel bit d’un octet. En effet, si vous effectuez " 1
xor 0 ", vous obtenez 1, si vous effectuez " 0 xor 0 ", vous obtenez 0. Donc, si vous appliquez xor 0, la
valeur de départ est inchangée.
Si par contre vous appliquez " 0 xor 1 " , vous obtenez 1, et avec " 1 xor 1 ", vous obtenez 0. En appliquant
xor 1, vous inversez le bit, quelque soit son état initial.
Maintenant, vous pouvez donc FORCER un bit à 1 avec OR, MASQUER un bit (le mettre à 0) avec AND,
et l’INVERSER avec XOR.
Syntaxe
Exemple
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 0 0 1 0 1
xor 0 0 0 0 1 1 1 1
= 1 1 0 0 1 0 1 0
Remarquez que tous les bits de l’octet initial ont été inversés par chaque bit de la seconde opérande qui
étaient à 1.
Syntaxe
C’est une instruction qui permet tout simplement de forcer directement un bit d’un emplacement mémoire à
1
Syntaxe
Aucun
Exemples
C’est une instruction qui permet tout simplement de forcer directement un bit d’un emplacement mémoire à
0
Syntaxe
Aucun
Exemples
Les opérations de décalage sont des opérations très souvent utilisées. Les PICs ont la particularité de ne
posséder que des opérations de ROTATION. Vous allez voir qu’avec ces opérations, on peut très
facilement réaliser des décalages.
L’opération de rotation effectue l’opération suivante : Le bit de carry C est mémorisé. Ensuite chaque bit de
l’octet est déplacé vers la gauche. L’ancien bit 7 sort de l’octet par la gauche, et devient le nouveau carry.
Le nouveau bit 0 devient l’ancien carry. Il s’agit donc d’une rotation sur 9 bits.
Syntaxe
Exemple1
C b7 b6 b5 b4 b3 b2 b1 b0
f 1 0 0 0 1 0 1 1 1
rlf 0 0 0 1 0 1 1 1 1
Vous voyez que tous les bits ont été décalés vers la gauche. " C " a été réintroduit dans b0. Le résultat reste
sur 9 bits.
Exemple 2
Si vous avez compris, le résultat sera B’00101110’, avec le carry à 0. Si le carry est à 0 au départ, on
effectue un simple décalage vers la gauche. Que se passe-t-il si, en décimal, on effectue ce type
d’opération ?
Prenons le nombre 125 et décalons-le vers la gauche en décimal, nous obtenons 1250. Nous avons multiplié
le nombre par sa base. Et bien c’est la même chose en binaire (une fois de plus).
Prenons B’00010111 ‘, soit 23 en décimal. Décalons-le, nous obtenons B’00101110’, soit 46. Nous avons
donc effectué une multiplication par 2. Retenez ceci, cela vous sera très utile par la suite.
L’opération de rotation vers la droite effectue l’opération suivante : Le bit de carry " C " est mémorisé.
Ensuite chaque bit de l’octet est déplacé vers la droite. L’ancien bit 0 sort de l’octet par la droite, et devient
le nouveau carry. L’ancien Carry devient le nouveau bit7. Il s’agit donc également d’une rotation sur 9 bits.
Syntaxe
Exemple1
b7 b6 b5 B4 b3 b2 b1 b0 C
f 0 0 0 1 0 1 1 1 1
rrf 1 0 0 0 1 0 1 1 1
Vous voyez que tous les bits ont été décalés vers la droite. C a été réintroduit dans b7. Le résultat reste sur 9
bits.
Exemple 2
Que s’est-il passé ? Et bien notre nombre de départ, soit 23 en décimal est devenu 11. Le carry représente le
bit " -1 ", donc, la moitié du bit 0, donc ½. En effet, en décimal, le chiffre derrière les unités a comme
valeur 1/base, donc 1/10. En binaire ce sera donc ½.
Si nous regardons alors les 9 bits, nous obtenons 11 ½ . Nous avons donc effectué une DIVISION PAR 2.
Retenez ceci, cela vous sera également très utile par la suite.
Traduit littéralement, cela donne : Teste le bit de l’emplacement mémoire et saute s’il vaut 0. Il s’agit ici de
votre premier SAUT CONDITIONNEL, ou RUPTURE DE SEQUENCE SYNCHRONE
CONDITIONNELLE .
En effet, il n’y aura saut que si la condition est remplie. Notez que dans ce cas l’instruction prendra 2
cycles, sinon, elle n’utilisera qu’un cycle. De plus, il faut retenir que pour tous ces types de saut, ON NE
SAUTE QUE l’INSTRUCTION SUIVANTE. En effet, la syntaxe ne contient pas d’adresse de saut,
comme nous allons le voir
Syntaxe
Aucun
Exemple1
Voici un exemple dans lequel on doit exécuter une seule instruction supplémentaire si le bit vaut 1.
Exemple 2
Que faire si les traitements différent de plus d’une instruction ? Et bien, on combine les sauts conditionnels
avec les saut inconditionnels (par exemple goto).
Ces procédures sont les mêmes pour tous les sauts inconditionnels, je ne les détaillerai donc pas avec autant
d’explications.
Syntaxe
Aucun
Exemple
Nous poursuivons les sauts conditionnels avec une instruction très utilisée pour créer des boucles. Cette
instruction décrémente un emplacement mémoire et saute l’instruction suivante si le résultat de la
décrémentation donne une valeur nulle.
Syntaxe
Aucun
Exemple1
ATTENTION
la boucle n’aurait jamais de fin, car la variable compteur ne serait jamais modifiée.
- Si vous placez 0 dans le compteur de boucles, la boucle sera exécutée 256 fois. Si vous ne désirez pas que
la boucle soit exécutée dans ce cas, vous devez ajouter un test AVANT l’exécution de la première boucle,
comme dans l’exemple suivant :
Exemple 2
Je ne vais pas détailler cette instruction, car elle est strictement identique à la précédente, hormis le fait
qu’on incrémente la variable au lieu de la décrémenter.
Syntaxe :
Aucun
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
Aucun : cette particularité nous sera très utile lorsque nous verrons les interruptions.
Exemple
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 ".
Syntaxe
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.
Aucun
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
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 :
La première chose qui vient à l’esprit, est d’effectuer un copier/coller de notre temporisation. On obtient
donc un programme comme ceci :
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.
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 :
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).
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
Aucun
Exemple
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
Aucun
Syntaxe
clrf f ; (f) = 0
Exemple
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é.
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
Aucun
Syntaxe
Exemple
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.
Place la PIC en mode de sommeil. Elle ne se réveillera que sous certaines conditions que nous verrons plus
tard.
Syntaxe
Aucun
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
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.