Vous êtes sur la page 1sur 7

ANNEXE : Microcontrôleur PIC Microchip

Un microcontrôleur est un processeur destiné à se suffire lui-même pour la réalisation d’une


application autonome dite « embarquée » : il comporte un processeur, de la mémoire ROM,
de la RAM ainsi qu’un certain nombre de coupleurs de périphériques (liaisons TOR
parallèles, liaison série, timers, convertisseurs A/N et/ou N/A. Il peut également comporter
de la mémoire EEPROM pour maintenir les variables d’états d’une application après une
coupure de l’alimentation électrique. Les dispositifs de mise en veille pour les économies
d’énergie sont de plus en plus présents.
La société Microchip a développé une famille de microcontrôleurs dont l’utilisation est très
répandue et nous allons plus particulièrement nous intéresser au groupe « PIC 16X » qui
correspond au milieu de gamme. « X » est un système de référencement tenant compte des
capacités mémoires RAM/ROM et du nombre de coupleurs de périphérique intégrés. Nous
nous appuierons sur le cas du PIC 1 16f628 dont nous allons donner les caractéristiques
essentielles.
Physiquement, le PIC16f628 se présente sous la forme d’un petit (8×23 mm) circuit intégré
à 18 broches à consommation électrique faible de l’ordre du milliwatt et dont le coût est de
quelques euros. On est aux antipodes des processeurs d’usages généraux que l’on trouve
dans les stations de travail et/ou les serveurs !
Architecture du PIC16f628.
Le PIC16f628 est un processeur 8 bits à jeu réduit d’instructions, (RISC) avec une
organisation de type Harvard au niveau de la mémoire. La mémoire de code est distincte de
celle des données et il y a ainsi deux chemins d’accès (bus) séparés.
La partie processeur est
constituée d’une unité de CODE P C
13 RAM données 8
contrôle servant au
Mémoire
séquencement des Flash
Pile DATA
opérations, au décodage 2048 mots 14b 4 pages
EEPROM
224 registres
d’adresse et à d’autres 14
(8 niveaux)
128 o

services annexes, d’une unité MUX Adressage Indirect


Reg Inst
arithmétique et logique 8 bits Adressage Direct FSR
associée à un unique registre 7 8
de
travail W (Work). Les 8

« codes de conditions » sont MUX mis


à jour dans le registre Décodage Instruction

STATUS. Tous les autres Séquenceur UAL Status


Pipeline (2 étages)
registres du processeur sont Divers : Energie,
de
fait des emplacements Timing, …

particuliers de la RAM. W
L’architecture RISC
implique que toutes les Xtal Horl

instructions ont la même Autres : timers, … USART Port A Port B


taille (ici 14 bits) et leur
exécution se fait en un seul
cycle de 4 périodes d’horloge. Le parallélisme interne est assuré par un pipeline à deux
étages : un étage de recherche d’instruction (phase fetch) et un étage d’exécution. La
                                                            
1
PIC est un nom déposé par Microchip, susceptible de signifier « Peripheral Interface Controller ».
séparation des mémoires de code et de données (Harvard) permet donc d’exécuter
l’instruction n et de procéder à la phase fetch de l’instruction n+1.
Modèle mémoire et registres.
Autour du processeur central, on trouve une mémoire Flash pour le code (2048 mots-
instructions de 14 bits), une EEPROM pour 128 octets de données et une RAM statique se
comportant comme une suite ordonnée de registres de 8 bits (register file2). La RAM est
répartie sur 4 pages (banks) accessibles par un adressage direct sur 7 bits (4 × 128
emplacements possibles) ou un adressage indirect sur 8 bits. Dans ce dernier cas, le registre
FSR (File Select Register) sert de registre d’adresse pointant sur la case mémoire voulue.
Les registres sont de deux types. Les registres GPR (General Purpose Register), au nombre
de 224, sont utilisables comme support de variable au sens de la programmation, ce sont des
registres en RAM et il y en a un certain nombre de disponibles dans chaque page. Dans le
cas du PIC16f628 la page 3 ne comporte pas de mémoire disponible. Les registres SFR
(Special Function Register), que l’on peut aussi appeler ‘Registres Système’, servent à la
fois au processeur (par exemple FSR et STATUS déjà cités, mais aussi le compteur de
programme PCL) et à la programmation des coupleurs d’Entrées-Sorties (adresses et
paramétrage I/O des ports TOR et timers). L’espace mémoire d’entrées-sorties est donc
intégré dans l’espace mémoire de données. Certains registres système sont globaux à toutes
les pages (PC composé de PCL et PCLATH, STATUS, FSR, INTCON), d’autres sont
spécifiques à des pages particulières.

PCL 02h PCL 82h PCL 102h PCL 182h


STATUS 03h STATUS 83h STATUS 103h STATUS 183h
FSR 04h FSR 84h FSR 104h FSR 184h
PORTA 05h TRISA 85h 105h 185h
PORTB 06h TRISB 86h PORTB 106h TRISB 186h

PCLATH 0Ah PCLATH 8Ah PCLATH 10Ah PCLATH 18Ah


INTCON 0Bh INTCON 8Bh INTCON 10Bh INTCON 18Bh

Special Special Special Special


Function Function Function Function
Register Register Register Register

General 20h
General A0h
General 120h

Purpose Purpose Purpose


Register Register Register
96 octets 80 octets 48 octets
libres libres libres 14Fh

EFh

7Fh 1FFh

Bank 0 Bank 1 Bank 2 Bank 3


L’adressage direct est réalisé avec les 7 bits de numéro de registre contenu dans
l’instruction ; la page courante est donnée par les 2 bits de numéros de pages RP0 et RP1 du
registres STATUS.
Dans l’adressage indirect, les 7 bits de registre sont en poids faible des 8 bits du registre
FSR. Le 8ième bit de FSR concaténé avec le bit IRP de STATUS fournit l’accès à la page.
L’adressage à la mémoire de code se fait avec une largeur de 14 bits dont 11 sont utilisés
dans PIC16f628. Le registre PC, compteur de programme, est de fait constitué par deux
                                                            
2
Le terme file est important pour la suite, car dans l’assembleur PIC, l’accès à la RAM est référencée par la
lettre f dans la syntaxe des instructions. RAM et registres du processeurs sont confondus.
registres. PCL fournit les 8 bits de poids faible (accessibles depuis l’UAL), les bits de poids
forts restant sont dans le registre PCLATH. Dans le cas des instructions de branchement
(Goto et Call), 11 bits de l’adresse de débranchement sont fournis directement par le
registre d’instructions, les 2 bits manquants sont donnés par le registre PCLATH
préalablement configuré.
La pile est une zone de mémoire indépendante permettant une profondeur d’empilement de
8 niveaux (c’est une file circulaire : le 9ième élément écrase le 1er et … sans prévenir). Elle
n’est pas manipulable directement et aucune indication n’est donnée sur son état à un instant
donné.

Le jeu d’instructions. ADDWF f, d Add W and f


ANDWF f, d And W with f
Le µC PIC16f628 comporte 35 instructions ayant CLRF f, d Clear f
toutes une longueur de 14 bits. La syntaxe CLRW Clear W
assembleur est du type Op, Src, Dest où OP, code COMF f, d Complement f
opératoire, donne la nature (mnémonique) de DECF f, d Decrement f
l’instruction (move, add, …) et Src et Dest sont les DECFSZ f, d Decrement f Skip if 0
INCF f, d Increment f
paramètres Source et Destination de l’instruction. INCFSZ f, d Increment f Skip if 0
Dans les notations suivantes, f représente un IORWF f, d Inclusive OR W with f
registre en RAM (file), d est un spécificateur de MOVF f, d Move f
destination : si d=0 le résultat est mis dans W, si MOVWF f Move W to f
NOP No Operation
d=1, il est mis dans le registre f spécifié dans
RLF f, d Rotate Left f through Carry
l’instruction, b une position de bit et k une valeur RRF f, d Rotate Right f throuch Carry
immédiate appelée ‘literal’. Il y a quatre types SUBWF f, d Substract W from f
d’instructions. SWAPF f, d Swap nibbles with f
XORWF f, d Exclusive OR W with f
Les instructions orientées ‘octet’ portent sur un
octet. Un bit indique la destination (W, registre de travail ou f registre) et 7 bits l’éventuel
numéro de registre dans la RAM. Dans les exemples de programmes présentés, d sera
directement remplacé par f ou w suivant que la destination est le registre-RAM ou le registre
de travail W.

Les instructions orientées ‘bits’ portent sur la BCF f, b Bit Clear b in f


BSF f, b Bit Set b in f
manipulation d’un bit particulier (codé sur 3 bits) BTFSC f, b Bit Test b in f, Skip if Clear
d’un registre en RAM (codé sur 7 bits). BTFSS f, b Bit Test b in f, Skip if Set

Les instructions à adressage immédiat comportent la valeur immédiate k sur 8 bits dans le
code de l’instruction. Le résultat d’une opération arithmétique est toujours mis dans W.
ADDLW k Add Literal to W
Les instructions de saut ont une destination décrite ANDLW k And Literal with W
sur 11 bits. Il y a les instructions de saut (goto), CALL k Call subroutine
d’appel de procédure (call) et 3 retours de CLRWDT Clear Watchdog Timer
procédure (Retxxx). GOTO k GoTo address f
IORLW k Inclusive OR literal with W
Il n’y a pas vraiment d’instruction de saut MOVLW k Move Literal to W
conditionnel utilisant les drapeaux du registre RETFIE Return from Interrupt
RETLW k Return with Literal in W
d’état STATUS. Une manière de réaliser un RETURN Return from subroutine
‘débranchement’ conditionnel est d’utiliser l’une SLEEP Go into stanby mode
des instructions d’incrémentation et de SUBLW k Sunstract W from Literal
décrémentation d’un registre. Ainsi l’instruction XORLW k Exclusive OR Literal with W
DECFSZ f,d décrémente le registre f et met le résultat dans W ou f (suivant la valeur de d),
incrémente le compteur de programme PC de 1 (passe à l’instruction suivante) si le résultat
est différent de 0 et incrémente PC de 2 dans le cas contraire (saute l’instruction suivante)
test DECFSZ compteur, f ;inst i
(+1) GOTO suite ;inst i+1
(+2) CALL proc1 ;inst i+2 : le résultat valait 0
Suite …

La variable compteur est décrémentée (résultat dans compteur car d=f) et un appel de
procédure est réalisé quand le compteur passe à 0. L’autre manière de procéder passe par
l’utilisation de l’une des deux instructions BTFSx (Bit Test and Skip if x). La structure de saut
est semblable à celle de l’instruction DECFZ : saut de l’instruction suivante si la condition
est vraie.
Exemple de code
Ce code initialise à 0 une table de 8 éléments et utilise pour ce faire l’adressage indirect. La
boucle d’itération est faite sur la base d’une instruction de test de bit.
movlw Table ; @Table mise dans W (reg en RAM)
movwf FSR ; @Table mise dans le registre FSR
movlw huit ; initialise un compteur cpt à 8
movwf cpt ;
iter clrf INDF ; ‘clear’ indirect, adresse dans FSR
incf FSR ; FSR pointe sur l’octet suivant
decfsz cpt,f ; fini les 8 octets ? aller à suite
goto iter ; l’initialisation continue.
suite …

Les deux premières instructions mettent l’adresse de Table dans le registre d’adresse FSR.
L’instruction CLRF INDF est particulière au sens du registre destination INDF. L’opération
‘clear’ porte sur un registre RAM INDF qui n’existe pas (adresse 0) mais qui indique que
l’adressage à utiliser est indirect (INDirect File) avec l’adresse réelle dans FSR. C’est bien
le registre d’adresse FSR qui est ensuite incrémenté pour pointer l’élément suivant. Le
compteur cpt est décrémenté et la sortie de boucle réalisée quand il passe à 0.

Gestion des ports d’entrées sorties.


Le µC PIC16f628 possède deux ports A et B d’entrées sorties, accessibles via les registres
système PORTA et PORTB (adresses 05h et 06h). Chacun de ces ports est constitué d’un
ensemble paramétrable de lignes multifonctions (TOR bidirectionnel, comparateurs
analogiques, horloges, programmation mémoire Flash …). En configuration TOR, le
paramétrage des lignes (RA0-7, RB0-7) en entrée ou en sortie se fait à l’aide des registres
systèmes TRISA et TRISB (Transfert Input Set, adresses 85h et 86h) : un bit à 1 (Input) met
la ligne correspondante du port en entrée, un 0 (Output) la met en sortie. Certaines entrées
TOR peuvent activer une demande d’interruption.
; Exemple d’utilisation du PortB
; on suppose que les lignes sont configurées en TOR
bcf STATUS, RP1 ;
bsf STATUS, RP0 ; sélection page 1 : accès à TRISB
movlw b’11110000’ ;
movwf TRISB ; 4 bits en entrée et 4 bits en sortie
bcf STATUS, RP1 ;
bcf STATUS, RP0 ; sélection page 0 : accès à PORTB
movlw b’00000011’ ; ‘allumez’ 2 bits
movwf PORTB ; de poids faible en sortie de B

Dans l’exemple ci-dessus, on programme le positionnement des broches RB0 et RB1 à 1


(mise au niveau haut, allumer des ampoules LED par exemple). Au départ, on suppose que
les broches du port B sont configurées en mode TOR. Avant d’agir sur les sorties ou de
prendre en compte les entrées, nous allons d’abord configurer le sens d’utilisation de ces
broches. Nous mettons les 4 bits de poids fort en entrée et les 4 de poids faible en sortie en
écrivant la valeur ‘11110000’ dans le registre TRISB (page 1, adresse 86). Puis nous
mettons les deux bits à 11 en écrivant la valeur ‘00000011’ dans le registre PORTB (page 0,
adresse 06). Il est donc nécessaire de changer de page entre les deux commandes.
Pour la lisibilité du code assembleur, on a tout intérêt à définir des macros de changement de
page du type : SELECT_Page_0, SELECT_Page_1 par :
SELECT_Page_0 MACRO
bcf STATUS, RP1 ;
bcf STATUS, RP0 ; sélection page 0
ENDM
SELECT_Page_1 MACRO
bcf STATUS, RP1 ;
bsf STATUS, RP0 ; sélection page 1
ENDM

Les interruptions.
Le µc PIC16f628 autorise 10 sources d’interruptions parmi lesquelles l’interruption externe,
d’usage général, via la broche RB0/INT, les changements de valeur sur les broches RB4-7
du portB, les signaux Tx et Rx de l’USART, et les dépassements (passage de ffh à 00h du
compteur) de temporisateurs (timer).
Si les principes généraux de la gestion des interruptions sont semblables à ceux d’un
processeur classique, il y a quand même pas mal de singularités du point de vue de
l’implémentation technique et donc de la mise en oeuvre au niveau de l’assembleur.
Lors de la prise en compte d’une interruption, le compteur de programme PC est
normalement sauvegardé dans la pile et restitué en sortie de routine d’interruption avec
l’instruction RETFIE. Les interruptions peuvent être masquées soit globalement soit
localement (plus ou moins individuellement) : des bits de configuration sont prévus à cet
effet dans le registre-RAM INTCON (INTerrupt CONfiguration).
Par contre, l’architecture interne implique les particularités suivantes.
Il n’y pas de vecteur d’interruption, donc une seule routine à une adresse fixe (004) et
l’identification de la source d’interruption doit se faire par scrutation. Le temps de latence se
voit ainsi augmenté.
Il n’y a pas de prise en compte d’une interruption pendant le traitement d’une autre : l’entrée
dans la routine d’interruption masque automatiquement les interruptions, le démasquage est
fait par RETFIE. Il n’y a pas d’interruptions logicielles.
Il n’y a pas de hiérarchisation des interruptions par niveau, le traitement des interruptions est
séquentiel (en fifo), éventuellement dans la même routine d’interruption.
Au niveau des sauvegardes du contexte, seul PC est rangé dans la pile. Il est du ressort du
programmeur de faire la sauvegarde du registre de travail W et du registre STATUS (registre
RAM). Mais, la pile n’étant pas accessible à la programmation, ces sauvegardes doivent
nécessairement se faire dans les registres RAM. Or cette sauvegarde est pour le moins
singulière en ce qui concerne STATUS. Il n’existe pas d’instruction de transfert d’un
registre-RAM vers un autre (à part W) sans passer par W. Cela signifie en premier lieu qu’il
faut d’abord obligatoirement sauvegarder le registre W. La sauvegarde de STATUS
implique sa recopie dans W (movf STATUS, w), puis le transfert dans un registre (movwf
svg_ST) que l’on aura affecté à cette destination. Or l’instruction movf de copie de STATUS
dans W, considérée comme une instruction arithmétique (‘mettre’ un résultat dans W)
modifie le drapeau Z de … STATUS et ne peut donc être utilisée. L’ « astuce » consiste
alors à trouver une instruction permettant le transfert d’un registre dans W sans affecter
STATUS. L’instruction swapf fait ce transfert, mais permute (swap) les 2 quartets du
registre. Le registre est ainsi recopié avec cette permutation : à la restauration il faudra bien
penser à faire la permutation inverse.
L’ossature générale d’une routine de traitement d’une interruption avec sa séquence de
sauvegarde-restauration pourra avoir la forme suivante :
CBLOC 0x020 ; début de la zone mémoire pour les données
Svg_W : 1 ; 1 octet pour sauvegarder W
Svg_ST : 1 ; 1 octet pour sauvegarder STATUS
ENDC
ORG 0x004 ; adresse de début de la routine d’interruption
; sauvegarde de W et STATUS
movwf Svg_W ; W est sauvegardé, STATUS intact
swapf STATUS, w ; STATUS ‘permuté’ dans W, STATUS intact
movwf Svg_ST ; STATUS ‘permuté’ sauvegardé dans Svg_ST
; sauvegarde d’éventuels autres registres (FSR par exemple)
bcf STATUS, RP0 ; travailler en page 0 (par exemple)
bcf STATUS, RP1 ; (bits RP0 et RP1 de STATUS mis à 0)

; identification de la source d’interruption


; traitement de l’interruption
; acquittement de l’interruption

; restauration des éventuels autres registes


; restauration de STATUS et W
swapf Svg_ST, w ; Svg_ST ‘permuté’ dans W
movwf STATUS ; Restitution correcte de STATUS
swapf Svg_W, f ; Svg_W recopié ‘permuté’ dans lui-même
; sans casser STATUS ! (pas de
movf)
swapf Svg_W, w ; Svg_W recopié ‘re-permuté’ dans W

retfie ; retour d’interruption

Les bits RP0 et RP1 de STATUS indiquent la page courante de travail : ce numéro de page
est donc ‘hérité’ du programme interrompu et n’est pas forcément la page souhaitée, d’où le
positionnement de ces 2 bits après la séquence de sauvegarde. La page d’origine sera
automatiquement remise en activité par la restauration de STATUS.
Pour rendre la programmation plus lisible, il est évidemment possible de définir deux
macros pour l’ensemble de ces instructions qui reviennent systématiquement dans la routine
d’interruption. On retiendra aussi que les choix architecturaux dans la conception d’un
processeur ont une incidence certaine sur la programmation de celui-ci.
Le µC PIC16f628 prend en compte d’autres formes d’ « interruptions », maintenant
indispensables sur les systèmes embarqués, comme la mise en sommeil et le redémarrage
par chien de garde. Le mode Sleep est une mise en sommeil pour économiser l’énergie dans
le système embarqué. Le processeur est arrêté par suppression de son horloge, il est comme
figé dans le temps et il n’y a pas de sauvegarde particulière à faire. C’est une forme
particulière d’interruption logicielle par l’appel à l’instruction sleep.
Le chien de garde (WatchDog) est un dispositif de veille automatique analogue à celui de
« l'homme mort » qui permet de s'assurer en permanence que le conducteur d’une
locomotive est présent à son poste et conscient. Le conducteur doit effectuer une tâche
périodique (appui d’une manette ou pédale) faute de quoi l’arrêt d’urgence du train se met
en route automatiquement.
Lorsque le Watchdog est activé le programme en cours d’exécution sur le microcontrôleur
doit venir régulièrement remettre à 0 le compteur de temps du chien de garde. S’il arrive à
expiration, le Watchdog provoque la réinitialisation du programme. Cela permet de s’assurer
que le programme ne reste pas bloqué sur une attente infinie ou boucle dans une zone non
prévue. La conception de l’application doit, dès les premiers stades, prendre en compte ce
type de système de sécurité.

Vous aimerez peut-être aussi