Microcontrôleur PIC
 


1. Introduction

2. Identification

3. Brochage du PIC 16F84

4. Structure interne

5. Instructions

6. Écriture d'un programme pour Pic

7. Les interruptions

8. Watchdog timer

9. Mode sommeil (sleep)

10. Reset

11. Annexe

12. MPLAB

1. Introduction :

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.

2. Identification : 

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.

3. Brochage du PIC16F84A

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. Structure interne

4.1. Schéma bloc


    • 15 registres spéciaux RAM (f) (SFRs : Special Function Registers) adressables de 8 bits (de 0x01 à 0x0B réservés par le Pic);
    •  1 registre virtuel (INDF) à l’adresse 0x00 
    • Une mémoire vive RAM (f) (Random Access Memory) volatile de 68 octets soit 68 registres disponibles pour l’utilisateur  (de l’adresse 0x0C à l’adresse 0x50), dans laquelle sont enregistrées les variables utilisées par le programme pour accélérer l’exécution du programme; 
    • Une mémoire EEPROM (Electrically Erasable programmable Read Only Memory) non volatile de 64 octets. La mémoire EEPROM peut garder un programme pour une période supérieure à 40 ans; 
    • Un registre de travail RAM (W = Working register), non adressable de 8 bits ; 
    • Mémoire ROM (Read Only Memory) dans laquelle sont enregistrées de façon permanente les instructions importantes sur le fonctionnement du microcontrôleur. 
    • Mémoire programme (flash) : elle est effaçable et réinscriptible électriquement, elle n'est pas volatile, le programme n'est pas perdu quand on coupe l’alimentation du montage. 

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é. 

 
    • UAL : C’est l’organe le plus complexe du microprocesseur. L’U.A.L. contient tous les circuits logiques nécessaires aux calculs que celui-ci sait effectuer : 

    - Fonctions logiques : ET, OU, NON, OU Exclusif etc.

    - Fonctions arithmétiques : addition, soustraction etc.

    - Fonctions de traitement particulier : décalage, tests etc. 

    • Le décodeur d’instructions : C’est un bloc logique qui teste les ordres ou instructions arrivant au microprocesseur. Ayant reconnu un ordre, il vient activer le circuit adéquat de l’U.A.L. 
    •   Ports d’entrées/Sorties

- 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.

5. Instructions :

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

Dans la mémoire programme, les instructions sont codées en suites de 0 et de 1, nous, nous préférons écrire des choses comme goto ou clrw, l'assembleur se charge de la traduction. Chaque ligne peut contenir jusqu’à 4 types d’informations appelées champs.

Les quatre champs (ou colonnes) sont: l’étiquette, le mnémonique (OPCODE), l’opérande et le commentaire.

Notez que le mnémonique (l’instruction) et la directive ne peuvent pas se trouver en première colonne.

L'instruction doit commencer en colonne 2. S’il y a une étiquette en colonne 1, il doit y avoir un ou plusieurs espace, deux points ( : ) ou une tabulation avant le mnémonique.

La directive est placée en colonne 2

L’étiquette en début de ligne de programme commence en colonne 1; elle est suivie par un espace, une tabulation, par deux points ( : ) ou par un retour de chariot si elle est seule sur la ligne. Derrière un call ou un goto, elle est en colonne 3.

 Initialisation         

C'est l'opération qui consiste à définir les entrées et les sorties des ports A et B.

 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.

7. Les interruptions

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

La seule chose dont le programme se souvient, après être parti en interruption est l’instruction à laquelle il doit revenir. Il faut donc sauvegarder, dans la routine d’interruption, successivement les registres “W” et “STATUS” sans modifier leur contenu.

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

            __config  _cp_off & _wdt_off & _pwrte_on & _xt_osc

 ;-------------------------------------------------------------------------------------

;  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

 ;  MACRO

        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

                        endc                      ;
;--------------------------------------------------------------------------------------

;  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

 ;  TEMPORISATION DE 390 ms

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"

 dec

        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)

 Valeurintcon0 equ 0x90     ; Masque d'interruption avant l'interruption

    ; 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

 output    macro

        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;


Principe
C’est un système de protection contre un blocage de programme.  Par exemple, si le programme attend le résultat d’un système extérieur (conversion analogique numérique par exemple) et qu’il n’y a pas de réponse, il peut rester bloqué. Pour en sortir, on utilise un chien de garde. Il s’agit d’un compteur qui, lorsqu’il arrive en fin de comptage, permet de redémarrer le programme. Il est lancé au début du programme. En fonctionnement normal, il est remis à zéro régulièrement dans une branche du programme qui s’exécute régulièrement. Si le programme est bloqué, il ne passe plus dans la branche de remise à zéro et le comptage va jusqu’au bout et déclenche le chien de garde qui relance le programme.

- 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

Le chien de garde possède sa propre horloge. Sa période de base est de 18 ms. Le pré-diviseur de fréquence utilisé par le compteur est partagé avec le chien de garde. Si le bit PSA (OPTION_REG, 3) est à 1, le pré-diviseur est assigné au chien de garde. Huit (8) valeurs de 1 à 128 sont disponibles, ce qui permet d’aller jusqu’à 128 x 18 ms = 2.3 s avant le déclenchement du chien de garde.

9. Mode sommeil

   - 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.

10. Reset :

Il y a plusieurs possibilités de Reset :

-  - Reset à l'allumage (POR)

- Reset externe par mise à la masse de l'entrée MCLR

-        - 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. Annexe

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      

        FSR = 0xC2   

ADDWF     FSR, 1

Avant l’instruction

W = 0x17

FSR = 0xC2

Après l’instruction

W = 0xD9

FSR = 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.

 Mots : 1

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

Retour au début

Retour à circuit à microprocesseur

MPLAB

Sommaire

Accueil