Utiliser les PIC 16F et 18F/Arithmétique et assembleur
Architecture pour le calcul
modifierPouvoir réaliser un calcul est le minimum que l’on demande à un Microcontrôleur. L'élément de base pour cela est l'UAL : Unité arithmétique et logique.
Unité arithmétique et logique
modifierLe symbole graphique associé à une Unité Arithmétique et Logique est assez caractéristique :
Il présente deux entrées A et B et une sortie R. La sortie R est fonction des deux entrées A et B et d'un code de sélection présent sur l'entrée F. La sortie D met à jour des drapeaux, ce qui sera expliqué plus tard.
Architecture simplifiée de notre PIC
modifierLa décomposition d'un processeur en chemin de données et unité de contrôle est abordée dans un autre projet, et si cela vous intéresse, lisez particulièrement le chapitre 4 et le chapitre 5 (de cet autre projet).
Nous allons donner un schéma du chemin de données qui reprend l’ensemble de ce que l’on a vu jusqu'à maintenant.
Comme on peut le remarquer, la sortie de l’Unité Arithmétique et Logique (ALU) peut être dirigée soit vers l’accumulateur, soit vers le banc de registres (chemins en bleu). Le chemin en rouge représente le fait qu'une partie de l'instruction est utilisée pour positionner correctement la sélection de l'ALU. Les deux chemins bleus désignent quant à eux les deux possibilités quant au cheminement d'un résultat de calcul : soit l’accumulateur W soit le banc de registres ou la mémoire RAM.
Le schéma porte bien son nom, il est simplifié. En effet, il doit être possible de laisser cheminer des données de la mémoire programme vers l'ALU lors d'un adressage immédiat (littéral), ce qui n’est pas présenté.
L'interrupteur de sélection de la sortie de l'ALU est vers le bas pour d=0 (voir les instructions pour la signification de d) ou en adressage immédiat (ou littéral). Il est vers le haut pour d = 1.
Quelques nouvelles instructions
modifierLa série des 16FXXX possède 35 instructions au total. Elles sont présentées en annexe en fin de ce document. Nous commençons par présenter les instructions liées à l'arithmétique.
Rappels sur la représentation des nombres
modifierRelisez l’article sur le système binaire pour commencer.
L’unité centrale connaît trois représentations des nombres :
- Nombres entiers non signés (Unsigned Integer): Un octet peut avoir des valeurs entre 0 et 255 ($FF), un mot entre 0 et 65535 ($FFFF).
- Nombres entiers signés complément à 2 (Two’s complement). Un octet peut avoir des valeurs entre -128 ($80) et +127 ($7F), un mot entre -32768 ($8000) et 32767 ($7FFF). Le bit de poids fort indique toujours le signe.
- Décimal codé binaire (BCD Binary Coded Decimal): Un octet contient deux chiffres décimaux. Les bits 7,6,5,4 contiennent le chiffre de poids fort, les bits 3,2,1,0 contiennent le chiffre de poids faible. Un octet peut donc avoir des valeurs entre 0 ($00) et 99 ($99). Comme beaucoup de micro-contrôleur, le PIC (16F84) gère ce format à travers la demi-retenue (bit DC du registre Status).
Les instructions arithmétiques du 16F84
modifierNous présentons les instructions qui de près ou de loin, ont un rapport avec les calculs arithmétiques.
Opérations arithmétiques | |||||
Mnémonique
Opérande |
Description | Cycles | 14 bits Opcode | status affected | notes |
CLRF f | mise à 0 de f | 1 | 00 0001 1fff ffff | Z | 2 |
INCF f,d | Incrémente f | 1 | 00 1010 dfff ffff | Z | 1,2 |
DECF f,d | Décrémente f | 1 | 00 0011 dfff ffff | Z | 1,2 |
ADDLW k | Addition de W et k | 1 | 11 111x kkkk kkkk | C,DC,Z | |
ADDWF f,d | Additionne W et f | 1 | 00 0111 dfff ffff | C,DC,Z | 1,2 |
SUBLW k | retire W du littéral | 1 | 11 110x kkkk kkkk | C,DC,Z | |
SUBWF f,d | soustrait W de f | 1 | 00 0010 dfff ffff | C,DC,Z | 1,2 |
Sauf spécification contraire, d vaut toujours, au choix :
- 0 la destination est W et le contenu de l’emplacement mémoire n’est pas modifié.
- 1 la destination est f (la lettre f) : dans ce cas le résultat est stocké dans l’emplacement mémoire.
La majorité des processeurs comportent deux instructions d'addition, avec et sans retenue (généralement appelées ADD et ADC). Pour le PIC ce n’est pas le cas. En cas de retenue, il faut utiliser un test et une incrémentation. Voici comment Microchip fait une addition sur 16 bits dans sa note d'application AN526 :
; Double Precision Addition ( ACCb + ACCa -> ACCb )
D_add movf ACCaLO,W
addwf ACCbLO, F ; add lsb
btfsc STATUS,C
incf ACCbHI, F
movf ACCaHI,W
addwf ACCbHI, F
retlw 0
L'instruction de branchement conditionnel btsfc est présentée au chapitre suivant.
Plus loin avec l'assembleur
modifierUn programme commence normalement à l'adresse 0. Mais pour différentes raisons, il se peut que ce ne soit pas le cas.
Les vecteurs
modifier- Après un reset ou un démarrage le PIC (16F84) démarre en adresse 0.
- L'adresse 0x004 étant réservée aux interruptions, un programme aura souvent une structure :
org 0x000 ; Adresse de départ après reset
goto start ; Adresse 0: initialiser
...
org 0x005 ; >=5 ici
start
END
"start" est une étiquette.
On appelle étiquette un nom symbolique destiné à représenter une adresse. L'adresse représentée n’est pas forcément explicite, mais elle peut toujours être calculée d'une manière ou d'une autre. L'assembleur la calculera facilement, mais vous devez pouvoir aussi le faire.
Tout programme se termine par la directive END. Voici un programme complet qui utilise une instruction goto facile à expliquer et présentée dans le chapitre suivant.
; {{Unité|64|octets}} en access RAM
CBLOCK 0x0C ; début de la zone variables sur 16F84
w_temp :1 ; Zone de 1 byte
status_temp : 1 ; zone de 1 byte
mavariable : 1 ; je déclare ma variable
ENDC ; Fin de la zone
org 0x000 ; Adresse de départ après reset
goto start; Adresse 0: initialiser
org 0x005 ; après l'interruption
start
clrf mavariable
boucle
incf mavariable,1 ;incf mavariable,f ->f
goto boucle
END
On distingue dans ce programme deux étiquettes (start et boucle), une définition symbolique des variables, un commentaire et la définition de l'origine du programme.
Règle sur le début de nos programmes
modifierTous nos programmes devront commencer à l'adresse 0x000 mais ne commenceront pas forcément par un "goto start" comme dans cet exemple :
; {{Unité|64|octets}} en access RAM
CBLOCK 0x0C ; début de la zone variables sur 16F84
w_temp :1 ; Zone de 1 byte
status_temp : 1 ; zone de 1 byte
mavariable : 1 ; je déclare ma variable
ENDC ; Fin de la zone
org 0x000 ; Adresse de départ après reset
start
clrf mavariable
boucle
incf mavariable,1 ;incf mavariable,f ->f
goto boucle
END
Introduction aux PIC 18F
modifierTout ce qui a été présenté dans ce chapitre est pratiquement identique pour le PIC 18F. Ce qui change est le modèle mémoire RAM. Les instructions sont identiques mais leurs Opcode sont maintenant sur 16 bits (au lieu de 14). Cela veut dire que vous ne pourrez pas utiliser un fichier hexadécimal (.hex) compilé pour un 16F avec un 18F : il faut ré assembler.
Les banques des 18FXXXX
modifierLa série des 18F dispose de 16 banques sélectionnées par les 4 bits de poids faible du registre BSR. Mais le changement de banque se fait maintenant en une seule instruction :
movlb 0x01; en banque 1
Probablement pour des raisons de compatibilité, l’adressage direct sur plusieurs banques du 16F est encore présent. La terminologie microchip est loin d’être claire à ce sujet : ce qui se passait sur la série des 16F est appelé "banked" et la nouveauté du 18F "access bank". Pour éviter toute confusion dans ce document j'utiliserai "access RAM" pour le nouveau mode d'adressage et "banked "pour l'ancien mode. Le mode "access RAM" permet d’avoir 256 emplacements toujours identiques :
- de l'adresse 0 à l'adresse 0x5F on dispose de cases mémoires (soit 60h=96 cases mémoire)
- de l'adresse 0x60 à 0xFF les registres SFR (de la banque 15)
Tout ceci se traduira par l'apparition d'un a dans les instructions (voir Structure for (boucle avec compteur) du chapitre suivant qui présente deux instructions du 18F)
Le banc de registres
modifierLe banc de registres est très différent de la série 16F. Voici le contenu partiel de ce banc :
Addr | Name | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Value on Power-on Reset |
FFFh | TOSU | - | - | - | TOS<20:16> | ---0 0000 | ||||
FFEh | TOSH | TOS<15:8>
|
0000 0000 | |||||||
FFDh | TOSL | Haut de pile (Top of stack = TOS) : poids faible TOS<7:0> | 0000 0000 | |||||||
FFBh | PCLATU | -
|
-
|
bit21
|
PC<20:16>
|
---0 0000 | ||||
FFAh | PCLATH | PC<15:8>
|
0000 0000 | |||||||
FF9h | PCL | Compteur programme (8 bits de poids faible) PC<7:0> | 0000 0000 | |||||||
FF2h | INTCON | GIE/ GIEH | PEIE/ GIEL | TMR0IE | INT0IE | RBIE | TMR0IF | INT0IF | RBIF | 0000 000x |
FF1h | INTCON2 | /RBPU | INTEDG0 | INTEDG1 | - | - | TMR0IP | - | RBIP | 111- -1-1 |
FF0h | INTCON3 | INT2IP | INT1IP | - | INT2IE | INT1IE | - | INT2IF | INT1IF | 11-0 0-00 |
FE8h | WREG | xxxx xxxx | ||||||||
FD8h | STATUS | - | - | - | N | OV | Z | DC | C | ---x xxxx |
FD7h | TMR0H | TIMER0 <15:8>
|
0000 0000 | |||||||
FD6h | TMR0L | TIMER0 <7:0>
|
xxxx xxxx | |||||||
FD5h | T0CON | TMR0ON | T08Bit | T0CS | T0SE | PSA | T0PS2 | T0PS1 | T0PS0 | 1111 1111 |
FCFh | TMR1H | TIMER1 <15:8>
|
||||||||
FCEh | TMR1L | TIMER1 <7:0>
|
||||||||
F9Eh | PIR1 | SPPIF | ADIF | RCIF | TXIF | SSPIF | CCP1IF | TMR2IF | TMR1IF | |
TRISC | ||||||||||
F93h | TRISB | 1111 1111 | ||||||||
F92h | TRISA | - | -111 1111 | |||||||
F8Ah | LATB | xxxx xxxx | ||||||||
F89h | LATA | - | -xxx xxxx | |||||||
PORTC | RC2/CCP1 | |||||||||
F81h | PORTB | RB7/PGD | RB6/PGC | RB5/PGM | RB4 | RB3/ CANRX | RB2/CANTX/INT2 | RB1/INT1 | RB0/INT0 | xxxx xxxx |
F80h | PORTA | - | RA6/CLKO/OSC2 | RA5/ AN4 | RA4/ TOCKI | RA3/AN3/Vref+ | RA2/AN2/Vref- | RA1/ AN1 | RA0/AN0/CVref | -x0x 0000 |
07h | ---- | Non implémenté | ||||||||
08h | EEDATA | Registre de données EEPROM | xxxx xxxx | |||||||
09h | EEADR | Registre d'adresses EEPROM | xxxx xxxx |
On remarquera la disparition des banques ce qui facilite grandement la programmation.
Faites ces exercices : Arithmétique et assembleur. |