http://www.didel.com/ [email protected]
www.didel.com/pic/Cours877-2.pdf
Apprendre à programmer avec le 16F877A -
2
e
partie
Exemples et exercices sous www.didel.com/pic/Cours877-2.zip
1ere partie sous www.didel.com/pic/Cours877.pdf
Gérons des entrées
Câblons le microdule P4S4 sur le portA. Il a 4
poussoirs sur les 4 bits de poids faibles, et 4
interrupteurs.
Copions le portA sur le portD Ex877-201.asm
On voit que les poussoirs sont actifs à zéro
(quand on presse, on a un zéro, affiché en
rouge) et que les interrupteurs ont leur état
‘’1’’ en haut, ce qui est logique.
Le portA n’a que 6 bits connectés. On voit
que les 2 interrupteurs à droite n’ont pas
d’effet, et que le processeur met ces bits à
zéro.
Masquage – instruction ET
Pour n’observer qu’un seul bit ou un groupe de bits, on fait un ET logique avec une valeur que
l’on appelle masque, et que l’on écrit naturellement en binaire. Par exemple, si on veut surveiller
le poussoir tout à droite, câblé sur le bit 0, on écrit
Move PortA,W
And #2'00000001,W
Move W,PortD ;
pour voir l’effet
Le résultat est qu’un seul bit passe, et la valeur est nulle ou non, ce qui permet d’aiguiller le
programme dans deux directions selon la valeur du bit.
Le programme Ex877-202.asm allume tous les bits du port C si le poussoir est pressé.
Ce programme est bien écrit avec une étiquette inutile (Allume:) qui met en évidence la structure
du programme avec 2 branches.
En assembleur, l’efficacité du code compte plus et on fait une jolie astuce : on se prépare à écrire
des zéros dans le portC, et si le poussoir est pressé, on change d’avis. On économise 4
instructions, et aussi quelques microsecondes.
Move PortA,W
And #2'00000001,W
Move W,PortD
Move #2'00000000,W ; Si la touche est relâchée
Skip,NE ; NE si relâché
Move #2'11111111,W ; On passe ici si la touche est pressée
Move W,PortC
Jump Loop
Créez vous-même le programme Ex877-203.asm avec ces instructions, et retenez bien ce truc,
c’est efficace.
Instruction OU
Le OU logique superpose les 2 opérandes, chaque bit étant le OU des bits correspondants.
Cela permet de forcer les bits du masque à un (le ET force les bits à 0. Par exemple, si on veut
masquer les bits de poids forts et les mettre tous à un pour ne voir que les poussoirs du microdule
P4S4, on écrit
Move PortA,W
Or #2'11110000,W
Move W,PortD
Une application fréquente est de décider si une variable 16 bits (un compteur, un long registre à
décalage) ne contient que des zéros. Le OU des deux mots est nul que si chaque mot est nul.
Le programme Ex877-204.asm améliore le programme Ex877-110 vu précédemment . Il arrête le
décalage dès que les deux registres sont vides.
Instruction XOR
Le OU-Exclusif XOR met un 1 si les 2 bits correspondants sont différents. Si l’un des deux mots
(masque) est à zéro ne change rien ; un masque à un change tout.
Si le masque est égal à l’autre mot, le résultat est nul, et il est nul seulement dans ce cas.
Par exemple, on veut savoir si les interrupteurs sont en
haut et le poussoir de droite activé, donc si le
processeur lit 2’00111110 sur le portA.
On écrit
Move PortA,W
XOR #2’
00111110
,W
Skip,EQ
Jump Mauvais
Jump BonneCombinaison
Inversion logique – Instruction NOT
On a vu comment inverser tous les bits : Xor #2’11111111,W en plus court Xor #-1,W
L’instruction NOT fait la même chose sur une variable.
Vous voulez savoir si tous les bits d’une variable ou d’un port sont à 1 ?
1ere solution
Not Var
Skip,EQ
Jump Pas à un
; tout est à un
2
e
solution
Inc Var
Skip,EQ
Jump Pas à un
; tout est à un
Test d’un bit – Instruction TestSkip,BS
L’instruction TestSkip,BS Var:#bit est longue à écrire, mais elle dit bien ce qu’elle fait : on teste
un bit de la variable ; si ce bit est à 1 (set) on saute l’instruction suivante.
Pour nos poussoirs, c’est donc facile. On veut afficher différents motifs selon le poussoir :
TestSkip,BS PortA :#0
Jump Poussoir0Actif
TestSkip,BS PortA :#1
Jump Poussoir1Actif
etc.
Ecrire #0 #1 n’est pas recommandé, il faut toujours donner des noms aux signaux. Une bonne
habitude est de distinguer les noms donnés aux bits en ajoutant au début un b minuscule (pour
les masques un m minuscule). C’est ce qui est fait dans le programme Ex877-205.asm. Cela
devient plus intéressant, mais étudiez bien ce qui permet le clignotement.
L’instruction TestSkip,BC Var:#bit saute si le bit testé est clear (à zéro).
Compter des impulsions
Si on veut compter les actions d’un poussoir, le programme ne doit compter qu’une fois par
action, et ne pas compter quand on presse, ni quand on relâche. Il faut donc deux boucles
d’attente. On peut décider d’agir quand on presse ou quand on relâche.
Loop:
AtPous: TestSkip,BC PortA:#bPousD
Jump AtPous
; on vient de presser, que faut-il faire
AtRel: TestSkip,BS PortA:#bPousD
Jump AtRel
; on vient de relâcher, que faut-il faire
Jump Loop
Le programme Ex877-206.asm compte sur le PortC quand on presse, et sur le portD quand on
relâche. Que remarque-t’on ?
Les contacts mécaniques ont des rebonds,
pendant 0.1 à 5 millisecondes (selon la
mécanique interne) et le processeur peut les
voir comme des actions séparées si on
échantillonne trop souvent. On échantillonne
donc à plus de 1ms pour des poussoirs
miniatures, et moins de 0.1s pour ne pas
rater les actions humaines les plus rapides.
Modifiez le programme Ex877-206.asm pour vérifier. Evidemment, il ne faut pas écrire
AtPous: TestSkip,BC PortA:#bPousD
Call Del1ms
Jump AtPous
2.16 Testeur de réflexes
On veut savoir combien de temps, ou quand on a pressé sur un poussoir. Il faut dans la boucle
d’attente, surveiller le signal du poussoir, toutes les 10 millisecondes par exemple si on veut être
assez précis, et presser moins de 10ms * 255 = 2.55 secondes si on ne veut pas de
débordement. Pour un détecteur de réflexes, on met un compteur à zéro, on attend quelques
secondes avant d’allumer une LED et on compte à partir de cet instant. Le cœur du programme
Ex877-207.asm est donc :
TestReflexe:
Clr PortC
Move #20,W
Call DelWx01s ; attente 2 secondes
Dec PortC ; PortC à 1
Clr PortD
AtPous:
Move #10,W
Call DelWx1ms
Inc PortD ; Durée en multiple de 10ms
TestSkip,BC PortA:#bPousD
Jump AtPous
Fini: Jump Fini ; ou Jump TestReflexe
On se pose naturellement quelques questions avec ce programme. Comment compter en décimal
et pas en binaire, comment faire une attente initiale aléatoire, comment recommencer
Agir sur une seule ligne de sortie
Si on sait observer une seule entrée, on doit aussi pouvoir agir sur une seule sortie. Ce sont les
instructions Set Var:#bit et Clr Var:#bit (Clr Var existe, on l’a utilisé pour mettre des ports à
0, mais pas Set Var).
Ces instructions très utiles agissent aussi sur les fanions et ont une notation abbrégée
SetC Force le carry à 1 ClrC Force le carry à 0
Par exemple, comment simuler l’instruction RR Var, qui fait un rotate 8 bits sans passer par le
carry ? On teste le carry et on le copie dans le bit de poids fort.
ClrC
RRC Var ; le bit 7 (poids fort) et à 0
Skip,CC
Set Var :#7 ; à 1 si carry à 1
Imaginons une application qui demande de permuter les paires de bits. Les bits 76543210 doivent
devenir 67452301. Avec 8 TestSkip et 8 Set bits et quelques instructins supplémentaires, ou peut
résoudre le problème. Une autre solution utilise des masquages (un bit sur deux) et un décalage.
Joli exercice de style pour se faire la main.
Instruction Swap
Les mots de 8 bits représentent souvent deux chiffres hexa ou décimaux (code BCD).
L’instruction Swap Var permute ces deux moitiés. Swap Var,W copie dans W les bits
permutés, sans modifier Var. 76543210 32107654.
Arithmétique
L’arithmétique binaire ou hexadécimale ne nous est pas naturelle, et la limitation des opérations à
8 bits ne facilite pas les choses. En assembleur, on ne fait pas des applications qui nécessitent
des calculs. Les applications pour des petits microcontrôleurs se limitent à corriger des
paramètres et comparer des valeurs, on ne va donc chercher à comprendre que l’essentiel.
Les PICs ne savent qu’ajouter et soustraire des nombres
binaires de 8 bits. en hexa, cela fait des nombres entre
16’00 et 16’FF. On a vu que si on compte, après FF on a
00. La représentation sur un cercle, le cercle des nombres
arithmétiques, va nous être utille.
Mais raisonnons avec un cercle décimal, de 0 à 99, ce qui
permettra de prendre des exemples numériques. Dans
chaque base, les problèmes de dépassement de capacité
de nombres négatifs, de comparaison, sont les mêmes.
Seul le diamètre du cercle change !
Additionnons deux nombres de 2 chiffres. Si le résultat
dépasse la capacité. 100 dans toutes les bases, un report
(carry) est généré.
Ce carry peut vouloir dire qu’il
y quelque chose d’anormal
dans l’application, ou qu’il
faut en tenir compte pour
calculer avec des chiffres
supplémentaires, comme on
verra plus loin.
S’il y a dépassement de
capacité, le bit C (Carry) est
mis à un. Si le résultat est
nul, le bit Z (Zero) est activé.
Pour les tests, on va utiliser le microdule
PotToD8 en série avec un affichage sur le
portA, en se limitant à des valeurs inférieures
à 16’3F, puisqu’il n’y a que 6 bits sur le
portA.
Vérifions avec le programme qui copie A sur
D, le Ex877-201.asm déjà vu. L’interrupteur
sur le PoToD8 doit être en bas.
Additionnons le portA avec une valeur
constante affichée sur le portC. Le résultat
est copié sur le portD. Ex877-210.asm
Comment visualiser le Carry ? Le
programme Ex877-211.asm.affiche sur le
port C le registre Status, qui contient ces
deux bits, carry C en position 0 et Z en
position 2. Oubliez le bit 1 qui va changer
parfois et qui aide les calculs en décimal.
Observez quand on tourne le potentiomètre
et que le total passe de FF à 00 puis 01.
Double précision
Calculer en 16 bits nécessite, comme à la main, d’additionner les poids faibles, de mémoriser le
report et l’ajouter à la somme des poids forts. L’exemple Ex877-212.asm montre de plus que
l’assembleur sait aussi calculer et masquer. Les opérations dans l’assembleur CALM facile à
mémoriser : + - * / .And. .Or. etc (on retrouve le nom des instructions).
Exercice : Fibonacci
La suite de Fibonacci est 1 1 2 3 5 8 13 21 … chaque nouveau nombre est la somme des deux
précédents. Afficher cette suite sur le portD (en hexa .. 8 D 15 …) en s’arrêtant dès qu’il y a
dépassement de capacité. Solution Ex877-220.asm
Complément à 1 et à 2
Le complément à 1 inverse tous les bits, c’est ce que fait l’instruction Not. vue précédemment.
Il ne faut pas confondre avec le complément à 2, ou
complément vrai, résultat de l’opération zéro moins le nombre.
Le figure ci-contre justifie ce terme : 20 est le complément de
80 (en format 2 digits décimal), et ceux qui ont étudié les
logarithmes vont comprendre la suite sans peine : au lieu de
soustraire, on peut additionner le complément.
La figure ci-contre montre qu’au lieu de calculer 40-20,
on peut calculer 40 + (100-20) = 40 + 80.
Cette addition du complément génère un Carry, alors
que la soustraction ne génère pas d’emprunt (borrow).
Contrairement à la majorité des micro-contrôleurs, les
PICs ne soustraient pas, ils ajoutent le complément, et
le carry a la valeur inverse du borrow. C’est tout ce
dont il faut se souvenir si on veut savoir si la
soustraction est possible (a donné un résultat positif).
Le programme Ex877-213.asm effectue les
soustractions 16’10 – (valeur du potentiomètre=0..3F).
Observez C et Z.
Donc, au lieu de soustraire, on peut ajouter le complément. Pour les constantes, l’assembleur sait
calculer les compléments, on a déjà utilisé des
Move #-1,W
au lieu de
Move #16’FF,W
.
On écrit donc souvent pour soustraire une valeur immédiate
Move #-Valeur,W
Add W,Var
calcule Var - #Valeur Var
Move #Valeur,W
Sub W,Var
L’instruction Sub des PICs est inhabituelle. Heureusement CALM (inspiré de Motorola et pas
d’Intel) dit exactement ce que font les instructions arithmétiques. Le 1
e
opérande est soustrait du
2
e
, et le résultat est mis dans le 3
e
opérande, s’il y en a un, autrement dans le 2e.
Les instructions arithmétiques sont les suivantes :
Add #Val,W ; #Val + W W ; pas sur 10F 12F
Add Var,W ; Var + W W
Add W,Var ; W + Var Var
Sub W,#Val,W ; #Val - W W ; pas sur 10F 12F
Sub W,Var,W ; Var - W W
Sub W,Var ; Var - W Var
Nombres négatifs
Encore une complexité à mentionner, mais que nous
n’allons pas analyser. On a placé des nonbres négatifs
sur notre cercle des nombres. Où s’arrêter, comment
savoir si un point sur le cercle est –10 ou F0?
Le processeur ne connaît que des groupes de 8 bits, et
son électronique transforme ces mots sans savoir ce
qu’ils représentent. C’est le programmeur qui décide s’il
travaille avec des nombres positifs de 0 à 16’FF = 255,
ou avec des nombres positifs et négatifs, usuellement
les positifs vont de 0 à 16’7F et les négatifs de
- 1 (= 16’FF) à -16’80 (= 16’80).
La soustraction de deux nombres positifs peut donner un résultat négatif, représenté en
complément à 2. Pour avoir sa valeur absolue, positive, on doit soustraire le résultat de zéro
(prendre son complément à 2)
Clr Temp ; variable temporaire
Sub W,Temp,W ; W 0-W = -W ou –W W
Quand on parlera de vitesse positive et négative d’un moteur, il faudra choisir une représentation
adaptée.
1 / 6 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !