Pour programmer un microcontrôleur il est nécessaire de connaître sa structure interne : registres, mémoires, ports d’entrées sorties, et toutes leurs possibilités. Il faut aussi disposer d’un éditeur de texte pour rédiger les programmes, d’un logiciel d’assemblage pour le traduire en langage machine et si possible, d'un simulateur pour mettre son programme au point.
Comme il existe un ensemble faisant tout cela, gratuit de surcroît, autant l’utiliser, c’est MPLAB IDE de chez Microchip.
Il faut enfin un programmateur pour entrer ce programme machine dans le microcontrôleur, c'est USBPICPRG ou MicroPro (WinXP, Vista), MPLAB ICD 2, PICSTART Plus, PICKit 3, PICKit 4 (Windows 7, 8 et 10).
Le PIC 16F84A "Programmable Intelligent Controller", est un microprocesseur avec des fonctionnalités entrées/sorties qui permettent de réaliser des montages avec un minimum de composants externes.
La
valeur courante de l’horloge est de 4 MHz, il existe des
16F84A acceptant une
fréquence maximale de 10 MHz ou 20 MHz. Un 16F84A
de 20 MHz peut
fonctionner à n'importe quelle fréquence
inférieure.
Alimentation conseillée de 2 V à 6 V, consommation moyenne inférieure à 2 mA pour une tension de 5 volts et une fréquence de 4 MHz.
4.1. Schéma bloc
Elle
se
caractérise par le fait que des octets peuvent
être adressés ou lus un par un,
mais que les opérations d'écriture ou de
suppression ne peuvent avoir lieu que
par blocs. Son volume est de 1024 cases mémoires de 14 bits
chacune, ce qui
permet un millier d'instructions pour le programme.
Le
chargement
se fait en série par deux des broches du circuit, l'une
reçoit (ou émet) les
informations, l'autre est utilisée pour l'horloge de
synchronisation du
transfert. La durée de vie de la mémoire flash
est de 1000 cycles
d’effacement/écriture.
Le
code
programme peut être chargé avec une protection
contre la lecture qui interdit
toute recopie; le circuit peut cependant toujours être
effacé et
reprogrammé.
- Fonctions logiques : ET, OU, NON, OU Exclusif etc.
- Fonctions arithmétiques : addition, soustraction
etc.
- Fonctions de traitement particulier : décalage,
tests etc.
-
Le
16F84A comporte deux (2) ports de communication de 13 broches :
- Le port A comporte 5 broches
- Le port B comporte 8 broches
Chaque
broche peut être configurée dans le programme
comme une entrée ou une sortie.
Chaque
sortie peut fournir 20 mA maximum
Chaque entrée peut accepter 25 mA maximum
Mais
le
total des débits du port A ne peut dépasser 80
mA, le total des débits du port
B ne peut dépasser 150 mA.
4.2.
Accès aux registres spéciaux et aux registres RAM
Ces
registres situés aux adresses
allant de 0x00 (b’0000 0000’)0x50 (b’0101
0000’) sont accessibles par deux
banques différentes (BANK0 et BANK1) comme le montre la
figure suivante.
REGISTER FILE MAP - PIC 16F84A
4.3.
Initialisation
L’initialisation
consiste à définir les broches des ports A et B
en entrées ou en sorties
selon l’utilisation qu’on veut en faire.
Les
registres qui nous intéressent pour
l’initialisation sont:
Les
adresses des registres à utiliser doivent être
déclarées au début
du programme.
Pour
accéder à l’une des banques, le choix
se fait par le bit 5 du registre “STATUS”.
Ce bit s’appelle RP0 (Register Bank
Select
Bit).
RP0 = 0
sélectionne Bank 0;
RP0 = 1 sélectionne Bank 1.
Pour
mettre une broche du port B en sortie, on met un 0 dans le bit
correspondant du
registre TRISB => 0 = Output.
Pour
mettre une broche du port B en entrée, on place un 1 dans le
bit correspondant
du registre TRISB => 1 = Input
L’initialisation
du port A est identique à celle du port B. Notez que sur le
même port, on peut
configurer certaines broches en entrée et les autres en
sortie.
Le
PIC
16F84A est un processeur RISC (Reduce Instructions Set Construction),
c'est-à-dire qu'il est doté d'un ensemble
d'instructions réduit (35
instructions), ce qui lui permet d'exécuter chacune d'entre
elles (à
l'exception des sauts), en un seul cycle machine. En fait, le Pic
16F84A
possède 37 instructions mais le constructeur
déconseille d'utiliser OPTION et
TRIS car les programmes ne seraient pas compatibles avec les autres
microcontrôleurs de la série qui n'ont pas ces
deux instructions.
Toutes
les instructions sont codées sur 14 bits. Elles sont
regroupées en trois grands
types :
Les indicateurs
d’état
Tous
les indicateurs sont des bits du registre STATUS.
Le
registre “STATUS” dont l’adresse est
b’0000 0011’ ou b’1000 0011’
est aussi appelé registre
d’état.
Bit 7 : bit
non utilisé avec le 16F84A. Il doit être maintenu
à 0
Bit 6 : bit
non utilisé avec le 16F84A. Il doit être maintenu
à 0
Bit
5 : RP0 (Register
Bank Select Bit)
Sélectionne
la banque à utiliser. Il fonctionne en
lecture/écriture.
- Bit 5 = 0 sélectionne la banque 0 (BANK0)
- Bit 5 = 1 sélectionne la banque 1 (BANK1)
Bit
4 : NOT_TO (Time
Out Bit)
Fonctionne
en lecture seulement
Repère
le dépassement de délai du watchdog
Passe
à 0 après “WDT Time Out”
Bit
3 : NOT_PD (Power
Down Bit)
Fonctionne
en lecture seulement
Passe
1 après “Power On Reset”
Passe
1 après l’instruction “CLRWDT”
Passe
0 après l’instruction “SLEEP”
Bit 2 : Z
(Zero Bit) ou indicateur d’état « Z
»
C’est
l’indicateur Zéro, il fonctionne de la
manière suivante :
Si
le résultat d’une opération pour lequel
il est affecté donne un
résultat égal à 0, le flag
Zéro passe à 1.
Par
contre, si on stocke une valeur avec l’instruction MOVWF, le
bit Z
ne sera pas modifié, même si la valeur vaut 0. Ces
remarques sont valables pour
les autres flags.
Ce
bit fonctionne en lecture/écriture
Z
= 1 si le résultat de l’opération
précédente est 0
Z
= 0 si le résultat de l’opération
précédente est différent de 0
Bit 1 : DC
(Digit Carry)
Fonctionne
en lecture/écriture
DC
= 1 si le résultat de l’opération
précédente crée un
dépassement du
4e bit du résultat (bit 3 dépassant sur
le bit 4).
DC
= 0 si le résultat de l’opération
précédente ne crée pas un
dépassement du 4e bit du résultat.
Bit 0 : C
(Carry) ou indicateur d’état « C
»
C’est
l’indicateur pour Carry (report). Si le résultat
d’une opération
entraîne un débordement, le bit C sera
positionné. Il s’agit en fait du 9e
bit de l’opération. Ce bit est en lecture
/ écriture
Exemple
:
Si
vous ajoutez B’11111110’ (254) +
B’00000011’ (3)
Vous obtenez B’100000001’, (257) dont le 9e bit est C de status è C=1.
6.
Écriture d’un programme pour le PIC
Comme
dans n’importe quel système à
microprocesseur, il est nécessaire
de préparer un programme qui permettra au PIC
d’effectuer son travail.
Un programme est constitué d’une liste
d’instructions en séquence, chacune
d’entre elles identifiant très
précisément la fonction que le PIC est
capable d’effectuer.
Chaque
instruction est représentée par un code
d’opération (OPCODE en
anglais) de 14 bits et est mémorisée
dans une mémoire flash qui contient
1024 emplacements. Chaque OPCODE est
représenté par un mnémonique plus
facile à retenir par l’utilisateur.
Exemple :
l’OPCODE du mnémonique RETURN est : 00
0000 0000
1000 (C’est MPLAB qui convertit
l’instruction en binaire).
La
combinaison des mnémoniques et des nombres en
hexadécimal est le
langage assembleur.
Un
programme en langage assembleur peut être écrit
sur un PC en
utilisant un éditeur de texte capable de
générer des fichiers de type ASCII
(American Standard Code for Information and Interchange). Ce fichier
texte est
appelé fichier source assembleur. Une fois
l’écriture du programme source
assembleur terminée, le fichier doit être
sauvegardé avec l’extension (.ASM).
La
syntaxe utilisée ne doit pas contenir d’accent,
d’espace inutile, de
cédille, de parenthèse etc.
À
la suite d’une ligne d’instructions, le programmeur
peut écrire un
commentaire à la condition qu’il soit
précédé d’un point virgule
(;). Notez que
tout texte après un point virgule sera ignoré par
le programme compilateur. Les
commentaires servent à aider un utilisateur à
comprendre votre démarche, ils ne
sont pas obligatoires mais un bon programmeur les fera toujours.
6.1. Organisation d’un
fichier (.ASM) : on prendra comme exemple le
laboratoire #1
L’identification
Si vous regardez attentivement, vous remarquerez que les deux
premières lignes
sont précédées du symbole (;). Tout ce
qui suit est une zone de commentaires,
vous pouvez y inscrire ce que vous voulez. On utilisera cette zone
comme zone
d’identification dans laquelle on inscrira : le
titre du programme, une
petite description de ce qu’il fait, la date
d’édition, le nom de l’auteur etc.
;
Programme pour le pic 16F84A-04.
; Titre : Lab1
Les directives
Les
directives ne font pas partie du
programme, elles ne sont pas traduites en OPCODE, elles servent
à indiquer à
l’assembleur de quelle manière il doit
travailler. Ce sont donc des
commandes destinées à l’assembleur
lui-même.
La
directive “list”
La
directive “List” en bas de
l’entête est
destinée au compilateur pour lui indiquer quel type de
processeur est utilisé
(ici : PIC16F84A) et les types de messages d’erreur
qui apparaîtront dans
les fichiers *.lst et *.err.
list
p=16f84a, w=2 ; Définition de processeur PIC
16F84A
;
Signaler seulement les erreurs
__config
0x3FF1 ;
Pas de
protection de lecture de la mémoire,
; Oscillateur à cristal, Watchdog à
Off,
Power
;
up timer à On
La
directive « org »
La directive
“org” précise à quelle
adresse
sera placée l’instruction qui suit.
Après un reset ou une mise sous tension, le
PIC démarre toujours à l’adresse 0x00,
c’est donc à cette adresse que doit
débuter votre programme.
L’adresse
“0x04” est réservée pour les
interruptions. Nous devons donc sauter par-dessus vers le
début de notre
programme principal.
La
directive « end »
Cette directive
indique l’endroit où doit
cesser l’assemblage de votre programme. Elle est obligatoire
sinon une erreur
vous signalera que la fin de fichier a été
atteinte sans rencontrer la
directive “end” (End Of File). Les instructions
après la directive “end” sont
tout simplement ignorées.
org 0x00 ; Origine de
départ (adresse
sélectionnée après un
reset)
goto debut ; L'adresse 04 est réservée aux interruptions, il faut donc sauter par dessus
debut
org 0x05
; Origine du programme
après une interruption
L’assignation
ou directive « equ » (equate)
Les lignes
commençant à “portb” et
finissant à
“compteur2” sont des assignations. Elles signalent
à l’assembleur les valeurs
(adresses) de toutes les constantes que nous allons utiliser. Il est en
effet
plus facile de retenir portb que de manipuler la valeur 0x06.
Une assignation
est une simple substitution,
elle associe un nombre à une étiquette. Au moment
de l’assemblage, chaque
assignation rencontrée sera remplacée par sa
valeur.
Si vous
remplacez la valeur d’une assignation,
le changement sera effectif pour tout le programme. Vous ne risquez
donc pas
d’oublier des valeurs en chemin.
portb
equ
0x06
; Adresse du registre portb pour utilisation
trisb
equ
0x86 ;
Adresse du registre trisb pour utilisation
status
equ
0x03 ;
Adresse du registre status pour utilisation
compteur0
equ 0x0c
; Identifie un registre à l'adresse
;
0x0c au nom de
compteur0
compteur1
equ
0x0d ; Identifie un registre
à l'adresse
; 0x0d au nom de
compteur1
compteur2
equ 0x0e
; Identifie un registre à l'adresse
; 0x0e au nom de
compteur2
Le programme principal
bsf
status, 05
clrf trisb
bcf status,
05
clrf portb
On
place un 1 au bit 1 du port B => La
Led branchée à la broche RB1 du PIC
s’allume. On la garde allumée durant 0.5
seconde.
On
met un 0 au bit 1 du port B =>
La
Led sur RB1 est éteinte. On la garde ainsi durant 0.5
seconde puis le cycle
recommence.
Conséquence
: la Led branchée sur RB1 clignote.
boucle
movlw
0x02
; b’0000 0010’
movwf
portb
call pause
movlw
0x00
; b’0000 0000’
movwf
portb
call pause
goto boucle
pause movlw 0x05
;Charge dans l'accumulateur la valeur 05
movwf compteur2
;Transfert w dans le registre
“compteur2”
load1 movlw 0xc8
;Charge l'accumulateur
à c8 (200)
movwf compteur1
;Transfert w dans le
registre “compteur1”
load0 movlw 0xa8
;Charge l'accumulateur
à a8 (168)
movwf compteur0
;Transfert w
dans le registre “compteur0”
dec decfsz compteur0, 1 ;Décrémente le registre “compteur0”,
;saute l'instruction suivante si le
résultat est zéro
goto dec
;Saute
inconditionnellement
à “dec”
;Un cycle
d’instruction utilise quatre périodes
d’horloge
;Décrémente = 1cycle, goto = 2 cycles soit au
total 3 cycles
;ou 3 x 4
périodes d’horloge = 3 x 1 µs = 3
µs
;t = 3 µs x contenu du
registre “compteur0” = 3µs x 168 =
0.5ms
decfsz compteur1,1 ;Décrémente le registre “compteur1”, saute
;l'instruction
suivante si le résultat est zéro
goto load0
;Temps écoulé t
= 3µs x 168 x 200 = 0.1s
decfsz compteur2,1 ;Décrémente le registre “compteur2”, saute
;l'instruction
suivante si le résultat est
zéro
goto load1
;Temps écoulé t = 3µs x 168 x
200 x 5 = 0.5s
;Temporisation=1/2 période=0.5s
return
;Retour
à la ligne suivant
l'appel de
l'étiquette “pause”
end
6.2. Modes
d’adressage : il existe trois grands
types d’accès à une
donnée
ou modes d’adressage.
Exemple :
movlw
0x04 ; mettre le chiffre 4 dans le registre W
Exemple :
movf
boite, 0 ; mettre le contenu du registre "boite"
dans le
registre W
L’accès
au registre dont l’adresse est contenue dans FSR se fait en
utilisant le
registre INDF qui se trouve à l’adresse 0x00 dans
les deux banques. Il ne
s’agit pas d’un registre physique. Il faut le voir
comme un autre nom de FSR,
utilisé pour accéder à la
donnée elle-même, FSR servant à choisir
l’adresse.
Exemple :
On veut transférer le contenu (0xFF) du registre
“Anne” qui se trouve à
l’adresse 0x1B dans le registre “W” en
utilisant l’adressage indirect.
movlw
0x1B
; charge 0x1B dans W
movwf FSR ;
transfert le contenu de W dans FSR soit 0x1B dans
; FSR, le pointeur se place
alors à l’adresse 0x1B et
; transfert son contenu dans le
registre virtuel INDF
movf INDF,0 ; charge le contenu de l’adresse 0x1B dans W
Application
des instructions FSR et INDF
Les registres FSR et INDF
(0x04 et 0x00)
Ces deux registres permettent aux instructions
d’accéder
aux informations qu’elles manipulent par un adressage
indirect.
Pour comprendre le fonctionnement de ces deux registres, on analyse une routine qui permet d’effacer la RAM. À la mise sous tension, la RAM contient des valeurs aléatoires qu’on va supprimer pour éviter des surprises.
La RAM disponible à
l’utilisateur commence à l’adresse
0x0C et finit à l’adresse 0x50.
L’effacement se fera en deux étapes :
0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 |
Effacement
de la RAM
movlw
0x0c
; Initialisation du pointeur (1e
adresse RAM)
movwf
fsr
; Pointeur
d'adressage indirect se place
à l’adresse 0x0C
Init
clrf
indf
; Effacer la ram
à l’adresse pointée par
“FSR”
incf
fsr,f
; Pointer sur suivant (adresse
précédente + 1)
btfss
fsr,6
;
Tester si la fin de zone
est atteinte (=40) Bit 6 du
registre FSR égal à 1
; lorsque son
contenu
est 0x40
soit 64 décimal
goto init
; Non, boucler
btfss
fsr,4
; Tester si la fin de zone
est atteinte (=50) Bit 4 du
registre FSR égal à 1
;
lorsque son
contenu est 0x50 soit 80 décimal
goto
init
; Non,
boucler
clrf indf
; Effacer la ram à
l’adresse 0x50
clrf portb
;
Éteindre toutes les lumières du portb
Explications :
MOVLW 0x0C
MOVWF FSR
Ces deux instructions installent dans le registre
FSR
l’adresse de la première case mémoire
à effacer. Ce registre FSR pointe donc
sur l’adresse du registre à effacer. Le contenu de
cette case mémoire est
transféré dans le registre virtuel INDF.
CLRF INDF
Cette instruction efface la case
mémoire dont l’adresse
se trouve dans le registre FSR. Le registre
INDF (INDIRECT FILE) n’existe pas
physiquement. Ce n’est qu’un
procédé qui
permet d’accéder à l’adresse
pointée
par le registre FSR (il facilite la construction
électronique
interne du PIC).
INCF FSR,
F
Cette instruction incrémente
l’adresse pointée par le
registre FSR soit nouvelle adresse = adresse précédente +1 = 0Ch + 1 =
0Dh (13)
BTFSS FSR, 6
Vérifie si le bit 6 du registre FSR est
égal à 1, ce qui
se produit lorsque l’adresse pointée est 0100 0000
soit 40h (64)
Si c’est le cas alors les cases
mémoires de 0Ch à 3Fh
sont effacées. On saute l’instruction suivante et
on va à :
BTFSS
FSR, 4
On est à l’adresse 0x40 et on
continue à incrémenter le
registre FSR. Cette instruction vérifie si le bit 4 du
registre FSR est égal à
1, ce qui se produit lorsque l’adresse pointée est
0101 0000 soit 50h (80)
Si c’est le cas alors les cases
mémoires de 40h à 4Fh
sont effacées. On saute l’instruction suivante, on
efface la case mémoire 50h
et on continue la suite du programme.
Le registre FSR sert donc à pointer une
adresse et le
registre INDF permet d’y accéder.
Il
y
a quatre (4) sources d'interruption :
a)
Externe par la broche RB0/INT
b)
Par dépassement du registre timer (TMR0)
c)
Par changement d’état des broches 4 à 7
du portb
d)
À
la fin de l’écriture des données dans
l’EEPROM.
Imaginez
une conversation normale :
Pour le PIC, le principe est le même
:
L’interruption est une rupture de séquence asynchrone. Pour la déclencher, il faut que deux conditions principales soient remplies:
7.1.
Principe
Lorsqu’une
interruption est provoquée :
7.2. Registre OPTION_REG (0x81)
C’est un registre de bits où chaque bit a un rôle particulier. Il se trouve à l’adresse 0x81, dans la banque 1. Le contenu de ce registre est :
Bit Value | TMR0 Rate | WDT Rate |
000 | 1:2 | 1:1 |
001 | 1:4 | 1:2 |
010 | 1:8 | 1:4 |
011 | 1:16 | 1:8 |
100 | 1:32 | 1:16 |
101 | 1:64 | 1:32 |
110 | 1:128 | 1:64 |
111 | 1:256 | 1:128 |
Si on ne désire pas utiliser de
prédivision, il faut
mettre le BIT 3 à 1 (Prédivision sur watchdog) et
les BITS 2-0 à 0 ce qui
correspond à une prédivision (1:1) soit pas de
prédivision.
7.3. Registre INTCON (0x0B et 0x8B) : c’est le registre qui gère les interruptions. Son écriture permet de les autoriser ou non et sa lecture de déterminer le type d’interruption qui s’est produite.
Qu’est-ce
que le TIMER0 ?
Le
TIMER0 est en fait un compteur avec lequel :
La
sélection de l’un ou l’autre de ces
modes de fonctionnement se fait par le bit
5 du registre OPTION_REG.
Le
registre TMR0 ne possède que 8 bits, il ne peut donc compter
que jusqu’à 255
(FF). Tout débordement du timer0 (passage de 0xFF
à 0x00) positionne le “flag”
T0IF (bit2) du registre INTCON. On peut donc consulter ce
“flag” pour savoir
s’il y a débordement du timer.
Avec
un quartz de 4 MHz, sachant qu’un cycle
d’instruction dure 4 périodes
d’horloge, nous avons une interruption toutes les 256
µs en mode timer0.
Si
on veut augmenter ce temps, on utilisera un prédiviseur et
des sous routines de
temporisation. Un prédiviseur étant un circuit
diviseur d’événements situé
avant l’entrée de comptage du timer0. Les
divisions de fréquence s’échelonnent
de 2 à 256 (voir les bits 0 à 2 du registre
OPTION_REG).
7.4.
Sauvegarde des registres
Exemple
: interruption du timer0
Nous
allons d’abord définir quelques directives:
Afin
d’éviter l’écriture
d’une multitude de lignes d’assignation au
début de chaque
programme, on peut les regrouper dans un fichier et les appeler par une
seule
commande :
#include “p16f84a.inc”,
#include
<p16f84a.inc> ou #include
p16f84a.inc
Une
définition « #define »
permet de remplacer un texte difficile à
mémoriser par quelque chose de plus simple.
Dans
le programme, on peut par exemple donner le nom
“stat” au bit 5 du registre
status (status,05 = stat). Il faut alors le définir dans le
programme en
utilisant la directive #define.
#define stat
status, 05
Pour
mettre à 1 le bit 5 du registre status, on écrira
alors :
bsf
stat au
lieu de bsf
status, 05
Une
macro remplace un morceau de code que nous utilisons souvent dans le
programme.
Elle fonctionne comme un simple traitement de texte.
Exemple :
Repete macro
movlw
0x00
movwf portb
call
pause
endm
La
macro se compose d’un nom écrit en
première colonne suivi de la directive
“macro”, de une ou plusieurs instructions et de fin
de macro “endm” (end of
macro).
Chaque
fois que le mot “repete” sera rencontré,
il sera remplacé au moment de
l’assemblage par les lignes d’instructions de la
macro soit :
movlw
0x00
movwf
portb
Call pause
Elle permet de définir des registres
mémoire comme avec
la directive equate.
Application
: on prend comme exemple le laboratoire #9
Avec la directive
« LIST », on indique au
compilateur que le microcontrôleur que l’on va
utiliser est le
« PIC16F84A » et que seules les
erreurs seront signalées dans les
fichiers .lst et .err
LIST
P=16F84A, W=2 ;
Définition de
processeur, pas d'avertissement
Afin
d’éviter l’écriture
d’une multitude de lignes d’assignation (adresses
des
différents registres à utiliser) au
début du programme, on les
a regroupé dans un fichier
« P16F84A.INC » qu’on
appellera par la commande : #include
"P16F84A.INC"
#INCLUDE <P16F84A.INC>
;
Définitions des constantes
Avec
la directive « config », on
établit les bits de configuration de la
case mémoire « 2007h »
(type d’oscillateur, fonctionnement du
watchdog, fonctionnement du power up timer, interdiction ou
autorisation de la
lecture de la mémoire programme).
__CONFIG
0x3FF1
;_CP_OFF &
_WDT_OFF & _PWRTE_ON & _XT_OSC.
La variable « VALEUROPTION » sert à stocker le contenu du registre OPTION_REG.
VALEUROPTION EQU
0X82 ;
Valeur registre OPTION_REG
; - Résistances pull-up OFF
; - Préscaler timer à 8
La variable « VALEURINTCON » sert à stocker le contenu du registre INTCON.
VALEURINTCON EQU 0XA0 ; Autorisation des interruptions du
; registre INTCON
; - Interruption générale autorisée GIE=1
; - Interruption TMR0 autorisée INTE=1
La
pause va dépendre de l’interruption du timer0 qui
se produit tous les 256µs, du
prédiviseur fixé à 8 et du
décompte du registre
« TIMEBASE » chargé
avec un nombre de 244. Pause = 256µs x 8 x 244 = 0.5 seconde.
TIMEBASE EQU
244 ;
Base de temps
(temporisation de 0.5 seconde)
Avec
la directive « MACRO », on
insère une instruction
BANK0 MACRO
bcf
STATUS, RP0 ;
Passer en banque0 :
bit 5 du registre STATUS à 0
ENDM
BANK1 MACRO
bsf
STATUS, RP0 ;
Passer en banque1 :
bit 5 du registre STATUS à 1
ENDM
Avec
la directive « CBLOCK », on va
définir les différents registres qu’on
va utiliser comme avec la directive
« EQU ». Ces registres commencent
à l’adresse 0Ch
CBLOCK
0x0C
;
Début de la zone
"variables"
w_temp :1
; Sauvegarde du registre W
status_temp : 1
; Sauvegarde du registre
STATUS
cmpt : 1
; Compteur de passages
ENDC
; Fin de la zone
"variables"
7.5.
Interruption externe (RB0/INT)
L’interruption
se produit sur le front montant ou descendant d’une impulsion
appliquée sur la broche
6 (RB0/INT). Il s’agit du front montant si le bit 6 (INTEDG)
du registre
OPTION_REG est à 1 et d’un front descendant
s’il est à 0.
L’interruption
externe est autorisée si le bit 4 (INTE) du registre INTCON
est à 1
Lorsqu’une
interruption valide a eu lieu, le bit 1 (INTF) du registre INTCON passe
à 1,
pensez donc à le remettre à 0.
Exemple
d’interruption : on veut allumer une
lumière placée sur RA2 à partir
d’un
bouton poussoir (BP) placé sur RB0/INT. (voir figure
suivante)
La
séquence est la suivante :
Dans
notre cas cela correspond à :
7.6. L’anti-rebond
Imaginez
un bouton poussoir géant.
Lorsque
la barre tombe sur les contacts, elle rebondit plusieurs fois. Il y a
donc une
série de fermetures et d’ouvertures du bouton
poussoir. C’est ce que le Pic,
qui est un composant rapide (1 µs par instruction) qui ne
travaille pas à la
même échelle de temps que nous, voit lorsque nous
appuyons sur le bouton
poussoir.
Pour remédier à ce problème, il faut tout simplement attendre un temps supérieur au temps de rebondissement avant d’autoriser une nouvelle interruption sur RB0.
7.7.
Explications
Le
programme principal effectue normalement ses initialisations puis teste
si une
interruption est survenue en vérifiant le
“flag” FINTRB0. S’il n’est pas
à 1,
il boucle sans fin.
Si
le bouton poussoir est appuyé, une interruption est
générée, RA2 est inversé,
la routine d’interruption positionne le
“flag” FINTRB0 à 1 et interdit toute
nouvelle interruption de RB0 (toute autre action sur BP sera sans effet
pour ne
pas prendre en compte les rebonds).
La
routine d’interruption prend fin. Retour au programme
principal qui continue
alors à tester le “flag” FINTRB0 qui
vient d’être positionné par la routine
d’interruption. Appelle de la routine de temporisation
“Attente” dont la durée
est supérieure à celle des rebonds.
Après
écoulement du temps nécessaire à la
fin des rebonds, l’indicateur (flag) INTF
(FINTRB0) du registre “INTCON” est remis
à 0 et les interruptions sont à
nouveau autorisées afin de permettre de prendre en compte
une nouvelle pression
sur le BP.
7.8. Finalisation du programme
;----------------------------------------------------------------------------------
;
Programme pour le pic 16F84A. Ce programme allume une
lumière
;
placée sur RA2 à l'aide d'un bouton poussoir
placé sur RB0/INT
;
Télérupteur version 1
;
Titre : Lab7
;
Remarque : Anti-rebond de 390 ms (temporisation) avec un quartz
;
de
4MHz
;
Fichier requis : p16f84a.inc
;------------------------------------------------------------------------------------
;----------------------------------ENTÊTE---------------------------------------
list
p=16f84a, w=2 ; Définition de
processeur, niveau d’erreur
#include <p16f84a.inc> ; Définition des constantes
; ASSIGNATIONS
ValeurOption equ
0xC0
; Valeur du registre "option"
; Résistances
pull-ups "OFF"
; Interruption
RB0/INT sur front montant
ValeurIntCon equ
0x90
; Masque d'interruption. Autorisation
; générale
d'interruption et permission
; de
l'interruption RB0/INT
;---------------------------------------------------------------------------------------
;
DÉFINITIONS
#define
led porta,
2
; LED de
sortie
#define
FINTRB0
intcon, 1
; Drapeau d'interruption pour
; temporisation contre les rebonds
; du bouton poussoir
bank0
macro
bcf
status, 5
;
Passer en banque0
endm
bank1
macro
bsf
status,
5
;
Passer en banque1
endm
;------------------------------------------------------------------------------------
; DÉCLARATION DE
VARIABLES
cblock
0x0c
; Début de la zone variables
w_temp
:1
;
Emplacement de sauvegarde du registre W
status_temp : 1
; Emplacement de sauvegarde du registre
; STATUS
compteur0 : 1
; Emplacement du compteur
compteur1 : 1
; Emplacement du compteur1
compteur2 : 1
; Emplacement du compteur2
; DÉMARRAGE SUR
RESET
org 0x00
;
Adresse de départ après reset
goto init
;
Aller à l'étiquette "init"
;---------------------------------------------------------------------------------------
; ROUTINE INTERRUPTION
; sauvegarde des registres
org 0x04
;
Adresse d'interruption
movwf
w_temp
;
Sauvegarder le registre W
swapf
status, w
;
Swap status avec résultat dans w
movwf
status_temp
;
Sauvegarder status "swappé«
call BPRB0 ; Traiter l'interruption RB0/INT
; Restauration des registres
swapf
status_temp, w ;
Swap ancien status, résultat dans w
movwf
status
; Restaurer status
swapf
w_temp, f
;
Inversion L et H de l'ancien W sans
;
modifier Z
swapf
w_temp, w
; Réinversion de L et H
dans W
;
W restauré sans modifier status
retfie
; Retour à la
ligne suivant
l'appel d'interruption
;---------------------------------------------------------------------------------------------
; INTERRUPTION RB0/INT
BPRB0
movlw
0x04 ;
Bit à inverser
bank0
;
Passer en banque0
xorwf
porta , f ;
Inverser LED
bcf intcon, inte ; Interdire une autre interruption sur
; RB0/INT
return
; Fin d'interruption
RB0/INT
;-------------------------------------------------------------------------------------
; INITIALISATION
Init
bcf FINTRB0
;
Effacer "flag" FINTRB0
bank1
; Passer en banque1
movlw
0x01
movwf
trisb
;
RB0 en entrée
movlw
0xfb
movwf
trisa
;
RA2 en sortie
movlw
ValeurOption
; Charger masque (pull-ups
;
"OFF" et RBO/INT sur
;
niveau haut)
movwf
option_reg
;
Initialiser le registre "option«
bank0
;
Passer en banque0
movlw
ValeurIntCon
; Masque d'interruption
;
(autorisation des interruptions
;
GIE et INTE)
movwf
intcon
;
Charger le masque dans le registre
;
"INTCON"
; Restauration des registres
swapf
status_temp, w ;
Swap ancien status, résultat dans w
movwf
status
; Restaurer status
swapf
w_temp, f
;
Inversion L et H de l'ancien W sans
;
modifier Z
swapf
w_temp, w
; Réinversion de L et H dans W
;
W restauré sans modifier status
retfie
; Retour
à la ligne suivant
l'appel d'interruption
;-----------------------------------------------------------------------------
; INTERRUPTION RB0/INT
BPRB0
movlw
0x04 ;
Bit à inverser
bank0
;
Passer en banque0
xorwf porta
, f ;
Inverser LED
bcf intcon, inte ; Interdire une autre interruption sur
;
RB0/INT
return
; Fin d'interruption
RB0/INT
; INITIALISATION
Init
bcf FINTRB0
;
Effacer "flag" FINTRB0
bank1
;
Passer en banque1
movlw
0x01
movwf
trisb
;
RB0 en entrée
movlw
0xfb
movwf
trisa
;
RA2 en sortie
movlw
ValeurOption ;
Charger masque (pull-ups
;
"OFF" et RBO/INT sur
;
niveau haut)
movwf
option_reg
;
Initialiser le registre "option«
bank0
;
Passer en banque0
movlw
ValeurIntCon ;
Masque d'interruption
;
(autorisation des interruptions
;
GIE et INTE)
movwf
intcon
;
Charger le masque dans le registre
;
"INTCON"
bcf led
;
Éteindre la Led
goto start
;
Aller au programme principal
;-----------------------------------------------------------------------------
; PROGRAMME PRINCIPAL
start
btfss FINTRB0 ;
Tester si le "flag" FINTRB0 est mis.
;
Si oui sauter la prochaine instruction
;
sinon l’exécuter.
goto start
;
Boucler
call Attente
;
Exécuter la temporisation
bcf FINTRB0
;
Effacer le "flag" FINTRB0
bsf intcon,
inte
;
Remettre RB0/INT en service
goto start
Attente
movlw
0x02
; Charge la valeur 2 dans
l'accumulateur
movwf
compteur2
; Transfert w dans le
registre
;
"compteur2 "
load1
movlw
0xff
;
Charge la valeur ff dans
l'accumulateur
movwf
compteur1
; Transfert w dans le registre
;
"compteur1 "
load0
movlw
0xff
; Charge la
valeur ff dans
;
l'accumulateur
movwf
compteur0
; Transfert w dans le registre
; "compteur0"
decfsz
compteur0, 1 ;
Décrémente le registre "compteur0",
;
saute l'instruction suivante si le
;
résultat est zéro
goto dec
;
Décrémente = 1 cycle, goto = 2 cycles
;
soit au total 3 cycles d’instruction ,
;
t = 3 micro-secondes x contenu du
;
registre "compteur0" = 3µs x 255 =
;
765µs
decfsz
compteur1, 1
; Décrémente le registre
"compteur1 "
goto
load0
; t = 3µs x 255 x 255 = 195ms
decfsz compteur2,
1 ;
Décrémente le registre "compteur2 "
goto
load1
;
t = 3µs x 255 x 255 x 2 = 390
ms
return
;
Retour à la ligne suivant l'appel de
;
l'étiquette "Attente"
end ; Directive fin de programme
7.9.
Utilisation de deux interruptions
Dans
l’exemple suivant, on va utiliser deux interruptions
différentes. Dans notre programme de télérupteur,
on
va remplacer la temporisation par une interruption sur le TIMER0.
La
mise en œuvre du timer0 est visible dans
l’application
suivante :
;--------------------------------------------------------------------------------------
;
Programme pour le pic 16F84A. Ce programme allume une lumière
;
placée sur RA2 à l'aide d'un bouton poussoir
placé sur RB0/INT
avec
;
une interruption sur le timer0
;
Télérupteur version 2
;
Titre : Lab8
;
Remarque : Anti-rebond de 328 ms à l'aide du timer (quartz
de
4MHz)
;
Fichier requis : p16f84a.inc
;----------------------------------------ENTÊTE--------------------------------------
list p=16f84a,
w=2
;
Définition de processeur, niveau
;
d’erreur
#include
<p16f84a.inc> ;
Définition des
constantes
__config _cp_off
& _wdt_off & _pwrte_on & _xt_osc
;-------------------------------------------------------------------------------------------
; ASSIGNATIONS
Valeuroption equ
0xC7 ;
Valeur registre option
; Résistance pull-up "OFF" (Non
RBPU = bit 7 = 0)
;
Interruption RB0/INT sur front montant
;
(INTDG = bit 6 = 0)
Incrémenté en fonction de
;
l’horloge interne
(T0CS = bit5 = 0)
; Utilisation de la
prédivision du timer (PSA = bit 3 = 0)
;
Prédivision du timer
à 256 (PS0, PS1, PS2=bits 0,1 et 2
;
à l’état 1)
; RB0
; Interruption
générale autorisée GIE = bit 7 = 1
; Interruption du
timer interdite T0IE = bit 5 = 0
; Interruption sur
RB0/INT autorisée INTE = bit 4 = 1
Valeurintcon1
equ 0x20
; Masque d'interruption après l'interruption
; RB0
; Interruption INTE
hors service (RB0/INT annulée)
; Interruption TMR0 en
service (T0IE=1)
; "Flag"
INTF remis à 0
Valeurintcon2 equ
0x10
;
Masque d'interruption durant
; l'interruption
Timer0
; Interruption TMR0
interdite
; Interruption RB0/INT
en service
; Flag RB0/INT effacé
; Le « bit" GIE
sera remis par retfie
Passages equ
0x05
;
Nombre de passages dans le registre TMR0
; Temporisation contre
les rebonds du bouton poussoir
; 256 µs x 256 x 5 =328 ms
;----------------------------------------------------------------------------
;
DÉFINITIONS
#define led
porta,2
;
LED placée sur RA2
;----------------------------------------------------------------------------
; MACRO
bank0 macro
bcf
status,5
; Passer en banque0
endm
bank1 macro
bsf
status,5
; Passer en banque1
endm
input
macro
bcf
status,5
movlw
0x01
movwf
trisb
;
RB0 en entrée
bsf
status,5
endm
bcf
status,5
movlw 0xfb
movwf trisa
;
RA2 en sortie
bsf
status,5
endm
;-----------------------------------------------------------------------------
; DÉCLARATION DE
VARIABLES
cblock
0x0c
;
Début de la zone "variables "
w_temp :1
; Sauvegarde du registre W
status_temp : 1
; Sauvegarde du registre STATUS
compteur : 1
;
Compteur de passages dans le
;
registre "TMR0 "
endc
; Fin de la zone
;-----------------------------------------------------------------------------
; DÉMARRAGE SUR
RESET
org 0x00
;
Adresse de départ après reset
goto init
;
Aller à l'étiquette "init"
;----------------------------------------------------------------------------
; ROUTINE INTERRUPTION
; Sauvegarde des registres
org 0x04
;
Adresse de départ de l'interruption
movwf
w_temp
;
Sauvegarder le registre W
swapf
status,w
; Permuter status (low et high) et
;
mettre le résultat dans w
movwf
status_temp ;
Sauvegarder le registre status
;
permuté
; Test
des différentes
interruptions
btfsc
intcon,t0ie
; Tester si l'interruption timer est
;
autorisée. Si 1, aller à l'instruction
;
suivante, sinon la sauter.
btfss
intcon,t0if
;
Tester si l'interruption timer est en
;
cours. Si oui sauter la prochaine
; instruction, si non l'exécuter.
goto
BPRB0
; Aller à l'étiquette intbp
call
Horlogeint ;
Traiter l'interruption par
;
débordement du timer
bcf
intcon,t0if
;
Effacer le "flag" d'interruption du
;
timer
goto
recupreg
;
Aller à récupération des registres
;
sauvegardés
; Restauration des registres
recupreg
swapf
status_temp,w ;
Permuter status_temp et mettre le
;
résultat dans w
movwf
status
;
Restaurer status
swapf
w_temp,f
;
Permuter L et H de w_temp, mettre
;
le résultat dans f sans modifier Z
swapf
w_temp,w
;
Réinversion de L et H, résultat dans w
; w est ainsi
restauré sans modifier
;
status
retfie ; Retour d'interruption
; INTERRUPTION TIMER 0
Horlogeint
decfsz
compteur,f
;
Décrémenter le compteur de passages
;
dans TMR0
return
;
Pas 0, retour au point
d'appel de
;
Horlogeint
movlw
passages
;
Charger w avec le nombre de passages
movwf
compteur
;
Recharger le compteur de passages
movlw
Valeurintercon2 ; Préparation valeur
INTCON
movwf
intcon
;
Interruption TMR0 interdite
;
Interruption RB0/INT en service
; Flag RB0/INT effacé
;
Le « bit" GIE sera remis par retfie
return
; Fin d'interruption timer
;
-------------------------------------------------------------------------------
; INTERRUPTION RB0/INT
BPRB0
;
Traiter l'interruption par RB0/INT
movlw
0x04
;
Préparer pour inversion bit
bank0
; Passer en
banque0
xorwf
porta,f
;
Inverser le niveau logique sur la LED
clrf
tmr0
;
Remise à zéro du timer0
movlw
Valeurintcon1 ;
Préparation pour le registre
;
INTCON
movwf
intcon
;
Interruption INTE hors service
;
(RB0/INT annulée)
;
Interruption TMR0 en service
;
(T0IE=1). "Flag" INTF remis à 0
bcf
intcon,intf
;
Effacer le "flag" de l'interruption
;
RB0/INT
goto
recupreg
; INITIALISATIONS
init
input
; RB0 en
entrée
output
;
RA2 en sortie
clrf
porta
;
Sorties portA à 0
clrf
portb
;
Sorties portB à 0
movlw
Valeuroption
; Charger masque
;
Résistances pull-ups "OFF"
; RB0/INT active sur
niveau haut
;
Signal d'horloge interne
;
TMR0 sélectionné
;
Prédiviseur à 256
movwf
option_reg
;
Initialiser registre option
bank0
; Passer en
banque 0
movlw
passages
;
Charger le nombre de passages
movwf
compteur
;
Charger le compteur de passages
bcf
led
;
Éteindre la LED
movlw Valeurintcon0 ; Masque interruption
;
Interruption générale autorisée
;
Interruption timer interdite
;
Interruption RB0/INT autorisée
movwf
intcon
;
Charger le registre INTCON
goto
start
;
Aller au programme principal
;
----------------------------------------------------------------------------
;
PROGRAMME PRINCIPAL
start
goto
start
;
Boucler
end
; Fin de
programme
Le
fonctionnement de ce programme est explicité par
l’ordinogramme
suivant :
8. Watchdog
timer » ou Chien de garde;
-
Mise en service
Elle
se décide lors de la programmation physique du PIC. Elle ne
peut pas être suspendue pendant
l’exécution d’un programme. Elle est
définitive
jusqu’à une nouvelle programmation de la puce.
La
directive de programmation __config permet de valider ou non
le chien de garde
(option_WDT_ON) ou
(option_WDT_OFF). La mise en service peut aussi être
réalisée directement par
le programmateur. L’inconvénient de cette seconde
solution est que le code du
programme ne contient pas l’information; la mise en service
du chien de garde
peut être oubliée lors du
téléchargement et générer
un fonctionnement incorrect
du programme en cas de blocage.
-
Gestion
Une
fois le chien de garde mis en service, il faut remettre le
comptage à zéro
régulièrement. Cette
opération est réalisée par
l’instruction
CLRWDT (Clear Watchdog).
Tant
que le programme se déroule normalement, cette instruction
est
exécutée régulièrement et
le chien de garde ne s’active pas. Si un blocage
apparaît, la remise à zéro
n’a pas lieu et le chien de garde est activé. Le
PIC
redémarre alors à l’adresse 0000h et le
bit TO (Time out bit) du registre “STATUS”
(status, 4) est mis à 0. Le test de ce bit au
début du programme permet de
savoir si le système vient d’être mis
sous tension (TO=1) ou si le chien de
garde vient de s’activer (TO=0)
-
Choix de la durée
- Principe
Lorsque
le PIC n’a rien à faire (par exemple lors de
l’attente
d’une mesure extérieure), ce mode est
utilisé pour limiter sa
consommation : le PIC est mis en sommeil (le programme
s’arrête) jusqu’à
son réveil (le programme repart).
Ce mode est principalement utilisé pour les systèmes embarqués fonctionnant sur pile.
- Gestion
Mise
en sommeil :
La mise
en sommeil est réalisée grâce
à l’instruction SLEEP. La séquence
suivante est
exécutée :
-
Le chien de garde est remis à 0 (équivalent
à CLRWDT)
-
Le bit TO (Time Out bit) (status, 4) est mis à 1
-
Le bit PD (Power Down bit) (status, 3) est mis à 0
-
L’oscillateur est arrêté ; le PIC
n’exécute plus d’instruction.
Réveil :
ce mode n’est intéressant que si l’on
peut en sortir
pour relancer le programme. Trois événements
permettent de sortir le PIC du
sommeil.
- Application
d’un niveau 0 sur MCLR (broche 4). Le pic effectue alors un
reset et relance le
programme à partir de l’adresse 0000h.
Les
bits NOT_TO (status, 4) et NOT_PD (status, 3) permettent à
l’utilisateur de savoir quel événement
a lancé le programme (mise sous tension,
reset, chien de garde)
-
Activation du chien de garde. Le programme reprend à
l’instruction suivant le SLEEP
-
- Apparition
d’une interruption (RB0/INT, RB4 à RB7 ou EEPROM).
Il faut pour cela que les
bits de validation spécifiques des interruptions
concernées soient positionnés.
Si
le bit de validation générale des interruptions
(GIE) est
à 0
(pas de validation des interruptions), le programme reprend
après l’instruction
SLEEP comme pour le chien de garde. Si le bit de validation
générale des
interruptions (GIE) est à 1 (validation des interruptions),
l’instruction
suivant le SLEEP est exécutée et la fonction
d’interruption liée à
l’événement
qui a réveillé le PIC est
exécutée.
Il
y a plusieurs possibilités de Reset :
- - Reset à l'allumage (POR)
- - Reset après Watchdog
Le
Power-up Timer (PWT) produit un délai de
72 ms à
l'allumage.
L'oscillateur
Start-up Timer (OST) maintient le 16F84A en
position reset jusqu'à ce que l'oscillateur à
quartz se soit stabilisé.
11.1. Les
instructions « orientées octet »
Ce sont des
instructions qui manipulent les données sous forme
d’octets (bytes). Elles sont
codées de la manière suivante :
Exemple:
ADDWF Add W and F soit
additionner les contenus des registres W et F
Syntaxe: [Étiquette]
ADDWF f,
d
Opérande :
0 ≤ f ≤ 127
d = 0 ou 1
Opération:
(W) + (f) => (destination)
Bits de
“status” affectés :
C, DC, Z
Encodage :
00 0111
dfff ffff
fff ffff est
l’adresse du registre F. Il y a au total 80 registres dans la
bank0, donc 7
bits suffisent pour y accéder. Pour accéder aux
adresses de la bank1, un 8e bit
est rajouté, c’est le 5e du registre STATUS.
Description:
Le contenu du registre W est additionné au
contenu du registre F. Si d=0, le résultat est
placé dans le registre W et si
d=1, le résultat est placé dans le registre F
(voir figure de la page
suivante).
Mots : 1
Cycles : 1
Cycle
d’activité (quadrature = 4 cycles
d’horloge): Q1, Q2, Q3, Q4.
Q1 | Q2 | Q3 | Q4 |
Décode l’instruction | Lit le registre F | Traite les données | Écrit dans le registre de destination |
Application
:
ADDWF
FSR, 0
Avant l’instruction
W
= 0x17
FSR
= 0xC2
Après l’instruction
W
= 0xD9
ADDWF
FSR, 1
Avant l’instruction
W = 0x17
FSR = 0xC2
Après l’instruction
W = 0xD9
11.2. Les instructions
« orientées bits »
Ce sont des
instructions destinées à manipuler directement
des bits d’un registre
particulier. Elles sont codées de la manière
suivante :
4 bits pour
l’instruction (dans l’espace resté libre
par les instructions précédentes)
3 bits pour
indiquer le numéro du bit à manipuler (23=8
possibilités,
manipulation des bits 0 à 7)
7 bits pour
indiquer l’opérande.
Exemple :
BCF
Bit Clear f : efface un bit du register
f
Syntaxe: [Étiquette]
BCF f,b
Opérande:
0 ≤ f ≤ 127
0 ≤ b ≤ 7
Opération:
0 => (f<b>)
Bits de
“status” affectés:
Aucun
Encodage:
01 00bb bfff
ffff
Description:
Le bit “b” du registre F est mis
à zéro.
Mots: 1
Cycles: 1
Cycle d’activité (quadrature = 4 cycles d’horloge): Q1, Q2, Q3, Q4.
Q1 | Q2 | Q3 | Q4 |
Décode l’instruction |
Lit le registre F |
Traite les données |
Écrit dans le registrede destination |
11.3. Les
instructions littérales et de contrôle
Les
instructions littérales : ce sont les instructions qui manipulent des
données qui
sont codées dans l’instruction directement. Nous
verrons ceci plus en détail
lorsque nous parlerons des modes d’adressage.
Elles sont codées
de la manière suivante :
L’instruction
est codée sur 6 bits
Elle est suivie
d’une valeur IMMEDIATE codée sur 8 bits (donc de 0
à 255).
Exemple #1:
ADDLW Add
literal and W
Syntaxe: [Étiquette]
ADDLW k
Opérande :
0 ≤ k ≤ 255
Opération:
(W) + k => (W)
Bits de
“status” affectés :
C, DC, Z
Encodage :
11 111x kkkk kkkk
Description:
Le contenu du registre W est additionné aux
8 bits du nombre k, le résultat est placé dans le
registre W
Mots : 1
Cycles : 1
Cycle
d’activité (quadrature = 4 cycles
d’horloge): Q1, Q2, Q3, Q4.
Q1 | Q2 | Q3 | Q4 |
Décode l’instruction |
Lit le registre F |
Traite les données |
Écrit dans le registrede destination |
Exemple #2 :
DECFSZ
Decrement f, Skip if
0
Syntaxe: [
label ]
DECFSZ f,d
Opérande:
0 ≤ f ≤ 127
d : (0 ou1)
Opération:
(f) - 1 => (destination);
skip
if result = 0
Bits de “status”
affectés:
Aucun
Encodage :
00 1011 dfff ffff
Description :
Le contenu du registre F est
décrémenté. Si d=0, le
résultat est placé dans le
registre W et si d=1, le résultat est placé dans
F.
Si le résultat
est différent de zéro, l’instruction
suivante est exécutée mais si le
résultat
est égal à zéro,
l’instruction suivante est ignorée.
Cycles : 1 (2)
Cycle d’activité (quadrature = 4 cycles d’horloge): Q1, Q2, Q3, Q4.
Q1 | Q2 | Q3 | Q4 |
Décode l’instruction |
Lit le registre F |
Traite les données |
Écrit dans le registrede destination |
S’il y a un saut (2e cycle)
Q1 | Q2 | Q3 | Q4 |
Pas d'opération | Pas d'opération | Pas d'opération | Pas d'opération |
Avant l’instruction
COMPTEUR = 240
Après l’instruction
COMPTEUR = COMPTEUR-1 = 240-1 =239
Lorsque le contenu du COMPTEUR
sera nul COMPTEUR = 0, l’instruction suivante est
ignorée, le programme
continuera à s’exécuter à la
ligne « SUITE »
Si COMPTEUR ≠ 0, l’instruction
suivante sera exécutée, le programme retournera
à l’étiquette
« ICI ».
Les
instructions de contrôle : Ce
sont les instructions qui provoquent une rupture dans la
séquence de
déroulement du programme. Elles sont codées de la
manière suivante :
Nous pouvons déjà en
déduire
que les sauts ne donnent accès qu’à 2K
de mémoire programme (211).
Ceci ne pose aucun problème, le 16F84A ne disposant que de
1K mots de mémoire.
Pour coder une adresse de saut à
l’intérieur de la mémoire programme, il
faut
donc : 10 bits (210
=
1024 adresses = 1K).
Exemple :
GOTO
Unconditional
Branch ou Branchement inconditionnel
Syntaxe : [ label ]
GOTO
k
Opérande : 0 ≤ k ≤ 2047
Opération : k =>
PC<10:0>
PCLATH <4:3> =>
PC<12:11>
Bits de “status”
affectés :
Aucun
Encodage : 10 1kkk kkkk kkkk
Description : GOTO est un
branchement inconditionnel. Les 11 bits de la valeur
immédiate sont chargés
dans le PC (compteur de programme) bits <10:0>. Les bits
supérieurs du PC
sont chargés à partir de PCLATH
<4:3>. GOTO utilise deux cycles
d’instruction.
Mots : 1
Cycles : 2
Cycle d’activité (quadrature = 4 cycles d’horloge) : Q1, Q2, Q3, Q4
Q1 | Q2 | Q3 | Q4 | |
Premier cycle |
Décode l’instruction |
Lit le nombre k |
Traite les données |
Écrit dans le PC |
Deuxième cycle |
Pas d’opération |
Pas d’opération |
Pas d’opération |
Pas d’opération |
Application :
GOTO PAUSE
Après
l’instruction, le programme va à
l’adresse PAUSE
PC =
Adresse PAUSE