PAR BIGONOFF
PREMIERE PARTIE
Rvision 22
2
RVISION 22........................................................................................................................................................ 1
1. INTRODUCTION............................................................................................................................................. 9
3
8. LA SIMULATION DUN PROGRAMME................................................................................................... 47
8.1 LANCEMENT ET PARAMTRAGE DU SIMULATEUR......................................................................................... 47
8.2 EXPLICATION DES REGISTRES FONDAMENTAUX ........................................................................................... 49
8.2.1 Les registres PCL et PCLATH ................................................................................................. 49
8.2.2 Le registre W .................................................................................................................................. 50
8.2.3 Le registre STATUS ........................................................................................................................ 50
8.3 LANCEMENT DE LA SIMULATION .................................................................................................................. 51
9. LE JEU DINSTRUCTIONS ......................................................................................................................... 57
9.1 LINSTRUCTION GOTO (ALLER )......................................................................................................... 57
9.2 LINSTRUCTION INCF (INCREMENT FILE) ............................................................................................ 58
9.3 LINSTRUCTION DECF (DECREMENT FILE).......................................................................................... 59
9.4 LINSTRUCTION MOVLW (MOVE LITERAL TO W) .............................................................................. 59
9.5 LINSTRUCTION MOVF (MOVE FILE)................................................................................................... 59
9.6 LINSTRUCTION MOVWF (MOVE W TO FILE)........................................................................................ 61
9.7 LINSTRUCTION ADDLW (ADD LITERAL AND W)............................................................................... 61
9.8 LINSTRUCTION ADDWF (ADD W AND F) .......................................................................................... 61
9.9 LINSTRUCTION SUBLW (SUBTRACT W FROM LITERAL) .................................................................... 62
9.10 LINSTRUCTION SUBWF (SUBTRACT W FROM F).............................................................................. 64
9.11 LINSTRUCTION ANDLW (AND LITERAL WITH W) ........................................................................... 64
9.12 LINSTRUCTION ANDWF (AND W WITH F) ....................................................................................... 65
9.13 LINSTRUCTION IORLW (INCLUSIVE OR LITERAL WITH W)............................................................... 65
9.14 LINSTRUCTION IORWF (INCLUSIVE OR W WITH FILE) ..................................................................... 66
9.15 LINSTRUCTION XORLW (EXCLUSIVE OR LITERAL WITH W)........................................................... 66
9.16 LINSTRUCTION XORWF (EXCLUSIVE OR W WITH F) ....................................................................... 67
9.17 LINSTRUCTION BSF (BIT SET F)......................................................................................................... 67
9.18 LINSTRUCTION BCF (BIT CLEAR F) ................................................................................................... 68
9.19 LINSTRUCTION RLF ( ROTATE LEFT THROUGH CARRY) .................................................................... 68
9.20 LINSTRUCTION RRF ( ROTATE RIGHT THROUGH CARRY) .................................................................. 69
9.21 LINSTRUCTION BTFSC (BIT TEST F, SKIP IF CLEAR) ......................................................................... 70
9.22 LINSTRUCTION BTFSS (BIT TEST F, SKIP IF SET) .............................................................................. 71
9.23 LINSTRUCTION DECFSZ (DECREMENT F, SKIP IF Z) ........................................................................ 72
9.24 LINSTRUCTION INCFSZ (INCREMENT F, SKIP IF ZERO) .................................................................... 73
9.25 LINSTRUCTION SWAPF (SWAP NIBBLES IN F).................................................................................. 73
9.26 LINSTRUCTION CALL (CALL SUBROUTINE) ..................................................................................... 73
9.27 LINSTRUCTION RETURN (RETURN FROM SUBROUTINE)................................................................. 74
9.28 LINSTRUCTION RETLW (RETURN WITH LITERAL IN W) ................................................................... 77
9.29 LINSTRUCTION RETFIE (RETURN FROM INTERRUPT) ...................................................................... 77
9.30 LINSTRUCTION CLRF (CLEAR F) ...................................................................................................... 78
9.31 LINSTRUCTION CLRW (CLEAR W) ................................................................................................... 78
9.32 LINSTRUCTION CLRWDT (CLEAR WATCHDOG).............................................................................. 78
9.33 LINSTRUCTION COMF (COMPLEMENT F) ......................................................................................... 79
9.34 LINSTRUCTION SLEEP (MISE EN SOMMEIL)....................................................................................... 79
9. 35 LINSTRUCTION NOP (NO OPERATION).............................................................................................. 80
9.36 LES INSTRUCTIONS OBSOLTES .................................................................................................................. 80
10. LES MODES DADRESSAGE .................................................................................................................... 81
10.1 LADRESSAGE LITTRAL OU IMMDIAT ...................................................................................................... 81
10.2 LADRESSAGE DIRECT ................................................................................................................................ 81
10.3 LADRESSAGE INDIRECT ............................................................................................................................ 81
10.3.1 Les registres FSR et INDF ................................................................................................................. 82
10.4 QUELQUES EXEMPLES ................................................................................................................................ 83
11. RALISATION DUN PROGRAMME EMBARQU ............................................................................. 85
11.1 LE MATRIEL NCESSAIRE ......................................................................................................................... 85
11.2 MONTAGE DE LA PLATINE DESSAIS ........................................................................................................... 85
11.3 CRATION DU PROJET ................................................................................................................................ 86
11.4 EDITION DU FICHIER SOURCE ..................................................................................................................... 87
11.5 CHOIX DE LA CONFIGURATION ................................................................................................................... 87
11.6 LE REGISTRE OPTION............................................................................................................................... 88
4
11.7 EDITION DU PROGRAMME........................................................................................................................... 90
11.8 LE REGISTRE PORTA ................................................................................................................................ 92
11.8.1 Fonctionnement particulier des PORTS............................................................................................. 93
11.9 LE REGISTRE TRISA.................................................................................................................................. 94
11.10 LES REGISTRES PORTB ET TRISB .......................................................................................................... 95
11.11 EXEMPLE DAPPLICATION ........................................................................................................................ 95
11.12 LA ROUTINE DINITIALISATION ................................................................................................................ 96
11.13 LES RSULTATS DE LA COMPILATION ....................................................................................................... 99
11.14 LE PROGRAMME PRINCIPAL .................................................................................................................... 100
11.15 LA SOUS-ROUTINE DE TEMPORISATION .................................................................................................. 100
12. LES INTERRUPTIONS............................................................................................................................. 107
12.1 QUEST-CE QUUNE INTERRUPTION ? ...................................................................................................... 107
12.2 MCANISME GNRAL DUNE INTERRUPTION .......................................................................................... 107
12.3 MCANISME DINTERRUPTION SUR LES PICS ........................................................................................... 108
12.4 LES SOURCES DINTERRUPTIONS DU 16F84.............................................................................................. 110
12.5 LES DISPOSITIFS MIS EN UVRE ............................................................................................................... 110
12.6 LE REGISTRE INTCON (INTERRUPT CONTROL) .................................................................................... 112
12.7 SAUVEGARDE ET RESTAURATION DE LENVIRONNEMENT ........................................................................ 113
12.7.1 Les registres sauvegarder ............................................................................................................. 114
12.7.2 La mthode de sauvegarde............................................................................................................... 114
12.7.3 Particularit de linstruction RETFIE ....................................................................................... 116
12.8 UTILISATION DUNE ROUTINE DINTERRUPTION ....................................................................................... 117
12.9 ANALYSE DE LA ROUTINE DINTERRUPTION ............................................................................................. 119
12.10 ADAPTATION DE LA ROUTINE DINTERRUPTION ..................................................................................... 122
12.11 LINITIALISATION .................................................................................................................................. 123
12.12 CONSTRUCTION DU PROGRAMME PRINCIPAL .......................................................................................... 124
12.13 CONSTRUCTION DE LA ROUTINE DINTERRUPTION ................................................................................. 125
12.14 PASSAGE AU SIMULATEUR DUNE ROUTINE DINTERRUPTION ................................................................ 126
12.15 PREMIRE CORRECTION : RESET DU FLAG ............................................................................................. 129
12.16 SE METTRE LCHELLE DE TEMPS DU PIC ........................................................................................... 130
12.17 LE PROBLME DE LANTI-REBOND ......................................................................................................... 130
12.18 FINALISATION DU PROGRAMME ............................................................................................................. 131
12.19 REMARQUES IMPORTANTES ................................................................................................................... 134
12.20 CONCLUSIONS ........................................................................................................................................ 135
13. LE TIMER 0................................................................................................................................................ 136
13.1 LES DIFFRENTS MODES DE FONCTIONNEMENT ........................................................................................ 136
13.2 LE REGISTRE TMR0................................................................................................................................... 136
13.3 LES MTHODES DUTILISATION DU TIMER0 ............................................................................................. 136
13.3.1 Le mode de lecture simple................................................................................................................ 137
13.3.2 Le mode de scrutation du flag .......................................................................................................... 137
13.3.3 Le mode dinterruption .................................................................................................................... 138
13.3.4 Les mthodes combines .................................................................................................................. 138
13.4 LE PRDIVISEUR ....................................................................................................................................... 138
13.5 APPLICATION PRATIQUE DU TIMER0......................................................................................................... 140
13.5.1 Prparations..................................................................................................................................... 140
13.5.2 Linitialisation.................................................................................................................................. 141
13.5.3 La routine dinterruption ................................................................................................................. 142
13.6 MODIFICATION DES REGISTRES DANS LE SIMULATEUR ............................................................................. 143
13.7 MISE EN PLACE SUR LA PLATINE DESSAIS ............................................................................................... 144
13.8 PREMIRE AMLIORATION DE LA PRCISION ............................................................................................ 145
13.9 SECONDE AMLIORATION DE LA PRCISION ............................................................................................. 145
13.10 LA BONNE MTHODE - ADAPTATION DE LHORLOGE ............................................................................ 146
13.11 LA MTHODE DE LUXE : LA DOUBLE HORLOGE ...................................................................................... 147
13.12 EXEMPLE DUTILISATION DE 2 INTERRUPTIONS ..................................................................................... 147
13.13 CONCLUSION.......................................................................................................................................... 148
14. LES ACCS EN MMOIRE EEPROM ............................................................................................ 149
14.1 TAILLE ET LOCALISATION DE LA MMOIRE EEPROM ........................................................................... 149
5
14.2 PRPARATION DU PROGRAMME................................................................................................................ 149
14.3 INITIALISATION DE LA ZONE EEPROM ....................................................................................................... 151
14.4 LE REGISTRE EEDATA ........................................................................................................................... 152
14.5 LE REGISTRE EEADR .............................................................................................................................. 153
14.6 LE REGISTRE EECON1 ............................................................................................................................ 153
14.7 LE REGISTRE EECON2 ............................................................................................................................ 154
14.8 ACCS EN LECTURE DANS LA MMOIRE EEPROM ................................................................................ 154
14.9 LACCS EN CRITURE LA ZONE EEPROM .............................................................................................. 155
14.10 UTILISATION PRATIQUE DE LA MMOIRE EEPROM ............................................................................ 157
14.11 SCURISATION DES ACCS EN MMOIRE EEPROM ............................................................................. 160
14.12 CONCLUSION.......................................................................................................................................... 160
15. LE WATCHDOG........................................................................................................................................ 161
15.1 LE PRINCIPE DE FONCTIONNEMENT .......................................................................................................... 161
15.2 LE PRDIVISEUR ET LE WATCHDOG .......................................................................................................... 161
15.3 LES RLES DU WATCHDOG ....................................................................................................................... 162
15.4 UTILISATION CORRECTE DU WATCHDOG .................................................................................................. 162
15.5 CE QUIL NE FAUT PAS FAIRE.................................................................................................................... 162
15.6 MESURE DU TEMPS REL DU WATCHDOG ................................................................................................. 163
15.7 SIMULATION DU PLANTAGE DUN PROGRAMME ....................................................................................... 164
15.7.1 Correction avec utilisation du watchdog ......................................................................................... 165
15.8 CHOIX DE LA VALEUR DU PRDIVISEUR ................................................................................................... 166
15.9 TEMPS TYPIQUE, MINIMAL, ET MAXIMUM ................................................................................................ 167
15.10 CONCLUSION.......................................................................................................................................... 167
16. LE MODE SLEEP ...................................................................................................................................... 169
16.1 PRINCIPE DE FONCTIONNEMENT ............................................................................................................... 169
16.2 LA SORTIE DU MODE SLEEP ................................................................................................................ 169
16.3 RVEIL AVEC GIE HORS SERVICE. ........................................................................................................... 170
16.4 RVEIL AVEC GIE EN SERVICE................................................................................................................. 170
16.5 MISE EN SOMMEIL IMPOSSIBLE ................................................................................................................ 170
16.6 UTILISATION DU MODE SLEEP ............................................................................................................ 171
REMARQUE ...................................................................................................................................................... 171
16.7 CAS TYPIQUES DUTILISATION ................................................................................................................. 172
16.7 POUR UNE CONSOMMATION MINIMALE .................................................................................................... 172
16.8 CONCLUSION............................................................................................................................................ 172
17. LE RESTE DU DATASHEET ................................................................................................................... 173
17.1 LA STRUCTURE INTERNE .......................................................................................................................... 173
17.2 LA SQUENCE DE DCODAGE ................................................................................................................... 173
17.3 ORGANISATION DE LA MMOIRE .............................................................................................................. 173
17.4 LES REGISTRES SPCIAUX ........................................................................................................................ 174
17.5 LLECTRONIQUE DES PORTS ................................................................................................................... 174
17.6 LE REGISTRE DE CONFIGURATION ............................................................................................................ 174
17.7 LES DIFFRENTS TYPES DOSCILLATEURS ................................................................................................ 175
17.7.1 La prcision de loscillateur ............................................................................................................ 176
17.8 LE RESET .................................................................................................................................................. 177
17.9 LA MISE SOUS TENSION ............................................................................................................................ 178
17.10 CARACTRISTIQUES LECTRIQUES ......................................................................................................... 179
17.11 PORTABILIT DES PROGRAMMES ............................................................................................................ 179
17.12 LES MISES JOUR DES COMPOSANTS...................................................................................................... 180
17.13 CONCLUSION.......................................................................................................................................... 181
18. ASTUCES DE PROGRAMMATION ....................................................................................................... 183
18.1 LES COMPARAISONS ................................................................................................................................. 183
18.2 SOUSTRAIRE UNE VALEUR DE W ............................................................................................................... 183
18.3 LES MULTIPLICATIONS ............................................................................................................................. 184
18.4 MULTIPLICATION PAR UNE CONSTANTE ................................................................................................... 186
18.5 ADRESSAGE INDIRECT POINTANT SUR 2 ZONES DIFFRENTES .................................................................. 187
18.6 LES TABLEAUX EN MMOIRE PROGRAMME .............................................................................................. 188
6
18.7 LES VARIABLES LOCALES ......................................................................................................................... 192
18.7.1 Dtermination des variables locales ................................................................................................ 193
18.7.2 Construction sans variables locales................................................................................................ 193
18.7.3 Construction avec variables locales................................................................................................. 193
18.8 DIVISION PAR UNE CONSTANTE ................................................................................................................ 194
18.9 CONCLUSION............................................................................................................................................ 194
19. LA NORME ISO 7816 ................................................................................................................................ 195
19.1 SPCIFICITS UTILES DE LA NORME ISO 7816.......................................................................................... 195
19.1.1 Les commandes ISO 7816 ................................................................................................................ 195
19.1.2 Le protocole dchange dinformations ........................................................................................... 196
19.2 LES LIAISONS SRIE ASYNCHRONES ......................................................................................................... 197
19.2.1 Le start-bit........................................................................................................................................ 198
19.2.2 Les bits de donnes........................................................................................................................... 198
19.2.3 Le bit de parit ................................................................................................................................ 198
19.2.4 Le stop-bit ........................................................................................................................................ 198
19.2.5 Vitesse et dbit.................................................................................................................................. 199
19.3 ACQUISITION DES BITS ............................................................................................................................. 199
19.4 CARACTRISTIQUE DES CARTES STANDARD ....................................................................................... 200
19.5 CRATION ET INITIALISATION DU PROJET ................................................................................................. 200
19.6 LA BASE DE TEMPS ................................................................................................................................... 202
19.7 RCEPTION DUN OCTET........................................................................................................................... 203
19.8 LMISSION DUN CARACTRE ................................................................................................................. 204
19.9 INITIALISATION ........................................................................................................................................ 207
19.10 ENVOI DE LATR ................................................................................................................................... 207
19.11 LENVOI DU STATUS ............................................................................................................................... 208
19.12 RCEPTION DE LA CLASSE ...................................................................................................................... 209
19.13 RCEPTION DE INS, P1, P2, ET LEN...................................................................................................... 209
19.14 CONTRLE DE LINSTRUCTION REUE.................................................................................................... 210
19.15 TRAITEMENT DUNE INSTRUCTION ......................................................................................................... 211
19.16 LES VARIABLES ...................................................................................................................................... 211
19.17 CONCLUSION.......................................................................................................................................... 212
ANNEXE1 : QUESTIONS FRQUEMMENT POSES (F.A.Q.)............................................................... 213
A1.1 JE TROUVE QUE 8 SOUS-PROGRAMMES, CEST PEU .................................................................................. 213
A1.2 JE NUTILISE QUE 8 IMBRICATIONS, ET POURTANT MON PROGRAMME PLANTE........................................ 213
A1.3 MON PROGRAMME SEMBLE NE JAMAIS SORTIR DES INTERRUPTIONS ....................................................... 213
A1.4 JE NARRIVE PAS UTILISER LE SIMULATEUR, LES OPTIONS NAPPARAISSENT PAS ................................. 213
A1.5 JE REOIS UN MESSAGE DERREUR EOF AVANT INSTRUCTION END....................................................... 213
A1.6 COMMENT DSASSEMBLER UN FICHIER .HEX ? .................................................................................. 214
A1.7 UTILISATION DES MINUSCULES ET DES MAJUSCULES............................................................................... 214
A1.8 LE CHOIX DUN PROGRAMMATEUR.......................................................................................................... 214
A1.9 JAI UNE ERREUR DE STACK ............................................................................................................... 215
A1.10 QUELLES SONT LES DIFFRENCES ENTRE 16F84 ET 16F84A ? .............................................................. 216
A1.11 JAI UNE ERREUR 173 LORS DE LASSEMBLAGE ..................................................................................... 216
CONTRIBUTION SUR BASE VOLONTAIRE ............................................................................................ 217
7
8
1. Introduction
Et voil, nous sommes partis ensemble pour cette grande aventure quest la
programmation des pics. Je vais tenter de rester le plus concret possible, mais, cependant, une
certaine part de thorie est indispensable pour arriver au but recherch.
Je vais donc commencer ce petit cours par un rappel sur les systmes de numrotation. Ca
y est, jen vois qui rlent dj. Mais je suis sr que vous comprendrez quil est impossible de
programmer srieusement un microcontrleur sans savoir ce quest un bit, ou comment
convertir les notations dcimales en hexadcimales.
Rassurez-vous, je vais faire bref, et nous pourrons trs rapidement aborder le sujet qui
nous intresse tant. Si vous tes dj un pro , vous pouvez sauter le premier chapitre et
passer directement au suivant.
Nhsitez jamais me faire part de vos remarques, ni me signaler les erreurs qui
mauraient chappes (www.abcelectronique.com/bigonoff ou www.bigonoff.org ). Faites du
copier/coller, rpercutez les infos que vous trouverez ici, traduisez le document dans une autre
langue ou un autre format. Simplement, dans ce cas, veuillez respecter les dsirs de lauteur
en fin douvrage et faites moi parvenir un exemplaire de votre travail. Ceci pour permettre
den faire profiter le plus grand nombre (bigocours@hotmail.com).
Jattire votre attention sur le fait que ce cours, pour tre efficace, doit tre lu tout en
ralisant les exercices que je vous propose. Les solutions des exercices sont disponibles sous
forme de fichiers exemples fournis en annexe de ce cours.
Tout ce quil vous faudra, cest un 16F84, un quartz de 4MHz, une petite platine dessais,
une LED, un bouton poussoir et le logiciel MPLAB, mis gracieusement votre disposition
par la socit Microchip ladresse http://www.microchip.com. A cette mme adresse, vous
pourrez vous procurer le datasheet du 16F84.
Jai pass de nombreuses journes raliser ces exercices. Je les ai personnellement tests
sur maquette un par un. Alors je vous demanderai de tenter de faire vous-mme ces petits
programmes avant de me poser par email des questions dont vous auriez eu les rponses si
vous aviez ralis cet effort. Croyez-moi sur parole, ce nest quau moment de mettre en
pratique quon saperoit quon navait finalement pas bien compris quelque chose qui
paraissait pourtant vident. Je rponds toujours au courrier reu, mais il faut dire que cest
parfois lgrement nervant de recevoir une question de quelquun qui affirme avoir assimil
la totalit de cet ouvrage en une heure. Ca mest arriv !
9
10
2. Les systmes de numrotation
2.1 Le systme dcimal
Nous sommes habitus, depuis notre enfance utiliser le systme numrique dcimal, tel
point que nous ne voyons mme plus la manire donc ce systme fonctionne, tant cest
devenu un automatisme.
Dcimal, pourquoi ? Parce quil utilise une numrotation 10 chiffres. Nous dirons que
cest un systme en BASE 10. Pour la petite histoire, on a utilis un systme base 10 car nos
anctres ont commenc compter sur leurs 10 doigts, pas besoin daller chercher plus loin.
Mais la position des chiffres a galement une grande importance. Les chiffres les moins
significatifs se situent droite du nombre, et leur importance augmente au fur et mesure du
dplacement vers la gauche. En effet, dans le nombre 502, le 5 a une plus grande importance
que le 2. En ralit, chaque chiffre, que lon peut appeler DIGIT, a une valeur qui dpend de
son RANG . Quel est le multiplicateur appliquer un chiffre en fonction de sa position
(rang) ? Il sagit tout simplement de llvation de la BASE utilise la puissance de son
RANG .
Cela a lair complexe crire, mais est trs simple comprendre. Lorsque vous avez
compris ceci, vous comprenez automatiquement nimporte quel systme de numrotation.
Reprenons, par exemple notre nombre 502. Que signifie le 2 ? Et bien, tout simplement
que sa valeur est gale 2 multipli par la base (10) leve la puissance du rang du chiffre,
cest dire 0.
Remarquez ici une chose trs importante : le comptage du rang seffectue toujours de
droite gauche et en commenant par 0. Pour notre nombre 502, sa valeur est donc en ralit :
502 = 2*10 + 0*101 + 5*10. Notez que le symbole * est utilis pour indiquer multipli .
Et rappelez-vous que 10 = (10/10) = 1, que 101 = 10, et que 10 = 10*10 = 100 etc.
Vous avez compris ce qui prcde ? Alors la suite va vous paratre simple. Cela ne pose
aucun problme pour vous de compter sur vos 10 doigts, mais pour les ordinateurs, cela nest
pas si simple. Ils ne savent faire la distinction quentre 2 niveaux (prsence ou absence de
tension). Le systme de numrotation dcimal est donc inadapt.
On comprendra immdiatement que le seul systme adapt est donc un systme en base 2,
appel systme binaire. Ce systme ne comporte donc que 2 chiffres, savoir 0 et 1. Comme,
de plus, les premiers ordinateurs (et les pics) travaillent avec des nombres de 8 chiffres
binaires, on a donc appel ces nombres des octets (ou bytes en anglais). Le chiffre 0 ou 1 est
appel un BIT(unit binaire, ou BInary uniT) .
Pour nous y retrouver dans la suite de ce petit ouvrage, on adoptera les conventions
suivantes : tout nombre dcimal est crit tel quel, ou en utilisant la notation Dxxx ; tout
nombre binaire est crit suivant la forme Bxxxxxxxx dans lesquels les x valent ? 0 ou 1
effectivement, vous avez bien suivi.
11
Analysons maintenant un nombre binaire, soit loctet : B10010101. Quelle est donc sa
valeur en dcimal ?
Et bien, cest trs simple, on applique le mme algorithme que pour le dcimal. Partons de
la droite vers la gauche, on trouve donc :
Comme, videmment 0 multipli par quelque chose = 0 et que 1 multipli par un chiffre =
le chiffre en question, on peut ramener le calcul prcdent :
Vous voyez donc quil est trs facile de convertir nimporte quel chiffre de binaire en
dcimal. Et linverse me direz-vous ? Et bien, cest galement trs simple. Il faut juste
connatre votre table des exposants de 2. Cela sapprend trs vite lorsquon sen sert.
Quel est le plus grand exposant de 2 contenu dans 149 ? Rponse 7 (27 = 128)
On sait donc que le bit 7 vaudra 1. Une fois fait, il reste 149-128 = 21
Le bit 6 reprsente 64, cest plus grand que 21, donc b6 = 0
Le bit 5 reprsente 32, cest plus grand que 21, donc b5 = 0
Le bit 4 reprsente 16, donc a passe, b4 = 1, il reste 21-16 = 5
Le bit 3 reprsente 8, cest plus grand que 5, donc b3 = 0
Le bit 2 reprsente 4, donc b2 = 1, reste 5-4 = 1
Le bit1 reprsente 2, cest plus grand que 1, donc b1 = 0
Le bit 0 reprsente 1, cest ce quil reste, donc b1=1, reste 0
Le nombre binaire obtenu est donc B10010101, qui est bien notre octet de dpart. Notez
que si on avait trouv un nombre de moins de 8 chiffres, on aurait complt avec des 0 placs
gauche du nombre. En effet, B00011111 = B 11111, de mme que 0502 = 502.
Pensez toujours complter les octets de faon obtenir 8 bits, car cest impos par la
plupart des assembleurs (nous verrons ce que cest dans la suite de ces leons).
Notez que la plus grande valeur pouvant tre reprsente par un octet est donc :
B11111111. Si vous faites la conversion (ou en utilisant la calculette de Windows en mode
scientifique), vous obtiendrez 255. Tout nombre suprieur 255 ncessite donc plus dun
octet pour tre reprsent.
La reprsentation de nombres binaires nest pas vidente grer, et crire une succession
de 1 et de 0 reprsente une grande source derreurs. Il fallait donc trouver une solution plus
pratique pour reprsenter les nombres binaires. On a donc dcid de couper chaque octet en 2
(QUARTET) et de reprsenter chaque partie par un chiffre.
12
Comme un quartet peut varier de b0000 b1111, on constate que lon obtient une
valeur comprise entre 0 et 15. Cela fait 16 combinaisons. Les 10 chiffres du systme dcimal
ne suffisaient donc pas pour coder ces valeurs.
Plutt que dinventer 6 nouveaux symboles, il a t dcid dutiliser les 6 premires lettres
de lalphabet comme CHIFFRES. Ce systme de numrotation en base 16 a donc t
logiquement appel systme hexadcimal.
Notez que ce systme est simplement une reprsentation plus efficace des nombres
binaires, et donc que la conversion de lun lautre est instantane. Dans la suite de ces
leons, nous noterons un nombre hexadcimal en le faisant prcder de 0x. Voyons si vous
avez bien compris :
Pour reprsenter un octet il faut donc 2 digits hexadcimaux. Par exemple, notre nombre
B10010101 est reprsent en hexadcimal par 0x95. Si vous faites la conversion de
lhexadcimal vers le dcimal, vous utilisez le mme principe que prcdemment, et vous
obtenez 0x95 = 9*161 + 5*16 = 149, ce qui est heureux.
Pour preuve, quel est le plus grand nombre hexadcimal de 2 digits pouvant tre
reprsent ? Rponse : 0xFF, soit 15*16 + 15 = 255.
Si vous avez bien tout compris, vous tes maintenant capable de convertir nimporte quel
nombre de nimporte quelle base vers nimporte quelle autre. Vous trouverez galement dans
certaines revues, des allusions au systme octal, qui est un systme en base 8 qui a t
largement utilis.
13
2.4 Les oprations
Aprs avoir converti les nombres dans diffrents formats, vous allez voir quil est
galement trs simple de raliser des oprations sur ces nombres dans nimporte quel format.
Il suffit pour cela deffectuer les mmes procdures quen dcimal.
B1011
+ B1110
--------------
Les 2 nombres de dpart tant B1011, soit 11, et B1110, soit 14. Vous procderez de
la mme manire pour les nombres hexadcimaux, en sachant que 0xF + 0x1 = 0x10, soit
15+1 = 16.
Dans certaines applications, il est ncessaire de pouvoir utiliser des nombres ngatifs.
Comme les processeurs ne comprennent pas le signe - , et comme il fallait limiter la taille
des mots 8 bits, la seule mthode trouve a t dintroduire le signe dans le nombre.
On a donc choisi (pas au hasard) le bit 7 pour reprsenter le signe. Dans les nombres
signs, un bit 7 1 signifie nombre ngatif. Si on stait content de cela, on aurait perdu
une valeur possible. En effet, B10000000 (-0) serait alors gal B00000000 (0). De plus,
pour des raisons de facilit de calcul, il a t dcid dutiliser une notation lgrement
diffrente.
14
Pour faire la conversion inverse, on procde de faon identique.
Dans le cas des nombres signs, on obtient donc les nouvelles limites suivantes :
- La plus grande valeur est B01111111, soit +127
- La plus petite valeur devient B10000000, soit 128.
B 11111101 (-3)
+ B 00000101 (5)
-----------------------------
= B100000010 (2)
Maintenant, si vous avez bien suivi, vous tes en train de vous poser la question suivante :
Quand je vois B11111101, est-ce que cest 3 ou est-ce que cest 253 ? Et bien vous ne
pouvez pas le savoir sans connatre le contexte.
Quest-ce que cest que a, me direz-vous ? Et bien, pour faire simple, disons que ce sont
des oprations qui seffectuent bit par bit sur un octet donn. Plutt quune grosse thorie sur
lalgbre de Boole (jen vois qui respirent), je vais donner dans le concret en prsentant les
oprations indispensables connatre dans la programmation des pics et autres
microcontrleurs.
2.6.1 Le complment
Que vous trouverez galement sous les formes inversion ou NOT ou encore
complment 1. Elle est souvent note ! Son fonctionnement tout simple consiste
inverser tous les bits de loctet (0 devient 1 et 1 devient 0).
15
Vous voyez ici que pour les oprations boolennes, il est plus facile de travailler en
binaire. Traduisez lexemple ci-dessus en hexadcimal (on dira maintenant hexa ) ou en
dcimal et essayez de complmenter directement. Bonjour les neurones.
A quoi sert cette opration ? Par exemple lire une valeur dont les niveaux actifs ont t
inverss, raliser des nombres ngatifs, ou autres que nous verrons par la suite.
Elle consiste appliquer un mot sur un autre mot et multiplier chaque bit par le bit de
mme rang. Pour faire une opration ET , il faut donc toujours 2 octets.
Les diffrentes possibilits sont donnes ci-dessous (le tableau se lit horizontalement).
On voit donc que la seule possibilit pour obtenir un 1 est que le Bit1 ET le Bit2 soient
1 . Ceci correspond une multiplication. 1*1 = 1, 0*1 = 0, 1*0 = 0.
Exemple :
A quoi sert cette instruction ? Et bien, elle est utilise pour MASQUER des bits qui ne
nous intressent pas.
On peut donc laide de cette instruction positionner un ou plusieurs bits dans un mot 0
sans connatre son contenu prcdent.
2.6.3 La fonction OU ou OR
Encore appele OR, souvent note | elle permet, comme son nom lindique, de
positionner un bit 1 si le Bit1 OU le Bit2 est 1.
16
Bit1 Bit2 OR
0 0 0
0 1 1
1 0 1
1 1 1
A quoi sert cette instruction ? Et bien, tout simplement elle permet de forcer nimporte
quel bit dun mot 1 sans connatre son contenu prcdent.
Vous voyez que dans lexemple prcdent, les 2 premiers bits ont t forcs au niveau 1,
indpendamment de leur niveau prcdent.
Voici la dernire fonction que nous allons aborder dans cette mise niveau. Elle est
souvent appele XOR (eXlusif OR). Elle se comporte comme la fonction OR, un dtail prs.
Pour obtenir 1, il faut que le Bit1 soit 1 OU que le Bit2 soit 1 lEXCLUSION des
deux bits ensemble. Si les 2 bits sont 1, alors le rsultat sera 0.
A quoi sert cette instruction ? Et bien tout simplement inverser un ou plusieurs bits dans
un mot sans toucher aux autres. Dans lexemple prcdent, vous voyez qu lemplacement
des 2 bits 1 du 2me octet, les bits correspondants du 1er octet ont t inverss.
Voil, ainsi se termine le premier chapitre consacr aux pics. Je sais quil tait
particulirement rbarbatif, mais, si vous ne matrisez pas parfaitement ce qui vient dtre
expliqu, vous ne pourrez pas raliser correctement vos propres programmes.
17
Notes :
18
3. Composition et fonctionnement des PICs
Enfin quelque chose de plus intressant. Nous allons maintenant nous pencher sur un PIC,
et en particulier sur le 16F84. Rassurez-vous, tout ce que nous verrons sur le 16F84 pourra
tre directement utilis sur les 16F876, qui ne sont rien dautre que des 16F84 amliors.
Chaque PIC dispose des fonctionnalits des modles infrieurs, augmentes de nouvelles
fonctions. Au moment de passer la rvision 13 du cours, les modles que vous rencontrerez
seront probablement des 16F84A, mais a ne posera aucun problme pour ltude de ce cours.
Tout dabord, vous devez tlcharger le datasheet du 16F84, car cest un document que
nous allons utiliser dans le reste de ces petites leons. Je vous conseille vivement de
limprimer, car vous en aurez toujours besoin quand vous vous lancerez dans la ralisation de
vos propres programmes.
Ces datasheets sont mes livres de chevet. Jai trouv plus judicieux de travailler par la
pratique et de les commenter, plutt que de traduire btement les datasheets en question.
Un PIC nest rien dautre quun microcontrleur, cest dire une unit de traitement de
linformation de type microprocesseur laquelle on a ajout des priphriques internes
permettant de raliser des montages sans ncessiter lajout de composants externes.
La dnomination PIC est sous copyright de Microchip, donc les autres fabricants ont t
dans limpossibilit dutiliser ce terme pour leurs propres microcontrleurs.
Les PICs sont des composants dits RISC (Reduced Instructions Set Computer), ou encore
composant jeu dinstructions rduit. Pourquoi ? Et bien, sachez que plus on rduit le nombre
dinstructions, plus facile et plus rapide en est le dcodage, et plus vite le composant
fonctionne.
Vous aurez devin quon trouve sur le march 2 familles opposes, les RISC et les CISC
(Complex Instructions Set Computer). Sur les CISC, on dispose de moins de vitesse de
traitement, mais les instructions sont plus complexes, plus puissantes, et donc plus
nombreuses. Il sagit donc dun choix de stratgie.
Tous les PICs Mid-Range ont un jeu de 35 instructions, stockent chaque instruction dans
un seul mot de programme, et excutent chaque instruction (sauf les sauts) en 1 cycle. On
atteint donc des trs grandes vitesses, et les instructions sont de plus trs rapidement
assimiles. Lexcution en un seul cycle est typique des composants RISC.
Lhorloge fournie au PIC est prdivise par 4 au niveau de celle-ci. Cest cette base de
temps qui donne la dure dun cycle.
19
Pensez que les pics peuvent monter 20MHz. Cest donc une vitesse de traitement plus
quhonorable.
La famille des PICs tait subdivise au moment dcrire la rvision 1 de cet ouvrage en 3
grandes familles : La famille Base-Line, qui utilise des mots dinstructions (nous verrons ce
que cest) de 12 bits, la famille Mid-Range, qui utilise des mots de 14 bits (et dont font partie
les 16F84 et 16F876), et la famille High-End, qui utilise des mots de 16 bits. Par la suite,
dautres familles sont apparues, comme la Enhanced family, et les choses ne devraient faire
quvoluler.
Nous nous limiterons dans cet ouvrage la famille Mid-Range, sachant que si vous avez
tout compris, vous passerez trs facilement une autre famille, et mme un autre
microcontrleur. Du reste, dautres cours sont prvus pour vous permettre dvoluer plus
facilement.
Cependant, la documentation de base suffit pour 99,9% des applications, et, de plus, les
datasheets Mid-Range sont disponibles sous la forme dun fichier par chapitre. Jai pour ma
part presque tout imprim, mais je vous conseille plutt daller les chercher le jour o vous en
aurez besoin.
Vient ensuite parfois une lettre L : Celle-ci indique que le PIC peut fonctionner avec une
plage de tension beaucoup plus tolrante.
C indique que la mmoire programme est une EPROM ou plus rarement une EEPROM
CR pour indiquer une mmoire de type ROM
Ou F pour indiquer une mmoire de type FLASH.
Notez ce niveau que seule une mmoire FLASH ou EEPROM est susceptible dtre
efface, donc nesprez pas reprogrammer vos PICs de type CR. Pour les versions C, voyez le
datasheet. Le 16C84 peut tre reprogramm, il sagit dune mmoire eeprom. Le 12C508, par
exemple, possde une mmoire programme EPROM, donc effaable uniquement par
exposition aux ultraviolets. Donc, leffacement ncessite une fentre transparente sur le chip,
qui est une version spciale pour le dveloppement, et non la version couramment rencontre.
20
Un composant quon ne peut reprogrammer est appel O.T.P. pour One Time
Programming : composant programmation unique. Puis vous constatez que les derniers
chiffres identifient prcisment le PIC. (84)
Finalement vous verrez sur les botiers le suffixe -XX dans lequel XX reprsente la
frquence dhorloge maximale que le PIC peut recevoir. Par exemple 04 pour un 4MHz. En
fait, il semble bien que cette donne soit purement commerciale et que tous les pics dun
mme modle acceptent de tourner la vitesse maximale de ce modle, vitesse donne en
dbut du datasheet. Cette inscription semble donc dans la ralit des faits parfaitement inutile.
Cette information nengage pas ma responsabilit, vous de juger et de vous renseigner.
Donc, un 16F84-04 est un PIC Mid-Range (16) donc la mmoire programme est de type
FLASH (F) donc rinscriptible de type 84 et capable daccepter une frquence dhorloge de
4MHz en thorie (probablement : 10Mhz pour un 16F84 et 20Mhz pour un 16F84A).
Une dernire indication que vous trouverez est le type de botier. Nous utiliserons pour
nos exprience le botier PDIP, qui est un botier DIL 18 broches, avec un cartement entre
les ranges de 0.3 (troit). La version 4MHz sera amplement suffisante.
Notez ds prsent que les PICs sont des composants STATIQUES, cest dire que la
frquence dhorloge peut tre abaisse jusqu larrt complet sans perte de donnes et sans
dysfonctionnement.
Donc, si vous voulez passer commande pour le PIC que nous allons utiliser dans le reste
de cet ouvrage, demandez donc un PIC16F84-04 en botier PDIP .
La mmoire du 16F84 est divise en 3 parties. Page 4 du datasheet, vous trouverez la table
1-1 qui donne un aperu de la famille 16F8X. Les numros de pages peuvent varier en
fonction des mises jour de Microchip. Vous devrez peut-tre chercher un peu, ou alors
utilisez le datasheet que je fournis avec le cours.
Pour ceux qui veulent tout comprendre, la figure 3-1 de la page 8 montre lorganisation
interne dun 16F84.
La mmoire programme est constitue de 1K mots de 14 bits. Cest dans cette zone que
vous allez crire votre programme. Ceci explique pourquoi vos fichiers sur PC font 2Kbytes.
En effet, il faut 2 octets pour coder 14 bits. Ceci explique galement pourquoi, lorsque
vous lisez un PIC vierge, vous allez lire des 0x3FFF. Cela donne en binaire
B11111111111111, soit 14 bits. Jexpliquerais plus loin do proviennent ces fameux 14
bits.
21
Notez ce point quune instruction est code sur 1 mot. Donc, 1K donne 1 bon millier
dinstructions possibles (cest dj pas si mal). Quand vous en serez crire des programmes
de 1K, vous serez sans aucun doute autonome pour vos applications.
La mmoire RAM (Random Access Memory) est celle que nous allons sans cesse
utiliser. Toutes les donnes qui y sont stockes sont perdues lors dune coupure de courant.
La mmoire RAM est organise en 2 banques pour le 16F84. La RAM est subdivise de
plus en deux parties. Dans chacune des banques nous allons trouver des cases mmoires
spciales appeles REGISTRES SPECIAUX et des cases mmoires libres dont vous
pouvez vous servir votre guise.
Pour le cas du 16F84, vous disposerez de 68 octets libres. Lorganisation de la RAM est
montre dans le tableau 4-2 page 13. Vous voyez la sparation verticale en 2 banques, et tout
en bas vous voyez deux banques de 68 octets de RAM.
Vous voyez dans la partie suprieure le nom de tous les registres spciaux utiliss dans le
PIC. Nous les verrons tous, rassurez-vous.
Remarquez que la banque 0 utilise les adresses de 0x00 0x7F, la banque 1 allant de 0x80
0xFF. Les zones en gris sont des emplacements non utiliss (et non utilisables).
Lemplacement 0x00 est un emplacement auquel on ne peut pas accder.
Pour la grande majorit des registres, chaque bit a une fonction spciale. Page 14, tableau
4-1, vous trouverez les noms des bits utiliss dans ces registres.
22
4. Organisation des instructions
4.1 Gnralits
Allez, courage, cela devient de plus en plus concret. On va faire un petit survol du jeu
dinstructions des PICs. On saute directement page 55 du datasheet, au chapitre 9. Et oui,
comme cet ouvrage nest pas un manuel de rfrence technique, mais un apprentissage, il faut
voir les chapitres du datasheet dans le dsordre.
Sur cette page, vous trouvez un petit encadr gris qui fait allusion deux anciennes
instructions qui ne sont plus utilises. Nous ne nous en servirons donc pas. Par contre, vous
trouvez un tableau 9-1 qui indique comment les instructions sont codes dans le PIC. Et la,
vous voyez enfin quoi correspondent nos 14 bits de mmoire programme.
Ce sont des instructions qui manipulent les donnes sous forme doctets. Elles sont codes
de la manire suivante :
- 6 bits pour linstruction : logique, car comme il y a 35 instructions, il faut 6 bits pour
pouvoir les coder toutes
- 1 bit de destination(d) pour indiquer si le rsultat obtenu doit tre conserv dans le
registre de travail de lunit de calcul (W pour Work) ou sauv dans loprande (F pour
File).
Aie, premier problme, 7 bits ne donnent pas accs la mmoire RAM totale, donc voici
ici lexplication de la division de la RAM en deux banques.
En effet, il faudra bien trouver une solution pour remplacer le bit manquant. Vous avez dit
un bit dun des registres ? BRAVO, je vois que vous avez tout compris. Il sagit en ralit
du bit RP0 du registre STATUS.
Ah, vous avez remarqu quil y a un RP1 ? Et oui, le 16F876 a 4 banques, ce bit sera
utilis pour certains autres PICs que nous verrons dans la seconde partie. Vous veillerez
laisser RP1 0 pour le 16F84, afin de pouvoir porter votre programme sans problme vers
un PIC suprieur.
Ce sont des instructions destines manipuler directement des bits dun registre
particulier. Elles sont codes de la manire suivante :
23
- 4 bits pour linstruction (dans lespace rest libre par les instructions prcdentes)
Ce sont les instructions qui manipulent des donnes qui sont codes dans linstruction
directement. Nous verrons ceci plus en dtail lorsque nous parlerons des modes dadressage.
Elles sont codes de la manire suivante :
- Elle est suivie dune valeur IMMEDIATE code sur 8 bits (donc de 0 255).
Ce sont les instructions qui provoquent une rupture dans la squence de droulement
du programme. Elles sont codes de la manires suivante :
Par convention, en effet, 1Kbytes correspond 210 = 1024 octets. Ce qui explique que si
vous avez 16K de mmoire, en ralit vous avez 16*1024 = 16384 bytes. Par extension,
1Mbyte = 1024 Kbytes, donc 1048576 octets.
Maintenant vous saurez pourquoi vous voyez plus que votre mmoire thorique lors du
test mmoire au dmarrage de votre ordinateur.
Une petite parenthse qui na rien voir ici : les fabricants de disques durs considrent
que 1Mbytes = 1000000 bytes. Comme Windows indique la taille en Mbytes de 1048576
bytes, cela vous explique pourquoi la plupart de vos disques durs semblent plus petits que
prvus.
24
4.3 Panoramique des instructions
Je vais maintenant vous montrer comment fonctionne le tableau de la figure 9-2 page 56.
Ce tableau vous permet dun simple regard de vous informer de la manire dont fonctionne
chaque instruction
Notez ici la confusion de langage commune pour le terme ASSEMBLEUR, quon utilise
la fois pour indiquer le programme qui permet dassembler le code (programme
dassemblage), et le langage utilis dans lditeur (langage dassemblage).
Vous allez donc trouver cet emplacement les instructions proprement dites que vous
allez pouvoir encoder dans votre programme.
La syntaxe doit tre la suivante pour lassembleur MPLAB, que nous utiliserons ds la
prochaine leon. Nous avons dans lordre :
- Etiquette (facultative)
- Espace(s) ou tabulation(s)
- Mnmonique (en majuscules ou minuscules)
- Tabulation ou Espace(s)
- Oprande ou la valeur
- Virgule ventuelle de sparation
- Bit de destination W ou F ou ventuellement numro du bit de 0 7 si ncessaire
- Espace(s) ou tabulation(s)
- point-virgule. (facultatif si pas de commentaire)
- Commentaire. (facultatif)
Notez que le mnmonique ne peut pas se trouver en premire colonne, et que tout ce qui
suit le point-virgule est ignor de lassembleur (donc cest de la zone commentaire).
Voici titre dexemple deux lignes valides, les mots en vert sont des mots rservs, en
bleu linstruction, ceux en jaune tant libres, le reste est du commentaire :
25
La seconde colonne du tableau donne un bref descriptif de linstruction.
Notez que toutes les instructions ncessitent un seul cycle, sauf les sauts qui en ncessitent
2, et les oprations de test avec saut, lorsque le rsultat du test engendre le saut (instructions
notes 1(2)).
La 4me colonne donne ce quon appelle l OPCODE, cest dire le mot binaire que
MPLAB va gnrer pour vous au dpart du mnmonique.
Vous ne vous en servirez donc pas, mais sachez que vous pourriez programmer
directement le PIC sans passer par un assembleur, directement en construisant un fichier .hex
et en entrant les valeurs trouves ici.
Vous devriez alors tout calculer, y compris les sauts. Cest ce que jai fait mes dbuts sur
un processeur 6502, car je ne disposais pas dun assembleur. On pouvait galement utiliser
cette technique pour construire des programmes auto-modifis pour cause de restriction
mmoire.
La 5me colonne est primordiale, car elle donne les INDICATEURS DETATS ou
STATUS FLAGS affects (modifis) une fois linstruction effectue. Nous verrons ces
indicateurs en dtail, car ils constituent les cls de la programmation.
La dernire colonne renvoie des notes en bas de page. La note 1 est trs importante, elle
fait allusion la mthode lecture/modification/criture propre aux ports dentres/sortie
(I/O).
La note 2 indique quune modification dun timer remet zro son prdiviseur. Nous y
reviendrons en abordant le TMR0.
La troisime note indique que si vous vous servez de linstruction pour modifier le
compteur de programme (celui qui pointe sur la PROCHAINE instruction excuter), il y
aura un cycle supplmentaire. Cest logique car cela quivaut un saut. Nous verrons que
cette technique est pratique pour aller chercher des valeurs dans une table construite en
mmoire programme.
26
Lisez donc attentivement ce qui suit. Tous les indicateurs sont des bits du registre
STATUS. Voyez le tableau page 15. Nous aborderons ici les flags Z et C. Les autres seront
traits lors de ltude des registres.
Si le rsultat dune opration POUR LEQUEL IL EST AFFECTE, donne un rsultat gal
0, le flag Zro passe 1.
Donc, si vous faites une addition avec ADDWF et que le rsultat obtenu est 0, le bit Z sera
1. Si le rsultat est <>0 (diffrent de 0), le bit Z vaudra 0. Dans les 2 cas il est modifi.
Par contre, si vous stockez une valeur avec linstruction MOVWF, le bit Z ne sera pas
modifi, mme si la valeur vaut 0. Ces remarques sont valables pour les autres flags, donc je
ny reviendrai pas.
Petit exemple :
Comme les registres du PIC ne font que 8 bits, vous obtiendrez B00000001 (1) et C
positionn 1 (en fait le 9me bit, donc le bit 8, donc 28 = 256). Donc le rsultat final est de
256 + 1 = 257.
Remarquez que si vous aviez ajout B11111110 et B00000010, vous auriez obtenu
B00000000.
Dans ce cas, vous auriez eu C 1 ET Z 1, ce qui signifie rsultat nul, mais avec report
(donc rsultat = 256).
Nous verrons les autres bits du registre dtat dans la suite de cet ouvrage, au moment o
la ncessit se fera sentir.
27
Notes :
28
5. Les dbuts avec MPLAB
Nous allons maintenant dmarrer la grande aventure avec notre tout premier et modeste
programme. Jexpliquerai les instructions et les registres au fur et mesure de leur utilisation.
A partir de la rvision 13 du cours, nous travaillerons avec MPLAB 6.x, qui est la version qui
succde la version 5.x utilise dans le cours jusque la rvision 12.
La premire chose faire est daller chercher la version actuelle de MPLAB 6.60 sur le
site Microchip : http://www.microchip.com section archives . Vous pouvez galement
utiliser une version 7.xx assez semblable. Dans ce cours, les copies dcrans ont t faites
avec MPLAB 6.3, mais les diffrences devraient tre minimes pour les versions plus rcentes.
Personnellement, je naime pas laisser les donnes avec mes programmes dans la partition
principale. Si vous tes comme moi, crez un rpertoire dans un endroit o vous rangez vos
data et appelez-le, par exemple DataPic.
Copiez y le fichier m16F84.asm fourni avec le cours. Cest un fichier que jai cr afin de
pouvoir dmarrer instantanment un nouveau programme. Je lai appel m16f84.asm ,
avec m pour maquette .
Si vous ne dsirez pas crer un nouveau rpertoire, copiez ce fichier dans le rpertoire
dinstallation : par dfaut c:\program files\MPLAB IDE.
Pour chaque nouveau programme que vous allez crer, faites un copier/coller du fichier
m16F84.asm. Pour notre premier programme, copiez/collez ce fichier et renommez la copie
obtenue en Essai1.asm.
Vous pouvez maintenant lancer MPLAB IDE partir du menu dmarrer ou de licne de
votre bureau, si vous en avez accept linstallation. Aprs quelques instants, vous vous
retrouvez avec un cran vide avec menu et barres doutils. Sil y a des fentres ouvertes dans
le bureau de MPLAB 6, fermez-les toutes, ainsi vous saurez comment les rouvrir, et tout le
monde dbutera avec la mme configuration.
MPLAB est un logiciel qui est construit sur la notion de projets. Un projet permet de
mmoriser tout lenvironnement de travail ncessaire la construction dun . projet. Il vous
permettra de rtablir tout votre environnement de travail lorsque vous le slectionnerez.
29
MPLAB 6 dispose dun wizard pour la cration des projets, qui vous permet den crer
automatiquement de nouveaux. Cependant, afin de vous permettre de localiser les principales
options des projets, je ne men servirai pas dans ce petit tutorial. Si par la suite vous dsirez
lutiliser, il se slectionne laide du menu project->wizard
Allez dans le menu Project et slectionnez new . La fentre qui souvre vous
permet dintroduire le nom du projet et le rpertoire de travail du dit projet. Pour le rpertoire,
vous disposez du bouton browser qui vous permet de pointer sur le bon rpertoire sans
risque de vous tromper.
Entrez essai1 comme nom de votre nouveau projet, et slectionnez le rpertoire dans
lequel vous avez plac votre fichier maquette et votre fichier essai1.asm. Jai nomm le
fichier asm de faon identique au projet, mais ce nest nullement obligatoire.
Une fois le bouton <OK> press, une nouvelle fentre apparat dans le coin suprieur
gauche du bureau de MPLAB IDE.
Dans cette fentre, vous voyez le nom de votre projet (essai1.mcp), ainsi que les
fichiers lis celui-ci. Pour linstant, vous nen avez aucun, cest normal.
30
Nous allons commencer prciser les paramtres importants de notre projet, et tout
dabord le type de pic que nous allons utiliser. Slectionner le menu configure->select
device , une fentre apparat pour vous proposer le choix du pic. Notez que par dfaut,
Microchip vous propose un pic de la famille 18F, promotion de nouveau produit oblige
Slectionnez le 16F84.
La fentre vous montre alors, laide de leds vertes ou rouges quels outils sont supports
par le pic slectionn. Vous voyez donc que le simulateur intgr (MPLAB SIM) fonctionne
avec ce pic, et ainsi de mme pour les autres outils de dveloppement disponibles chez
Microchip. Une fois cliqu <OK>, la fentre se referme.
Nous allons maintenant prciser quel langage nous allons utiliser, sachant que nous
travaillons en assembleur, mais que diffrents compilateurs sont proposs par Microchip et
dautres socits. Slectionnez le menu project -> Select langage toolsuite . Dans la fentre
qui souvre, slectionnez dans le menu droulant : Microchip MPASM toolsuite . MPASM
est en effet lassembleur par dfaut de Microchip.
31
Dans les fentres infrieures, vous voyez le nom des excutables utiliss par MPASM, ne
vous en proccupez pas. Cliquez <OK> pour fermer la fentre.
Il nous faut maintenant indiquer MPASM quel est notre ou nos fichiers source(s). Ceci
seffectue dans la fentre essai1.mcw qui est reste ouverte dans le coin suprieur gauche.
Pour ajouter un fichier source, cest trs simple : cliquez avec le bouton droit sur source
files , puis slectionnez Add . Une fois slectionn le fichier, le nom de celui-ci apparat
dans larborescence. Notez que MPLAB pointe par dfaut sur votre rpertoire de travail,
prcdemment choisi.
Ici, il est important de bien comprendre que le fichier source choisi sera celui qui sera
assembl ou compil. Autrement dit, si dans ce fichier se trouve une instruction include
qui inclut un autre fichier, vous ne devez pas le slectionner en supplment, il sera joint au
projet au moment de lassemblage.
Par contre, si vous dsirez assembler simultanment deux fichiers, et que votre premier
fichier ne fait pas rfrence au second, alors vous devez ajouter ce fichier larborescence.
32
Tous nos projets ne ncessiteront dajouter quun seul fichier. Si votre projet ncessite un
ou plusieurs fichier(s) supplmentaire(s), la directive include sera ajoute au fichier source
afin que lassembleur intgre automatiquement ce ou ces autre(s) fichier(s).
Vous navez besoin de rien dautre, les autres lments de larborescence ne sont pas
ncessaires pour un projet assembleur du type dont nous allons parler.
Comme nous avons dcid de numroter lhexadcimal sous la forme 0x, et le binaire
sous la forme B. Tout nombre sans prfixe sera considr comme dcimal. Cochez donc la
case Decimal . Ne touchez pas aux autres options, vous les utiliserez peut-tre lorsque vous
serez devenus un pro et que vous voudrez adapter certains paramtres. A ce moment, leur
rle vous semblera clair.
33
Afin dviter tout oubli, je vous conseille cependant de TOUJOURS placer un prfixe
devant vos nombres, ceci vous vitera bien des dboires. Utilisez par exemple les syntaxes
suivantes :
Un nombre crit sous la forme sans prfixe sera interprt selon le paramtre
prcdemment dcrit, et donc risque de poser problme si vous intgrez votre fichier dans un
autre projet, ou, simplement, si vous communiquez autrui votre fichier source sans prciser
la notation par dfaut.
Maintenant, MPASM est prt assembler votre programme. Mais, allez-vous me dire,
il ny a toujours rien lcran !
Vous pouvez avoir autant de fichiers que vous voulez sur lcran, ou ne pas en avoir du
tout. MPLAB sen moque. Par contre, tous les fichiers ouverts lors de la sauvegarde de votre
projet seront automatiquement rouverts lors de la prochaine ouverture du projet, mme sils
ne servent rien. Cette proprit est pratique pour faire des copier/coller partir dun autre
fichier ou pour voir tout en programmant ce quun autre a bien pu faire.
Bien entendu, nous allons afficher notre fichier source, pour voir ce quil contient. La
mthode la plus simple est de double-cliquer sur son nom dans larborescence de la fentre
essai1.mcw. Faites-le. Voici votre fichier de dpart ouvert. Mettez-le la taille approprie en
lui faisant occuper la moiti gauche de lcran si vous manquez de place (vous naurez plus
besoin de fentre du projet, vous pouvez la masquer ou la rduire).
Pour ouvrir un fichier qui nest pas inclus dans larborescence, utilisez le menu file-
>open ou licne douverture dans la barre doutils.
Si vous voulez que vos crans ressemblent au mien, changez la fonte de lditeur. Pour
ceci, slectionnez Edit -> properties , puis longlet text . Ensuite, un clic sur le bouton
Select font vous permettra de choisir la fonte : Courier New de style Standard et
dimposer une taille de 9 .
Pour ceux que a intresse, je travaille sur un moniteur 22 pouces, et ma rsolution est de
1280 X 1024, a vous indique les proportions. Vrifiez galement dans longlet Tabs que
la longueur de la tabulation est fixe 4 ( size sur MPLAB >7.5). Au besoin, modifiez-la.
Votre fichier asm est maintenant affich lcran. Notez pour ceux qui viennent de
MPLAB5 que la gestion des tabulations est diffrente sur MPLAB5 et MPLAB6, ce qui
signifie que les mises en page dun fichier crit sur MPLAB5 ne seront plus respectes lors du
passage MPLAB6. Jai donc modifi tous les fichiers en consquence. Ceux qui disposent
de la version prcdente ont intrt utiliser les nouveaux fichiers.
34
Pour ceux qui viennent de MPLAB5, vous constatez que MPLAB6 est plus simple
manipuler, ceci va encore plus se confirmer lorsque nous verrons le simulateur.
35
Notes
36
6. Organisation dun fichier .asm
Tout dabord, cliquez nimporte o lintrieur de ce fichier. Vous tes lintrieur dun
simple traitement de texte. Dans le coin infrieur gauche, vous verrez un numro de ligne et
de colonne. Cest la position actuelle de votre curseur. Je me servirai de cette position pour
vous guider au travers du fichier. Najoutez donc pas de lignes pour linstant, pour garder la
correspondance correcte avec ce texte. Si vous ne voyez pas de numro de lignes, allez dans
le menu edit -> properties et cochez line numbers dans longlet editor
Si vous narrivez pas effectuer des modifications dans vote fichier, et que votre clavier
semble inactif (rencontr avec MPLAB 5.x), cest que vous avez utilis un caractre tendu
dans le nom de votre fichier. Au contraire de MPLAB5, MPLAB6 gre maintenant tous les
caractres tendus, pour les fichiers et pour les dossiers.
Prenez lhabitude de toujours commenter vos programmes. Soyez sr que dans 6 mois,
vous ne vous rappellerez plus ce que vous avez voulu faire, les commentaires vous seront
alors dune grande utilit si vous dcidez de modifier votre programme.
Remplissons donc le cadre en indiquant les diffrentes rfrences. Je joins avec cette
leon le fichier essai1.asm , qui reprend le fichier tel quil sera la fin de cette leon.
A la ligne 34, nous trouvons une DIRECTIVE destine MPASM pour lui indiquer quel
type de processeur est utilis dans ce programme.
Les DIRECTIVES ne font pas partie du programme, elles ne sont pas traduites en
OPCODE, elles servent indiquer lassembleur de quelle manire il doit travailler. Ce sont
donc des COMMANDES destines lassembleur en lui-mme.
37
Pour voir ce quil contient, allez dans le menu file ->Open , choisissez all source
files dans le cadre infrieur, et ouvrez p16F84.inc. dans le rpertoire
C:\Program Files\MPLAB IDE\MCHIP_Tools.
Une fois dpasse la zone de commentaires, vous verrez des lignes du style :
Cette ligne signifie tout simplement que FSR est EGAL 0x04. Autrement dit, lorsque
vous utiliserez FSR dans une instruction, MPASM interprtera FSR comme tant 0x04. 0x04
tant tout simplement ladresse de FSR dans la mmoire du PIC.
H04 est une autre mthode autorise pour exprimer un nombre hexadcimal, tout comme
04h
Si vous prenez votre tableau 4-2 page 13, vous constaterez que cest bien le cas. Ce fichier
est donc principalement destin vous viter davoir mmoriser toutes les adresses, un nom
est bien plus simple utiliser et retenir. Fermez le fichier p16F84.inc pour ne pas encombrer
votre fentre.
La ligne suivante, commence par __CONFIG . Cette ligne contient les fameux
fusibles qui fixent le fonctionnement du PIC.
Les valeurs crites ici seront intgres dans le fichier .hex pour signaler au
programmateur les valeurs encoder aux adresses spcifiques du PIC. Nous y reviendrons.
Sachez donc que si un fichier .hex a t cr par un programmeur attentif qui a utilis
cette directive, vous naurez nul besoin de dfinir ces paramtres au moment de la
programmation. Le logiciel du programmateur ira normalement chercher ces valeurs dans le
fichier lui-mme.
Jai plac dans le fichier toutes les valeurs possibles de ces paramtres, avec les
explications correspondantes. Il suffit de remplacer une des valeurs par celle souhaite.
Par exemple, activons le Code Protect (protection en lecture) :
Faites-le. Remarquez que les diffrentes valeurs sont lies par le symbole & (AND)
expliqu dans la leon sur les systmes de numrotations. Ils fonctionnent donc en plaant des
38
bits 0 , si vous avez tout suivi. Donc, attention de toujours bien prciser tous les
paramtres, mme ceux que vous nutilisez pas.
Les valeurs correspondantes sont de nouveau dans le fichier P16F84.INC . Donc, pas
de magie, tout sexplique en rflchissant un peu.
Aux lignes 57 et 62, vous trouverez des ASSIGNATIONS personnelles qui fonctionnent
selon le mme principe que dans le fichier .inc .
Un autre avantage est que si vous remplacez la valeur dune assignation, le changement
sera effectif pour tout le programme. Vous ne risquez donc pas doublier des valeurs en
chemin.
Je vous encourage vivement utiliser les ASSIGNATIONS et autres mthodes que nous
allons voir plus bas. La syntaxe est simple puisquil sagit de EQU (gal )
Exemple dassignation :
Par exemple nous pourrons utiliser un PORT suivi dun numro de bit, ou bien carrment
une instruction avec ses paramtres.
Une dfinition est construite de la manire suivante : La directive #DEFINE, suivie par le
nom que lon dsire utiliser, puis la chane substituer. Par exemple :
Lutilisation de cette macro seffectue tout simplement en utilisant son nom dans le
programme. Par exemple :
39
Sera traduit par MPLAB comme suit :
LIREIN macro
comf PORTB,0
andlw 1
endm
La macro se compose dun nom crit en premire colonne, suivi par la directive
macro . Commence alors la ligne suivant la portion de code qui constitue la macro. La fin
de la macro est dfinie par la directive endm ) (end of macro).
Une macro remplace donc un morceau de code que nous utilisons souvent. La macro
fonctionne galement uniquement comme un simple traitement de texte.
Dans notre exemple, chaque fois que la macro LIREIN sera rencontre, elle sera
remplace au moment de lassemblage par les 2 lignes :
comf PORTB , 0
andlw 1
La macro simplifie donc lcriture, mais ne raccourcit pas la taille du fichier .hex obtenu,
puisque les 2 lignes seront crites dans le PIC.
Notez que lon peut utiliser des macros plus complexes, avec passage de paramtres, mais
nous nentrerons pas dans ces fonctions particulires pour linstant.
Notez galement que vous disposez dune aide dans le menu help->MPASM Help . En
effet, laide de MPLAB concerne lutilisation du logiciel. Les aides concernant le langage
sont dans MPASM, puisque cest ce langage que MPLAB utilise (revoyez ldition des
nuds).
Toute zone dfinie par lutilisateur commence avec la DIRECTIVE CBLOCK, suivie par
ladresse du dbut de la zone.
Pour placer nos variables, qui sont des emplacements mmoires auxquels on a donn un
nom, nous consultons de nouveau le tableau 4-2. Nous voyons que la zone RAM librement
utilisable commence l'adresse 0x0C. Notre zone de variable contiendra donc la directive
40
Par exemple :
Vous trouverez dans les programmes en 1ere colonne ce que nous appellerons des
ETIQUETTES. Ce sont des noms que vous choisissez et qui sont des REPERES pour le
programme.
La directive ORG, suivie de ladresse, prcise quelle adresse les instructions qui suivent
seront places dans le PIC. Il est important de savoir 2 choses :
Aprs un reset ou une mise sous tension, le PIC dmarre toujours ladresse 0x00. Le
dbut de votre programme doit donc se situer l.
Ladresse 0x04 est ladresse utilise par les interruptions (nous verrons le principe plus
tard). Il ne vous reste donc pas grand place pour placer votre programme. Nous
commencerons donc par un saut vers lemplacement du programme principal o nous aurons
plus de place. Allons donc voir ligne 103 comment tout ceci fonctionne :
La premire ligne est une DIRECTIVE qui indique que la ligne suivante sera place
ladresse 0x00.
La seconde ligne est une INSTRUCTION, explique page 62, qui indique au PIC que le
programme doit SAUTER ladresse init . init est une ETIQUETTE.
Aprs le reset, le PIC excute donc linstruction goto init qui se trouve ladresse 0x00,
suivie par linstruction qui se trouve ladresse init plus bas dans le programme (donc juste
en dessous de ltiquette init).
41
6.11 La directive END
Cette directive prcise lendroit o doit cesser lassemblage de votre programme. Elle est
obligatoire dans tout programme, sous peine dune erreur qui vous signalera que la fin de
fichier (End Of File) a t atteinte avant de rencontrer la directive END.
Toutes les instructions situes aprs la directive END seront tout simplement ignores.
42
7. Ralisation dun programme
Avant de lancer notre premier programme, nous allons procder quelques modifications
du fichier essai1.asm , afin de ne conserver que ce qui nous intresse.
Premirement, allez ligne 104 (le numro peut tre diffrent chez vous) et remplacez la
ligne goto init par goto start. Ne faites pas de faute dorthographe.
Descendez ensuite en ligne 225, vous trouverez l notre tiquette start, cest donc l que
notre programme va sauter. Effacez ensuite la ligne
Il reste donc une instruction que nous avons dj vue, linstruction goto .
Le datasheet, page 62, nous apprend que linstruction goto est suivie dune valeur
IMMEDIATE (cest dire une valeur sous forme dun nombre), code sur 11 bits (rappelez-
vous, le programme peut faire 1KMOTS, donc, avec 11 bits, on peut sauter nimporte o dans
la mmoire programme.
La valeur peut bien sr tre remplace par une tiquette, MPASM se chargeant pour vous
de calculer son emplacement. Le datasheet vous indique aussi quil sagit dun saut
INCONDITIONNEL, cest dire quil seffectuera toujours, sans condition. Il est rappel
quun saut prend 2 cycles.
Faisons de la place sous ltiquette start, et ajoutons la ligne suivante (attention, pas en
premire colonne) :
CLRF est une instruction dtaille dans le chapitre ddicac aux instructions. Il y est dit
que lemplacement mmoire prcis derrire linstruction (ou une variable) est effac. Le bit
Z est positionn selon le rsultat de lopration.
Comme le but de lopration est de mettre la variable 0, le bit Z vaudra toujours 1 aprs
cette instruction. Notez que lemplacement mmoire peut se situer de 0 127 (0x7F). Cest
logique : si vous consultez le tableau 4-2, vous voyez que la RAM sarrte au 127me
emplacements pour chacune des 2 banques.
Placez ensuite une tiquette (colonne1) que vous appellerez boucle. Sous cette tiquette,
ajoutez linstruction :
boucle
43
INCF mavariable,f
Cette instruction est explique galement dans le chapitre relatif aux instructions. Vous
voyez que cette instruction incrmente (+1) le contenu de la variable mavariable, et que le
rsultat de lopration est plac dans lemplacement d. Pour toutes les instructions, d peut
valoir soit f , dans ce cas le rsultat est stock dans la variable en question, soit w , dans
ce cas le rsultat est plac dans le registre de travail, et la variable nest pas modifie.
Vous voyez galement que le bit de STATUS Z est affect par lopration. Je rappelle
une dernire fois : si le rsultat de lincrmentation donne 0, Z sera mis 1. Il sera mis 0
dans tous les autres cas.
goto start
par
goto boucle
start
clrf mavariable ; effacer mavariable
boucle
incf mavariable,f ; incrmenter mavariable
goto boucle ; boucler
END ; directive fin de programme
Nous allons maintenant tenter dassembler ce programme pour en faire un fichier .hex.
Pressez la touche F10 , des fentres souvrent, MPLAB passe les commandes MPASM
qui tente dassembler notre programme. Lassemblage s arrte en chemin, une barre rouge
apparat et nous nous retrouvons une nouvelle fentre (output ) qui contient les rsultats de
sortie de la commande. Si vous rencontrez un problme non prvu (erreur 173 par exemple)
jetez un oeil un fin de cours, dans les annexes.
44
Que sest-il pass ? Et bien, examinons le rapport construit. Vous voyez dabord des
messages (warning). Ce sont des messages destins attirer votre attention, mais qui ne
gnrent pas dimpossibilit dassemblage. Noubliez pas quil y a toute une partie du
programme qui ne sert rien dans notre exemple, mais qui est tout de mme crite (au dessus
de ltiquette start). Nous mettrons cette partie en pratique dans les chapitres suivants.
Le problme vient videmment des lignes error . Il y est dit que le symbole
mavariable na pas t dfini par lutilisateur. Cette erreur se retrouve dans les 2 lignes o
nous avons utilis notre variable. En fait, nous avons oubli de la DECLARER. Pour remdier
cela, fermons la fentre des messages derreurs, et retournons dans notre diteur.
Faisons de la place sous la ligne 97, dans la zone des variables. Ajoutons alors
Cette fois, tout sest bien pass, lindicateur est rest vert, et, aprs les warnings, nous
obtenons la phrase :
Nous venons de construire notre premier programme, et nous avons dj appris 3 des 35
instructions que comporte le PIC. Qui a dit que ctait compliqu ?
Allez voir maintenant dans votre rpertoire de travail, et vous devriez y trouver 7 fichiers
gnrs par votre application du type essai1.xxx
Remarquez surtout lexistence de votre premier fichier .hex. Le fichier tel quil devrait
tre la fin de ce chapitre, est disponible dans les fichiers dexemples, comme tous les autres
crs par la suite.
45
Notes :
46
8. La simulation dun programme
Nous avons cr, dans le chapitre prcdent, notre premier petit programme en 16F84.
Bien sr, ce programme ne sert strictement rien. Cependant nous allons lutiliser en vue
dexprimenter le simulateur de MPLAB. Une fois ce chapitre vu, vous serez en mesure de :
Commencez donc par lancer MPLAB. Ce dernier connat le nom de votre dernier projet
(essai1.mcp) et louvre automatiquement. Si vous avez procd des essais personnels
depuis, chargez-le depuis le menu project->open . Vous vous retrouvez avec la fentre de
votre dernire leon.
Rappelez-vous que si vous avez un problme, le fichier essai1.asm est disponible dans
les fichiers dexemples fournis avec ce cours. Rappelez-vous alors de lancer la compilation
par la touche <F10>.
Slectionnez le menu : Debugger -> select tool -> MPLAB Sim . Cest tout. De
nouveaux outils apparaissent dans la barre doutils. Notez aussi lapparition de nouveaux
items dans le menu debugger Les connaisseurs de MPLAB5 constaterons que la
procdure est une nouvelle fois beaucoup plus simple.
Si ce nest dj fait, placez la fentre du source fond vers la gauche. Nous allons
donc faire apparatre lcran les informations surveiller. Slectionnez View -> Special
function registers . Une nouvelle fentre souvre. Agrandissez-la et placez la droite de la
fentre du fichier source (ou ailleurs si vous manquez de place).
Vous voyez dans cette fentre le contenu de tous les registres que vous avez dcouverts
dans le tableau 4-2 de la page 13. Dans les chapitres suivants, nous les utiliserons
progressivement tous.
Dans notre petit programme, nous utilisons une variable. Nous allons donc la faire
apparatre. Allez dans le menu View -> watch . Une nouvelle fentre apparat. Vous
disposez de 4 onglets pour y placer 4 sries de variables, cest trs pratique pour debugger.
- Vous double-cliquez dans la case situe juste sous symbol name et vous tapez le nom
de la variable. Si la variable nexiste pas, la mention not found apparat dans la
colonne value , dans le cas contraire, cest la valeur actuelle qui apparat.
47
- Vous double-cliquez dans la case juste sous la colonne Add.. (adresse), et vous entrez
manuellement ladresse (dans ce cas-ci, 0x00E, vous entrez donc E )
- Vous slectionnez le nom dans le fichier source, puis vous cliquez une fois sur la slection
obtenue, et vous tirez la variable vers la fentre Watch en maintenant le bouton
enfonc. Une fois au-dessus, relchez le bouton de la souris ( Drag and drop ).
Notez quau dmarrage, MPLAB suppose que la valeur de votre variable vaut 0 , ce
qui nest pas forcment le cas rellement dans le pic, puisque la RAM prend une valeur
alatoire lors dune procdure de mise sous tension.
Cliquez avec le bouton droit de la souris, puis properties pour indiquer le style
daffichage des valeurs, soit 8 bits et format hexadcimal, mais ceci doit tre fait par dfaut.
48
Pressez ensuite sur <OK> pour fermer cette fentre.
Vous voici prt lancer une simulation. Mais quoi cela pourrait-il vous servir si vous ne
comprenez pas les changements qui vont soprer dans les registres spciaux ? Je vais donc
commencer par vous expliquer les registres de base ncessaires la comprhension du
processus.
Un processeur, quel quil soit est un composant qui excute SEQUENTIELLEMENT une
srie dINSTRUCTIONS organises selon un ensemble appel PROGRAMME.
Il existe donc dans le processeur un SEQUENCEUR, cest dire un compteur qui permet
de pointer sur la PROCHAINE instruction excuter. Ce squenceur est appel suivant les
processeurs compteur ordinal , Pointeur de programme etc. Dans le cas des PICs, il
sappelle PC, pour Program Counter. Le PC nest pas accessible directement par lutilisateur.
Le principe de base est toujours le mme. Dans les PICs, les registres ne font que 8 bits,
on ne peut donc stocker quune adresse maximale de 255. Il faudra donc 2 registres pour
accder une adresse. Les PICs ont un fonctionnement un peu particulier ce sujet.
Nous trouvons tout dabord un registre qui contient ladresse basse du PC, cest dire les
8 bits de poids faibles. Ce registre est accessible en lecture et en criture. Il est appel PCL
(PC Low)
49
Il existe un autre registre de 5 bits qui participe au fonctionnement du squenceur. Il
sappelle PCLATH (PC LATch counter High). Il est accessible en lecture et en criture par
lutilisateur.
Le PC complet tant cod sur 13 bits, il faudra donc complter PCL avec 5 bits
supplmentaires. Il existe deux cas possibles :
- Lors dun saut, par exemple, le contenu du PC est charg directement avec les 11 bits de
destination contenus dans linstruction en elle-mme. Les 2 bits manquants sont extraits
du registre PCLATH.. Les bits 3 et 4, qui doivent tre positionns par lutilisateur, sont
placs directement dans les bits 11 et 12 du PC afin de complter ladresse de destination.
Comme le 16F84 ne gre que 1K de mmoire programme, nous naurons pas besoin de ce
registre dans le cas des sauts. Rappelez-vous que le 16F84 ne gre que 10 des 13 bits du
PC
Remarquez que la limite du PC est de 13 bits, ce qui implique que les PICs de la famille
mid-range auront une capacit de mmoire programme de 8K mots maximum (soit 213).
Il est trs important de se rappeler que le PC pointe toujours sur linstruction suivante,
donc linstruction qui nest pas encore excute. Cest indispensable de bien comprendre ceci
pour analyser les programmes en cours de debuggage.
8.2.2 Le registre W
Ce registre est un registre utilis par les pics pour raliser toutes sortes de calculs.
Souvenez-vous que la destination dun rsultat (d) peut en gnral tre un emplacement RAM
(f) ou le registre de travail (w). Cest un donc un registre fondamental.
Cest un registre dont chaque bit a une signification particulire. Il est principalement
utilis pour tout ce qui concerne les tests. Il est donc galement dune importance
fondamentale. Il est dcrit dans le tableau de la page 15.
Voici les diffrents bits qui le composent, en commenant par le bit0 (b0), donc le bit le
plus droite, ou encore le moins significatif. Remarquez quon utilise le terme LSB, parfois
comme byte le moins significatif, parfois comme bit le moins significatif. Cest galement un
abus de langage, mais le contexte permet trs bien de les distinguer.
50
b1 : DC Digit Carry Ce bit est utilis principalement lorsque lon travaille avec
des nombres BCD : il indique un report du bit 3 vers le bit 4.
Pour info, un nombre BCD est un nombre dont chaque
quartet reprsente un chiffre dcimal. Nous naborderons
pas ce principe ici.
b4 : TO Time-Out bit Ce bit indique (si 0), que la mise en service suit un arrt
provoqu par un dpassement de temps ou une mise en
sommeil. Dans ce cas, PD effectue la distinction.
b5 : RP0 Register Bank Select0 Permet dindiquer dans quelle banque de RAM on
travaille.0 = banque 0.
b6 : RP1 Register Bank Select1 Permet la slection des banques 2 et 3. Inutilis pour le
16F84, doit tre laiss 0 pour garantir la compatibilit
ascendante (portabilit du programme).
Et voil, vous connaissez maintenant 4 des registres. Nous allons pouvoir commencer
simuler notre programme.
Est maintenant indique par une flche verte. La flche verte indique la prochaine ligne
qui sera excute par le simulateur. Vous avez en fait provoqu un Reset de votre programme.
Au lieu dutiliser les touches clavier (plus pratiques), vous pouvez galement utiliser les
nouveaux outils de la barre doutils ou les nouveaux items du menu debugger . La
correspondance est la suivante :
51
<F6> : reset
<F7> : step into (avancer dun pas dans le programme)
<F8> : step over (idem, mais un appel de sous-programme est excut en une fois au lieu
dentrer lintrieur).
- Au dessus de la ligne slectionne, vous trouvez la directive ORG 0x00 qui prcise
que la ligne suivante est ladresse 0x00 : premier bon signe.
Examinons la ligne en question. Elle nous dit que la prochaine instruction, aprs son
excution, sera celle situe ladresse start .
Pressez <F7>. Votre programme est maintenant positionn sur la ligne qui suit ltiquette
start . Il a donc effectu un SAUT, ou encore, rupture de squence.
start
clrf mavariable ; effacer mavariable
MPASM a donc calcul tout seul quel emplacement se situe ltiquette start . Si vous
aviez voulu indiquer ladresse vous-mme, vous auriez d compter toutes les lignes
prcdentes pour voir o vous en tiez. De plus, chaque modification du programme, vous
devriez recalculer toutes les adresses. Heureusement, MPASM le fait pour vous.
Pressez de nouveau <F7> pour excuter cette instruction : Effacer mavariable. Comme
mavariable vaut dj 0, il ne se passe rien au niveau de celle-ci.
ATTENTION, RAPPEL : la mise sous tension, les cases mmoires (RAM) du pic se
trouvent une valeur quelconque. Or, MPLAB ne peut savoir quelle est cette valeur. Il met
donc par dfaut 0. Si vous voulez quune case RAM du PIC contienne effectivement 0, VOUS
ETES OBLIGE DE LE FAIRE VOUS-MEME, sinon, le programme fonctionnera
correctement sur simulateur, mais pas sur circuit rel.
52
Cest donc bien ladresse suivante : pas de saut signifie pas de rupture de squence, donc
fonctionnement squentiel du programme.
Profitons-en pour jeter un il sur la fentre Watch . Vous voyez votre variable
mavariable . Sa valeur est 0x00 (ou H00), et son adresse est 0x0E. Pourquoi ?
Examinons la zone de dclaration des variables :
A ce stade, vous vous demandez ce qui va se passer lorsque votre variable atteindra la
valeur 0xFF ? Bien entendu, vous navez pas envie de presser encore 500 fois la touche <F7>.
On va donc acclrer le processus.
Nous allons donc modifier la valeur de mavariable . Pour ceci, rien de plus simple, il
suffit de double-cliquer sur la case value situe face au nom de mavariable et
dinscrire une nouvelle valeur (en hexadcimal, puisque nous avons choisi ce format.)
La variable mavariable est passe 0. Logique, car 0xFF + 1 = 0x100. Or, 0x100
ncessite 9 bits (256). On obtient donc 00 (et on reporte le bit 8).
Les bits 2, 3 et 4 sont 1, les autres sont 0. Les bits 3 et 4 sont actifs ltat bas (0).
Comme ils sont 1, ils sont donc inactifs.
Reste le bit2. Un coup dil sur le tableau 4-3 nous informe quil sagit du bit Z (pour 0).
Logique, car le rsultat de lopration est 0.
53
Si ce niveau, vous vous demandez pourquoi le bit C (carry) nest pas positionn, bravo,
car vous vous posez les bonnes questions, puisque le rsultat de la dernire incrmentation est
B00000000 et on reporte B1. Mais alors, chapeau pour ceux qui ont pens vrifier le
fonctionnement de linstruction incf page 62 du datasheet. En effet, vous constaterez en
vrifiant que le seul bit affect (modifi) par cette instruction est le bit Z, lexclusion du bit
C : Status affected : Z .
Nous allons clturer par les autres mthodes dexcution du programme par le simulateur.
Pressez <F6> pour ramener le PC 0. Dans le menu Debugger->run vous trouvez toutes
les mthodes possibles : essayez ceci :
- Pressez <F9> pour lancer rapidement le programme sans visualisation. Pressez <F5> pour
larrter l o il est arriv.
- Le menu debugger -> animate vous donne une excution anime, plus lente
lexcution, mais qui vous permet de suivre lexcution du programme.
- Lavance en pas pas avec <F8> vous permet deffectuer la mme chose quavec <F7>,
la diffrence quune sous-routine, que nous verrons plus tard, est excute en une seule
fois, comme si ctait une seule instruction. La touche <F7> entrera dans la sous-routine
pour excuter les instructions une une. Encore une autre mthode : Allez sur la ligne
de votre petit programme. Positionnez votre souris en dbut de ligne et cliquez avec le bouton
de droite. Un menu apparat. Vous pouvez mettre des points darrt dans votre programme.
Vous pouvez galement demander votre programme de dmarrer jusquau point spcifi
(run to cursor), ainsi que dautres options. La fentre trace menu view->trace vous donne
des informations supplmentaires sur la trace du programme. Le menu debugger vous
permet dautres configurations. Lisez laide concernant le simulateur pour des informations
dtailles. Le sous-menu debugger->stimulus controler vous permet par exemple de placer
des points darrts conditionnels.
Un double-clic sur une ligne place galement un point darrt, que vous remarquerez
grce au symbole B qui apparat gauche de la ligne. Un autre double-clic lannule.
Placez un point darrt dans votre programme. Pressez <F6>, puis <F9>, le programme
va sexcuter jusque la ligne rouge, puis passer en stop. Voil encore une nouvelle mthode
pratique pour debugger les longs programmes.
Il existe cependant une nouvelle procdure encore plus rapide : la trace de votre
programme.
Enlevez le point darrt, pressez <F6>, puis slectionnez : view -> simulator trace .
Une nouvelle fentre souvre, avec un message no items to display . Pressez maintenant
<F9> puis quelques fractions de seconde plus tard, <F5>.
Dans la fentre trace , vous obtenez le compte-rendu de toutes les instructions excutes
par votre programme depuis le lancement jusque larrt. Ceci se rvle trs pratique en cas de
plantage inexpliqu par exemple.
54
Il y a encore plein doptions concernant le debugger, je ne peux cependant pas toutes les
expliquer dans le cadre de cet ouvrage. Vous les dcouvrirez petit petit lors de vos
exprimentations, nhsitez pas examiner tous les menus.
55
Notes :
56
9. Le jeu dinstructions
Les instructions sont dtailles partir de la page 57 du datasheet. Il peut donc sembler
inutile de les reprendre dans ce cours. Mais jai finalement opt pour une explication pratique
de ces instructions. Jai choisi en effet de les expliquer avec des petits exemples concrets,
plutt que de simplement traduire le datasheet.
Bien entendu, vous pouvez exprimenter ces instructions avec MPLAB et son simulateur,
en insrant ces instructions aprs ltiquette start de votre programme.
Je vais donc expliquer ces instructions dans un ordre qui me facilite les explications, en
commenant par celles dj vues, dans le but final dobtenir toutes les rfrences aux
instructions dans le mme document.
Cette instruction effectue ce quon appelle un saut inconditionnel, encore appel rupture
de squence synchrone inconditionnelle.
Ceci na aucune espce dimportance pour le 16F84, qui ne dispose que de 1Kmots de
mmoire programme, mais devra tre considr pour les pics de plus grande capacit
(16F876). Nous en reparlerons dans la seconde partie.
Souvenez-vous, que pour le 16F84 : Adresse de saut = adresse relle. Vous ne devez donc
vous proccuper de rien. Pour les autres, en cas de dbordement, MPLAB vous le signalera.
Syntaxe
goto etiquette
Exemple
Start
goto plusloin ; le programme saute linstruction qui suit ltiquette
; plusloin
xxxxxxxx
plusloin
57
xxxxxxxx ; instruction excute aprs le saut : le programme se poursuit ici
Syntaxe
incf f,d
Comme pour toutes les instructions, f reprsente File , cest dire lemplacement
mmoire concern pour cette opration, d , quant lui: reprsente la Destination.
La formule est donc (f) + 1 -> (d) : Les parenthses signifient le contenu de . Soit, en
franais : Le contenu de lemplacement spcifi est incrment de 1, le rsultat est plac dans
lemplacement dsign par d . Emplacement qui pourra tre soit lemplacement spcifi
par f , soit laccumulateur, (f) restant dans ce cas inchang.
Etant donn que la seule manire, en incrmentant un octet, dobtenir 0, est de passer de
0xFF 0x00. Le report nest pas ncessaire, puisquil va de soi. Si, aprs une incrmentation,
vous obtenez Z=1 , cest que vous avez dbord. Z vaudra donc 1 si (f) avant lexcution
valait 0xFF.
Exemples
58
9.3 Linstruction DECF (DECRement File)
Syntaxe
Exemples
Cette instruction charge la valeur spcifie (valeur littrale, ou encore valeur immdiate),
dans le registre de travail W.
Syntaxe
Exemple
Syntaxe
Une fois de plus, seul le bit Z est affect (si f vaut 0, Z vaut 1).
Exemple 1
59
Pour cette instruction, je vais me montrer beaucoup plus explicite. Vous allez comprendre
pourquoi
ATTENTION
Il est impratif ici de bien faire la distinction entre movlw k et movf f,w.
Dans le premier cas, cest la VALEUR qui est charge dans w, dans le second cest le
CONTENU de lemplacement spcifi. Si nous nous rappelons, dans la leon prcdente que
mavariable reprsentait ladresse 0x0E de notre zone de RAM. Supposons maintenant que
mavariable contienne 0x50.
movlw mavariable
movlw 0x0E
Aprs linstruction, nous aurons 0x0E dans le registre W. Nous parlerons dans ce cas dun
ADRESSAGE IMMEDIAT. Le droulement est du type f -> (d) (f nest pas entre
parenthses).
movf mavariable , w
movf 0x0E , w
Ce qui signifie : charger le CONTENU de lemplacement 0x0E dans w. Nous parlerons ici
dun ADRESSAGE DIRECT. Je rappelle quil est primordial de ne pas confondre, sinon,
vous ne comprendrez plus rien lors de la ralisation des programmes.
Aprs cette instruction, W contient donc 0x50. Le droulement est du type (f) -> (d).
Exemple 2
movf mavariable , f
Que fait cette instruction ? Si vous avez tout suivi, elle place le CONTENU de mavariable
dans mavariable. Dire que cela ne sert rien est tentant mais prmatur. En effet, si le contenu
de mavariable reste bien inchang, par contre le bit Z est positionn. Cette instruction permet
donc de vrifier si (mavariable) = 0.
60
9.6 Linstruction Movwf (MOVe W to File)
Syntaxe
Aucun
Exemple
Cette opration permet dajouter une valeur littrale (adressage immdiat) au contenu du
registre de travail W.
Syntaxe
Ne vous inquitez pas trop pour DC, il nest utilis que pour les oprations sur les
quartets, par exemple, les nombres Binary Coded Decimal.
Exemple
Ne pas confondre avec linstruction prcdente. Une nouvelle fois, il sagit ici dun
ADRESSAGE DIRECT. Le CONTENU du registre W est ajout au CONTENU du registre F
Syntaxe
61
Bits du registre STATUS affects
C, DC, et Z
Exemple
Syntaxe
C, DC, Z
Notez ici que le bit C fonctionne de manire inverse que pour laddition. Ceci est commun
la plupart des microprocesseurs du march. Les autres utilisent parfois un bit spcifique
pour la soustraction, bit le plus souvent appel borrow (emprunt).
Ceci est logique, et sexplique en faisant une soustraction manuelle. Le bit C reprsente le
me
9 bit ajout doffice la valeur initiale. Si on effectue une soustraction manuelle donnant
une valeur <0, on obtient donc une valeur finale sur 8 bits, le report obtenu venant soustraire
le bit C. Si le rsultat est >0, il ny a pas de report, le rsultat final reste donc sur 9 bits.
Exemple 1
62
Effectuons cette opration manuellement :
C b7 b6 b5 b4 b3 b2 b1 b0 Dec
1 0 0 0 0 0 0 1 010 2
- 0 0 0 0 0 0 0 01 1 1
= 1 0 0 0 0 0 0 0 1 1
Comment procder ? Et bien, comme pour une soustraction dcimale. On commence par
les bits de droite : 0-1, a ne passe pas, donc on emprunte 10 (not en exposant vert), et on
soustraira videmment une unit supplmentaire au bit b1. On a donc :B 10 B1, car
souvenez-vous quon a emprunt 10 en BINAIRE. Rsultat 1. On soustrait ensuite les b1 : on
aura 1 0 lemprunt, donc 1-0-1 = 0. On continue de droite gauche jusquau 9me bit qui
est le carry. Rsultat final : B00000001 et carry 1, C.Q.F.D.
Exemple 2
C b7 b6 b5 b4 b3 b2 b1 b0 Dec
1 0 0 0 0 0 0 1 0 2
- 0 0 0 0 0 0 0 1 0 2
= 1 0 0 0 0 0 0 0 0 0
Exemple 3
C b7 b6 b5 b4 b3 b2 b1 b0 Dec
1 010 010 010 010 010 010 110 010 2
- 01 01 01 01 01 01 01 11 1 3
= 0 1 1 1 1 1 1 1 1 -1
Comme ce dernier vaut 0, vous tes AVERTI que le rsultat de lopration est ngatif. Or,
comment savoir la valeur absolue dun nombre ngatif ? En prenant son complment 2.
Rappelez-vous :
Complment 1 de B11111111 = B00000000 (on inverse tous les bits)
Complment 2 = complment 1 + 1, donc B00000001.
63
La preuve, si vous ajoutez 1 1, vous obtenez B11111111 + B00000001 =
B00000000 = 0.
Vous matrisez maintenant les soustractions. Certains auront sans doute pens que
jexpliquais trop en dtail, mais mon exprience ma appris que les soustractions
reprsentaient souvent un cueil dans la ralisation de trop de programmes.
Encore un dernier dtail : Pour effectuer une soustraction de 1, vous pouvez bien entendu
effectuer une addition de 1. Le rsultat sera strictement le mme, votre charge dinterprter
les bits Z et C. Je vous laisse le faire vous-mme pour vous convaincre.
Nous restons dans les soustractions, mais, cette fois, au lieu dun adressage immdiat,
nous avons un ADRESSAGE DIRECT.
Syntaxe
C , DC , Z
Exemple
Cette instruction effectue une opration AND BIT A BIT entre le contenu de W et la
valeur littrale qui suit.
Syntaxe
Exemple
64
movlw B11001101 ; charger w
andlw B11110000 ; effectuer un and (&)
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 0 1 1 0 1
And 1 1 1 1 0 0 0 0
= 1 1 0 0 0 0 0 0
Rappelez-vous quon effectue un AND entre chaque bit de mme rang. Seuls restent donc
positionns 1 les bits dont les 2 oprandes valent 1. Donc, le fait deffectuer un AND avec la
valeur B11110000 MASQUE les bits 0 3, et ne laisse subsister que les bits 4 7.
Tant que vous ne jonglerez pas avec lhexadcimal, je vous conseille de toujours traduire les
nombres en binaires pour toutes les instructions concernant les bits.
Maintenant, vous devriez avoir bien compris. De nouveau la mme opration, mais en
ADRESSAGE DIRECT. Je vais donc acclrer les explications.
Syntaxe
Exemple
Et oui, les mmes instructions, mais pour le OU inclusif. Inclusif signifie simplement le
contraire dexclusif, cest dire que le bit de rsultat vaudra 1 si un des bits, OU LES DEUX
BITS, oprandes =1.
Syntaxe
65
Exemple
b7 b6 b5 b4 b3 b2 b1 b0
1 1 0 0 0 0 1 1
OR 0 0 0 0 1 1 1 1
= 1 1 0 0 1 1 1 1
Donc, avec un ou inclusif (OR), on peut FORCER nimporte quel bit 1 (pour rappel,
avec AND, on peut forcer nimporte quel bit 0).
Syntaxe
Cette instruction peut donc servir INVERSER nimporte quel bit dun octet. En effet, si
vous effectuez 1 xor 0 , vous obtenez 1, si vous effectuez 0 xor 0 , vous obtenez 0.
Donc, si vous appliquez xor 0, la valeur de dpart est inchange.
Si par contre vous appliquez 0 xor 1 , vous obtenez 1, et avec 1 xor 1 , vous
obtenez 0. En appliquant xor 1, vous inversez le bit, quelque soit son tat initial.
Maintenant, vous pouvez donc FORCER un bit 1 avec OR, MASQUER un bit (le mettre
0) avec AND, et lINVERSER avec XOR.
Syntaxe
66
Exemple
b7 b6 B5 B4 b3 b2 b1 b0
1 1 0 0 0 1 0 1
Xor 0 0 0 0 1 1 1 1
= 1 1 0 0 1 0 1 0
Remarquez que tous les bits de loctet initial ont t inverss par chaque bit du second
oprande qui tait 1.
Syntaxe
Cest une instruction qui permet tout simplement de forcer directement un bit dun
emplacement mmoire 1.
Syntaxe
Aucun
Exemples
67
9.18 Linstruction BCF (Bit Clear F)
Cest une instruction qui permet tout simplement de forcer directement un bit dun
emplacement mmoire 0.
Syntaxe
Aucun
Exemples
Les oprations de dcalage sont des oprations trs souvent utilises. Les PICs ont la
particularit de ne disposer que dinstructions de ROTATION. Vous allez voir quavec ces
instructions, on peut trs facilement raliser des dcalages.
Syntaxe
Exemple1
68
C b7 b6 b5 b4 b3 b2 b1 b0
F 1 0 0 0 1 0 1 1 1
Rlf 0 0 0 1 0 1 1 1 1
Vous voyez que tous les bits ont t dcals vers la gauche. C a t rintroduit dans
b0. Le rsultat reste sur 9 bits.
Exemple 2
Si vous avez compris, le rsultat sera B00101110, avec le carry 0. Si le carry tait 0
au dpart, on effectue un simple dcalage vers la gauche. Que se passe-t-il si, en dcimal, on
effectue ce type dopration ?
Prenons le nombre 125 et dcalons-le vers la gauche en dcimal, nous obtenons 1250.
Nous avons multipli le nombre par sa base (dcimal = base 10). Et bien cest la mme chose
en binaire (une fois de plus).
Syntaxe
Exemple1
69
b7 b6 b5 B4 b3 b2 b1 b0 C
F 0 0 0 1 0 1 1 1 1
Rrf 1 0 0 0 1 0 1 1 1
Vous voyez que tous les bits ont t dcals vers la droite. C a t rintroduit dans b7. Le
rsultat reste sur 9 bits.
Exemple 2
Si vous avez compris, le rsultat sera B00001011, avec le carry 1. Si le carry est 0 au
dpart, on effectue un simple dcalage vers la droite.
Que sest-il pass ? Et bien notre nombre de dpart, soit 23 en dcimal est devenu 11. Le
carry reprsente le bit -1 , donc, la moiti du bit 0, donc . En effet, en dcimal, le chiffre
1 derrire les units a comme valeur 1/base, donc 1/10. En binaire ce sera donc .
Si nous regardons alors les 9 bits, nous obtenons 11 . Nous avons donc effectu une
DIVISION PAR 2. Retenez ceci, cela vous sera galement trs utile par la suite.
Traduit littralement, cela donne : Teste le bit de lemplacement mmoire et saute sil vaut
0. Il sagit ici de votre premier SAUT CONDITIONNEL, ou RUPTURE DE SEQUENCE
SYNCHRONE CONDITIONNELLE .
Notez que dans ce cas linstruction prendra 2 cycles, sinon, elle nutilisera quun cycle. De
plus, il faut retenir que pour tous ces types de saut, ON NE SAUTE QUE lINSTRUCTION
SUIVANTE. En effet, la syntaxe ne contient pas dadresse de saut, comme nous allons le voir
Syntaxe
Aucun
Exemple1
70
Voici un exemple dans lequel on doit excuter une seule instruction supplmentaire si
le bit vaut 1.
Exemple 2
Que faire si les traitements ncessitent plusieurs instructions ? Et bien, on combine les
sauts conditionnels avec les saut inconditionnels (par exemple goto).
Ces procdures sont les mmes pour tous les sauts inconditionnels, je ne les dtaillerai
donc pas avec autant dexplications.
Traduit littralement, cela donne : Teste le bit de lemplacement mmoire et saute sil
vaut 1. Toutes les remarques de linstruction BTFSC restent valables.
Syntaxe
Aucun
Exemple
btfss STATUS,C ; tester si le bit C du registre STATUS vaut 1
bsf mavariable,2 ; non (C=0), alors bit 2 de mavariable mis 1
xxxx ; la suite du programme est ici dans les 2 cas
71
9.23 Linstruction DECFSZ (DECrement F, Skip if Z)
Nous poursuivons les sauts conditionnels avec une instruction trs utilise pour crer
des boucles. Cette instruction dcrmente un emplacement mmoire et saute linstruction
suivante si le rsultat de la dcrmentation donne une valeur nulle.
Syntaxe
Aucun
Exemple1
ATTENTION
la boucle naurait jamais de fin, car la variable compteur ne serait jamais modifie.
- Si vous placez 0 dans le compteur de boucles, elle sera excute 256 fois. Si vous ne
dsirez pas quelle soit excute dans cette circonstance, vous devez ajouter un test AVANT
lexcution de la premire boucle, comme dans lexemple suivant :
Exemple 2
72
decfsz compteur , f ; dcrmenter compteur et tester sa valeur
goto boucle ; si compteur pas 0, on boucle
suite ; on saute directement ici si compteur = 0
movf mavariable , w ; on charge la valeur obtenue dans w
Je ne vais pas dtailler cette instruction, car elle est strictement identique la
prcdente, hormis le fait quon incrmente la variable au lieu de la dcrmenter.
Syntaxe
Aucun
Nous pouvons traduire cette instruction par inverser les quartets dans F . Cette
opration inverse simplement le quartet (demi-octet) de poids faible avec celui de poids fort.
Syntaxe
Aucun : cette particularit nous sera trs utile lorsque nous verrons les interruptions.
Exemple
73
Syntaxe
Mcanisme
Attention, cette pile a une taille limite 8 emplacements. Il nexiste aucun moyen de
tester la pile, vous devez donc grer vos sous-programmes pour ne pas dpasser 8
emplacements, sinon, votre programme se plantera.
Notez que lorsque vous sortez dun sous-programme, lemplacement est videmment
libr. La limite nest donc pas dans le nombre de fois que vous appelez votre sous-
programme, mais dans le nombre dimbrications (sous-programme qui en appelle un autre qui
en appelle un autre) etc.
Aucun
Retour de sous-routine. Va toujours de pair avec une instruction call. Cette instruction
indique la fin de la portion de programme considre comme sous-routine (SR). Rappelez-
vous que pour chaque instruction call rencontre, votre programme devra rencontrer une
instruction return .
Syntaxe
Aucun
Exemples
Comme ceci est un concept trs important, je vais dtailler un peu plus.
74
Imaginons un programme qui a besoin dune petite temporisation (comme chaque
instruction prend du temps, on peut sarranger pour en faire perdre volontairement au
programme afin de retarder son fonctionnement. Ecrivons-la :
Imaginons maintenant que cette petite temporisation soit appele rgulirement par
notre programme principal. Ecrivons quoi ressemble le programme principal :
75
Ceci nest pas lgant, car, si nous devons changer la valeur de notre tempo, nous devons
la changer partout dans le programme, sans oublier un seul endroit. De plus, a prend
beaucoup de place.
On peut galement se dire : utilisons une macro , qui, rappelez-vous, effectue une
substitution au moment de lassemblage. Cest vrai, qualors, il ny a plus quun endroit
modifier, mais, dans notre PIC, le code se retrouvera cependant autant de fois quon a utilis
la temporisation. Que de place perdue, surtout si la portion de code est grande et utilise
plusieurs fois.
Pour remdier ceci, nous utiliserons la technique des sous-programmes. Premire tape,
modifions notre temporisation pour en faire une sous-routine :
Deuxime tape, nous modifions notre programme principal pour que chaque fois que
nous avons besoin dune tempo, il appelle le sous-programme. Nous obtenons :
Dans ce cas, la routine tempo nest prsente quune seule fois en mmoire programme.
On peut amliorer : supposons que nous dsirons une temporisation dure variable.
On modifie la sous-routine en supprimant la valeur dinitialisation, et on place celle-ci
dans le programme principal. Cela sappelle un sous-programme avec passage de
paramtre(s).
76
xxx ; instruction quelconque
xxx ; instruction quelconque
xxx ; instruction quelconque
xxx ; instruction quelconque
movlw 0x25 ; charger w avec 0x25
call tempo ; appel du sous programme tempo dune dure de 0x25
xxx ; instruction quelconque, le programme continue ici
xxx ; instruction quelconque
xxx ; instruction quelconque
movlw 0x50 ; charger w avec 0x50
call tempo ; appel du sous programme tempo dune dure de 0x50
xxx ; instruction quelconque, le programme continue ici
xxx ; instruction quelconque
movlw 0x10 ; charger w avec 0x10
call tempo ; appel du sous programme tempo dune dure de 0x10
xxx ; instruction quelconque, le programme continue ici
Retour de sous-routine avec valeur littrale dans W. Cest une instruction trs simple : elle
quivaut linstruction return, mais permet de sortir dune sous-routine avec une valeur
spcifie dans W.
Syntaxe
Aucun
Exemple
Cette instruction indique un retour dinterruption (nous verrons ultrieurement ce que sont
les interruptions). Cette instruction agit dune manire identique RETURN, except que les
interruptions sont remises automatiquement en service au moment du retour au programme
principal.
77
Syntaxe
Aucun
Syntaxe
clrf f ; (f) = 0
Exemple
Syntaxe
clrw ; (w) = 0
Cest une instruction qui nest pas vraiment indispensable, car on pourrait utiliser
linstruction movlw 0 . La diffrence est que dans ce cas, le bit Z nest pas affect.
78
Le mcanisme est simple comprendre : il sagit pour votre programme denvoyer cette
instruction intervalles rguliers. Si la commande nest pas reue dans le dlai imparti, le PIC
redmarre ladresse 0x00. Cest exactement le mcanisme utilis par les conducteurs de
train qui doivent presser un bouton intervalle rgulier. Si le bouton nest pas press, le train
sarrte. On dtecte ainsi si le conducteur est toujours dans ltat dattention requis.
Syntaxe
Aucun
Syntaxe
Exemple
Astuce : en utilisant cette instruction, on peut galement tester si mavariable vaut 0xFF.
En effet, si cest le cas, W vaudra 0 et Z vaudra donc 1.
Place le PIC en mode de sommeil. Il ne se rveillera que sous certaines conditions que
nous verrons plus tard.
Syntaxe
79
Bit du registre STATUS affect
T0, PD
Comme vous devez tre fatigu, et moi aussi, je vous prsente linstruction qui ne fait
rien, qui ne positionne rien, et qui ne modifie rien. On pourrait croire quelle ne sert rien. En
fait elle est surtout utilise pour perdre du temps, par exemple pour attendre une ou deux
instructions, le temps quune acquisition ai pu se faire, par exemple. Nous lutiliserons donc
loccasion.
Syntaxe
Ceci termine lanalyse des 35 instructions utilises normalement dans les PICs mid-
range.
Ceci peut vous paratre ardu, mais en pratiquant quelque peu, vous connatrez trs vite
toutes ces instructions par cur. Pensez pour vous consoler que certains processeurs CISC
disposent de plusieurs centaines dinstructions.
Il reste 2 instructions qui taient utilises dans les prcdentes versions de PICs. Elles sont
encore reconnues par le PIC 16F84 mais leur utilisation est dconseille par Microchip. En
effet, leur compatibilit future nest pas garantie.
Ces instructions ne sont plus ncessaires actuellement, car ces registres sont dsormais
accessibles directement laide des instructions classiques. Je vous conseille donc fortement
dviter de les utiliser, sous peine de rencontrer des problmes avec les futures versions de
PIC de Microchip.
Je ne vous les ai donc prsentes que pour vous permettre de comprendre un ventuel
programme crit par quelquun dautre qui les aurait utilises.
80
10. Les modes dadressage
Les instructions utilisent toutes une manire particulire daccder aux informations
quelles manipulent. Ces mthodes sont appeles modes dadressage .
Exemple
Avec l ADRESSAGE DIRECT, vous pouvez dire : je vais mettre le contenu du coffre
numro 10 dans ma poche. Ici, lemplacement contenant la valeur utile est donn
DIRECTement dans la phrase. Mais il faut dabord aller ouvrir le coffre pour savoir ce que
lon va effectivement mettre en poche. On ne met donc pas en poche le numro du coffre,
mais ce quil contient. Pour faire lanalogie avec les syntaxes prcdentes, je peux dire que je
mets (coffre 10) dans ma poche.
Exemple
Vous devez donc allez demander ce prpos quil vous donne le numro du coffre que
vous irez ouvrir pour prendre largent. On ne met donc en poche, ni le numro du prpos, ni
le numro du coffre que celui-ci va vous donner. Il y a donc 2 oprations pralables avant de
connatre la somme que vous empocherez.
Cet adressage fait appel 2 registres, dont un est particulier, car il nexiste pas vraiment.
Examinons-les donc :
81
10.3.1 Les registres FSR et INDF
Ceux qui suivent sont dj en train de chercher dans le tableau 4-2 aprs INDF.
INDF signifie INDirect File. Vous le voyez maintenant ? Et oui, cest le fameux registre
de ladresse 0x00. Ce registre nexiste pas vraiment, ce nest quun procd daccs
particulier FSR utilis par le PIC pour des raisons de facilit de construction lectronique
interne.
Le registre FSR est ladresse 0x04 dans les 2 banques. Il nest donc pas ncessaire de
changer de banque pour y accder, quelle que soit la banque en cours dutilisation.
On peut donc dire que INDF est en fait le registre FSR utilis pour accder la case
mmoire. Donc, quand on veut modifier la case mmoire pointe, on modifie FSR, quand on
veut connatre ladresse de la case pointe, on accde galement FSR. Si on veut accder au
CONTENU de la case pointe, on accde via INDF. Nous allons voir tout ceci par un petit
exemple, mais avant,
ATTENTION
Le contenu du registre FSR pointe sur une adresse en 8 bits. Or, sur certains PICs, la
zone RAM contient 4 banques (16F876). Ladresse complte est donc une adresse sur 9 bits.
Ladresse complte est obtenue, en adressage DIRECT, par lajout des bits 7 et 8 sous
forme de RP0et RP1 (RP1 est inutilis pour le 16F84 car seulement 2 banques), et par lajout
du bit IRP dans le cas de ladressage INDIRECT (inutilis sur le 16F84). Veillez donc
toujours laisser IRP (dans le registre STATUS) et RP1 0 pour assurer la portabilit de votre
programme.
Exemple
82
10.4 Quelques exemples
Je vais me rpter, mais les modes dadressages doivent imprativement tre compris.
En multipliant les exemples, jespre que tout le monde pourra comprendre. Pour les habitus
des processeurs divers, excusez ces rptitions. Les registres sont initialiss avec les valeurs
prcdentes.
movlw mavariable
movf mavariable , w
Cette fois, cest de ladressage DIRECT, donc, on va ladresse mavariable voir ce quil y
a lintrieur. On y trouve le CONTENU de mavariable, donc (w) = 0x50 (dans notre
exemple). Pour lassembleur, mavariable sera remplace par 0x0E , donc movf 0x0E,w
movf INDF , w
movf FSR , w
Ceci est un pige. Cest en effet de ladressage DIRECT. On placera donc dans (W) le
CONTENU du registre FSR, donc 0X0E (ladresse pointe) sera mis dans (W).
Je terminerai avec un petit mot pour les spcialistes des microprocesseurs qui lisent ce
cours comme mise niveau.
Vous aurez donc constat que je ne parle nulle part des modes dadressage de type
index (pr et post, avec ou sans offset). En fait, cest tout simplement parce que ce mode
dadressage nexiste pas dans les PICs 16F.
Il vous faudra donc faire preuve dastuce pour compenser ces lacunes.
Il est logique que la facilit dapprentissage et de mise en uvre se paye par une moins
grande souplesse de cration des applications.
83
Notes :
84
11. Ralisation dun programme embarqu
On dsigne gnralement sous la dnomination logiciel embarqu un programme
destin tourner localement sur une carte disposant dun microcontrleur. Nous allons donc
commencer la partie la plus amusante. Nous allons crer de petits programmes sur une carte
PIC.
Utilisez une platine dessais constitue de petits trous relis ensemble par ranges. Les
liaisons seffectuent alors en fils volants. Vous trouverez ces platines chez tous les marchands
dlectronique. Pour mettre ces leons en pratique, il vous faudra le matriel suivant
(rcuprable et peu onreux) :
Cet ensemble ne vous ruinera pas. De plus, les composants pourront tre rcuprs pour
vos prochaines applications. Vous verrez que les PICs peuvent tre utiliss dans des tonnes
dapplications au quotidien. Bien entendu, nomettez pas de vous construire un
programmateur de PICs. Voyez lannexe A1.8 pour plus de dtails.
85
Une fois tout ceci fait, vrifiez une dernire fois, sans placer le PIC avec son support dans
le support de la platine, puis mettez sous tension. Vrifiez si les tensions sont correctes au
niveau des broches dalimentation du PIC.
Effectuez une copie de votre fichier m16F84.asm, et renommez cette copie Led_cli.asm.
Lancez MPLAB et rpondez non lorsquon vous demande si vous voulez charger Essai1.
Dans MPLAB, vous savez maintenant crer un projet. Crez donc le projet Led_cli
dans votre rpertoire de travail (project->new project). Si vous avez une fentre untitled
lcran, fermez-la pralablement.
86
Noubliez pas bien sr douvrir votre fichier Led_cli.asm .De nouveau, ce fichier est
disponible en annexe.
;**************************************************************************
; PROGRAMME DE CLIGNOTEMENT D'UNE LED CONNECTEE SUR LE PORTA.2 *
; D'UN PIC16F84. PROGRAMME D'ENTRAINEMENT AU FONCTIONNEMENT *
; DES PICS. *
;**************************************************************************
; *
; NOM: LED-CLI *
; Date: 09/02/2001 *
; Version: 1.0 *
; Circuit: Platine d'essais *
; Auteur: Bigonoff *
;**************************************************************************
; *
; Fichier requis: P16F84.inc *
; *
;**************************************************************************
; *
; Notes: Ce petit programme permet de faire clignoter une LED *
; sur le port A.2 une frquence de 1Hz *
; Ce programme fait partie de la leon 6 des cours *
; *
;**************************************************************************
87
Jai inclus les commentaires dans le fichier de faon ce quil soit plus rapidement
modifiable sans devoir recourir au datasheet. Je vais donner un brin dexplication.
Remarquez quon effectue un AND (&) entre les diffrentes valeurs, les niveaux actifs
sont donc des niveaux 0, puisquun AND ne permet dimposer que des 0 . Vous devez
donc prciser toutes les valeurs que vous nutilisez pas.
Le premier paramtre prcise si votre PIC sera protg ou non contre la lecture la fin de
la programmation. Laissez ici ce paramtre sur CP_OFF = non protg.
Le second paramtre prcise si le chien de garde (watchdog) est mis ou non en service.
Dans un premier temps, remplacez WDT_ON par WDT_OFF pour le mettre hors-service.
Ensuite, laissez PWRTE sur ON pour prciser que vous utilisez un reset scuris , donc
avec un allongement du temps avant dmarrage. Ceci vous met labri des alimentations un
peu lentes dmarrer. Jexpliquerai ceci plus tard.
Enfin, vient le fonctionnement de loscillateur que vous allez utiliser. Le tableau 8-1 page
40 donne les valeurs recommandes en fonction des frquences utilises pour un PIC de
10MHz.
Retenez que la valeur _HS_OSC convient pour les frquences leves, ce qui est notre
cas, puisque nous utilisons la vitesse maximale de notre PIC. Si vous avez achet une version
10 ou 20MHz, pas de panique, le mode HS_OSC fonctionnera galement.
Mme, si en pratique, les PICs sont des composants trs solides, vitez de vous tromper
ce niveau. Et voil, vous connaissez parfaitement _Config. Vous avez maintenant la ligne
suivante :
Si vous regardez le tableau 4-2, vous constaterez que ce registre se trouve ladresse
0x81, donc dans la banque1. Dans les fichiers include de MPLAB, ce registre est dclar avec
le nom OPTION_REG.
Cest donc ce nom que vous devrez utiliser. Nous allons le dtailler ici. Ce registre est un
registre de bits, cest dire que chaque bit a un rle particulier :
Le tableau de la page 16 reprsente le contenu de ce registre :
88
b7 : RBPU
Quand ce bit est mis 0 (actif niveau bas en italique), une rsistance de rappel au +5
volt est place sur chaque pin du PORTB. Nous verrons dans cette leon le fonctionnement du
PORTB. Si vous regardez notre schma, vous constaterez que le bouton-poussoir connect sur
RB2 place cette pin la masse si on le presse.
Il nexiste aucune possibilit pour envoyer du +5V dans notre schma. En validant
cette option, la rsistance interne force la pin RB2 1 lorsque le bouton nest pas press.
Notez que cette option valide les rsistances sur toutes les pins du PORTB. Il nest donc
pas possible de choisir certaines rsistances en particulier. De mme cette fonction nexiste
que pour le PORTB.
Vous constatez donc dj que tous les ports ne sont pas identiques : il faut y penser au
moment de la conception dun circuit. Dans notre cas, nous mettrons donc les rsistances en
service avec b7 = 0
b6 : INTEDG
Donne, dans le cas o on utilise les interruptions sur RB0, le sens de dclenchement de
linterruption. Si b6 = 1, on a interruption si le niveau sur RB0 passe de 0 vers 1. Si b6 = 0,
linterruption seffectuera lors de la transition de 1 vers 0.
Comme nous nutilisons pas les interruptions dans cette leon, nous pouvons laisser b6 =
0.
b5 : TOCS
Ce bit dtermine le fonctionnement du timer0, que nous verrons bientt. Retenez que le
timer0 est incrment soit en fonction de lhorloge interne (synchronis au programme) , dans
ce cas b5 = 0, soit il compte les impulsions reues sur la pin RA4, dans ce cas b5=1.
b4 : TOSE
Donne, pour le cas ou le bit 5 serait 1, le sens de la transition qui dtermine le comptage
de tmr0. Si b4 = 1, on a comptage si le signal passe de 5V 0V sur RA4, si on a b4 = 0, ce
sera le contraire.
Comme nous avons plac b5=0, b4 est alors inutilis. Nous laisserons donc b4 = 0.
b3 : PSA
Nous avons dans le PIC un prdiviseur. Quest-ce que cest ? Et bien tout simplement,
ceci indique le nombre de pulses qui devra tre reu pour provoquer une incrmentation de la
destination. Nous y reviendrons en dtail avec le fonctionnement du tmr0.
89
A ce niveau, sachez simplement que ce prdiviseur peut servir une des deux fonctions
suivantes (et pas les deux) : soit il effectue une prdivision au niveau du timer du watchdog
(b3 = 1), soit il effectue une prdivision au niveau du tmr0 (timer0) (b3=0). Dans notre cas,
mettez b3 = 1 (nous verrons ci-dessous pourquoi).
Ces trois bits dterminent la valeur de prdivision pour le registre dtermin ci-dessus. Il y
a donc 8 valeurs possibles, montres dans le petit tableau de la page 16.
Remarquez que les valeurs sont diffrentes pour le watchdog et pour tmr0. En effet, il ny
a pas de division par 1 pour ce dernier registre.
Si vous dsirez ne pas utiliser de prdiviseur du tout, la seule mthode est de mettre b3=1
(prdiviseur sur watchdog) et PS2 PS0 0. Dans ce cas : pas de prdiviseur sur tmr0, et
prdiviseur 1 sur watchdog, ce qui correspond pas de prdiviseur non plus. Nous mettrons
donc b2=b1=b0= 0.
Voil encore un registre vu. Nous utiliserons donc la valeur B00001000 pour notre
programme, soit 0x08. Jai lhabitude de ne pas traner des valeurs fixes travers mes
programmes, afin den faciliter la maintenance. Je place ces valeurs en dbut de programme
en utilisant des assignations ou des dfinitions.
Lassignation est dj cre plus bas dans le programme. Jai cr une CONSTANTE que
jai appel OPTIONVAL et qui contiendra la valeur placer plus tard dans le registre
OPTION_REG. Je rappelle que les CONSTANTES noccupent pas de place dans le PIC, elles
sont simplement remplaces par lassembleur au moment de la compilation. Elles servent
faciliter la lecture du programme.
Cherchez donc plus bas dans le programme aprs les assignations, et remplacez la valeur
affecte OPTIONVAL par celle que nous avons trouve et ajoutez vos commentaires.
Supprimez lassignation concernant INTERMASK, car nous ne nous servirons pas des
interruptions dans ce premier programme. Dans la zone des assignations, il vous reste donc
ceci :
;*********************************************************************
; ASSIGNATIONS *
;*********************************************************************
Descendons encore jusqu la zone des dfinitions. Nous allons donner un nom notre
bouton-poussoir et notre LED.
90
Les instructions bcf et bsf que nous allons utiliser pour mettre ou lire des 1 ou des 0 dans
les registres ont la syntaxe suivante bsf f , n et comme le registre daccs sappelant PORTA
(pour le port A) et PORTB (pour le port B), nous utiliserons des DEFINE permettant
dintgrer f et n en mme temps.
Nous voyons sur le schma que la LED est connecte sur le bit 2 du port A. Le bouton-
poussoir est connect sur le bit 2 du port B. Nous effaons donc les dfinitions dexemple, et
nous les remplaons par les ntres. Nous obtenons alors ceci :
;*********************************************************************
; DEFINE *
;*********************************************************************
#DEFINE LED PORTA,2 ; Led rouge
#DEFINE BOUTON PORTB,2 ; bouton-poussoir
Notez que LED et BOUTON sont des noms que nous avons librement choisis,
condition quil ne sagisse pas dun mot-cl. Pas question par exemple dutiliser STATUS ou
encore MOVLW, bien que ce dernier exemple soit tir par les cheveux, cela pourrait vous
arriver un jour dutiliser un mot rserv par inadvertance. A quoi servent les dfinitions ?
Et bien supposons que vous dcidez de connecter la LED sur le PORTB bit 1 (RB1), par
exemple. Et bien, nul besoin de rechercher partout dans le programme, il suffira de changer
dans la zone DEFINE.
On descend encore un peu, et on arrive dans la zone des macros. Nous nen avons pas
vraiment besoin ici, mais nous allons quant mme les utiliser titre dexemple.
Effacez la macro donne titre dexemple et entrons celles-ci.
;*********************************************************************
; MACRO *
;*********************************************************************
LEDON macro
bsf LED
endm
LEDOFF macro
bcf LED
endm
la premire colonne donne le nom de la macro (ici, 2 macros, une LEDON et une
LEDOFF). La directive macro signifie dbut de la macro la directive endm signifie fin de la
macro. Notez que les macros peuvent videmment comporter plusieurs lignes de code.
Prenons notre exemple : quand nous utiliserons la ligne suivante dans notre
programme (attention, ne pas mettre la macro en premire colonne) :
LEDON
bsf LED
Il remplacera galement LED par PORTA,2. Ce qui fait quen ralit nous obtiendrons :
91
bsf PORTA , 2
Nous avons donc obtenu une facilit dcriture et de maintenance. Gardez lesprit que
les macros sont des simples substitutions de traitement de texte. Si votre macro se compose de
50 lignes de code, les 50 lignes seront copies dans le PIC chaque appel de la macro.
Nous arrivons dans la zone des variables. Nous ajouterons celles-ci au fur et mesure de
leur ncessit. Effacez donc les 2 variables prsentes, car elles sont utilises dans les routines
dinterruption que nous nutiliserons pas ici.
;*********************************************************************
; DECLARATIONS DE VARIABLES *
;*********************************************************************
CBLOCK 0x00C ; dbut de la zone variables
ENDC ; Fin de la zone
Comme nous nutiliserons pas les interruptions, supprimez tout ce qui suit jusqu la
routine dinitialisation, vous obtenez :
**********************************************************************
; DEMARRAGE SUR RESET *
;*********************************************************************
;*********************************************************************
; INITIALISATIONS *
;*********************************************************************
suite du programme
A ce stade, avant de poursuivre, nous allons tudier les registres dont nous allons nous
servir, et tout dabord :
Ce registre est un peu particulier, puisquil donne directement accs au monde extrieur.
Cest en effet ce registre qui reprsente limage des pins RA0 RA4, soit 5 pins. Si vous
suivez toujours, cest ce registre qui va servir allumer la LED.
Ce registre se situe ladresse 05H, dans la banque 0. Chaque bit de ce registre reprsente
une pin. Donc, seuls 5 bits sont utiliss. Pour crire sur une pin en sortie, on place le bit
correspondant 1 ou 0, selon le niveau souhait.
Par exemple :
92
place un niveau +5V sur la pin RA1. Notez quil faut pour cela que cette pin soit
configure en sortie (voir TRISA). Pour tester une entre, on pourra par exemple utiliser
btfss PORTA,3 ; tester RA3 et sauter si vaut 5V
Pour les lectroniciens, vous avez le schma interne des bits RA0 RA3 figure 5-1 page
21. Vous voyez que la sortie peut tre place au niveau haut ou bas grce aux deux transistors
de sortie (montage push-pull). Quand ces pins sont programmes en entre, elles sont
sensibles des niveaux 0/5V. Le niveau de transition dpend du modle de PIC, mais se situe
gnralement la moiti de la tension dalimentation. Une entre en lair est vue comme
tant au niveau 0. Evitez cependant ce cas pour les problmes de grande sensibilit aux
parasites.
Pour la pin RA4, figure 5-2, en sortie elle est de type drain ouvert, et en entre elle
comporte un trigger de Schmitt.
Les PORTS disposent dune diode de protection vers le 0V et vers le 5V. De sorte quavec
une simple rsistance srie, vous pouvez envoyer des signaux vers ces pins qui sortent de la
gamme de tension Vss/Vdd.
La pin RA4 fait exception cette rgle, car elle ne dispose que dune diode vers la masse.
Pour tous, retenez que les pins RA0 RA3 peuvent tre utilises en entre avec des
niveaux 0/5V ou en sortie en envoyant du 0V ou du 5V. Quant la pin RA4, en sortie, elle ne
peut pas envoyer du 5V.
Elle ne peut que mettre la sortie en lair sur niveau 1 et la forcer la masse sur niveau
0. En entre, elle comporte un dispositif permettant dempcher les hsitations lorsque le
niveau prsent nest pas franc. Par exemple lorsque le niveau varie lentement de 0V 5V.
Tenez compte de ces spcificits lorsque vous construirez votre montage. Par exemple, si
nous avions plac la LED telle quelle sur RA4, elle ne se serait jamais allume.
A partir de la page 75, chapitre 11, vous avez les caractristiques maximales de
fonctionnement du PIC. Vous pouvez retenir simplement de vous limiter utiliser 20mA
maximum par pin de sortie, avec un maximum total de 80mA pour le PORTA, et 150mA pour
le PORTB.
Si vous utilisez des caractristiques proches de cette limite, analysez les tableaux avec
plus de prcision pour obtenir les limites en puissance et t. Nous naurons pas ce genre de
problme dans nos exercices. La consommation de notre LED sur RA2 rpond la formule
suivante :
Intensit : (5V Tension Led) / 330 ohms, soit (5V 1,75V) / 330 ohms = 9,85mA.
93
1) Le PORTA est lu en intgralit (pins en entre et en sortie)
2) Le bit 1 est mis 1
3) Tout le PORTA est rcrit (concerne les pins en sortie).
Consquences
Supposons par exemple que le RA4 soit en sortie et mis 1. Comme il est drain ouvert,
supposons quune lectronique externe le force actuellement 0.
Lorsque le PORTA va tre lu, RA4 sera lu comme 0, bien quil soit 1. RA1 sera forc
1, et le tout sera replac dans PORTA. RA4 est donc maintenant 0, sans que vous layez
explicitement modifi.
Cest vrai que ce type de cas nest pas courant (par exempe, utilisation de RA4 pour
piloter une ligne IC), mais il est bon de le savoir, si un jour une de vos interfaces vous pose
problme, et si vous avez limpression que vos pins en sortie changent de niveau sans que
vous le dsiriez.
Ce registre est situ la mme adresse que PORTA, mais dans la banque 1. Son adresse
complte sur 8 bits est donc 0x85.
Au reset du PIC, toutes les pins sont mises en entre, afin de ne pas envoyer des signaux
non dsirs sur les pins. Les bits de TRISA seront donc mis 1 lors de chaque reset.
Notez galement que, comme il ny a que 5 pins utilises sur le PORTA, seuls 5 bits
(b0/b4) seront utiliss sur TRISA.
Exemple dutilisation
Prenons en exemple le schma de notre petit circuit : que devons-nous faire pour allumer
la LED ? (PS : ne mettez pas pour linstant ces instructions dans votre projet).
Premirement, nous devons configurer TRISA et mettre le bit2 (RA2) en sortie.
Comme le registre TRISA se trouve en banque1, et que ladressage DIRECT nutilise que
7 bits, nous devrons donc commuter le bit RP0 du registre STATUS (voir chapitres
prcdents).
94
Ensuite, nous pourrons envoyer un niveau 1 sur PORTA, correspondant 5V sur la pin
RA2. La squence correcte sera donc :
bsf STATUS , RP0 ; on passe en banque 1
bcf TRISA , 2 ; bit 2 de TRISA 0 = sortie pour RA2
bcf STATUS , RP0 ; on repasse en banque 0
bsf PORTA , 2 ; on envoie 5V sur RA2 : la LED sallume
.
.
.
bcf PORTA , 2 ; 0V sur RA2, la LED steint
Notez que comme RA2 restera en sortie durant tout le programme (dpend du schma),
nous placerons la valeur de TRISA dans la routine dinitialisation. Quand nous voudrons
allumer ou teindre la LED dans le programme principal, nous naurons donc plus quune
seule instruction utiliser. On commence entrer dans le concret .
Ces registres fonctionnent exactement de la mme manire que PORTA et TRISA, mais
concernent bien entendu les 8 pins RB. Tous les bits sont donc utiliss dans ce cas.
Note :
Aprs un reset, vous vous demandez peut-tre quel est ltat de tel ou tel registre ?
Vous trouverez ces explications dans le tableau de la page 14. Vous voyez quaprs un
reset, le registre OPTION_REG voit tous ses bits mis 1. Vous devez donc spcifier
leffacement du bit7 pour valider les rsistances de rappel au +5V.
Toujours en partant de notre schma, nous dsirons allumer la LED lorsque nous
pressons le bouton, et lteindre lorsque nous le relchons. Voici un exemple du programme
ncessaire (attention, prenez garde que le niveau sur RB2 passe 0 lorsque le bouton est
enfonc (connexion la masse)
95
bsf STATUS , RP0 ; on passe en banque 1
bcf OPTION_REG, NOT_RBPU ; rsistance de rappel en service
bcf TRISA , 2 ; bit 2 de TRISA 0 = sortie pour RA2
; inutile de configurer TRISB, car il est
; en entre par dfaut au reset du PIC
bcf STATUS , RP0 ; on repasse en banque 0
boucle ; tiquette dbut de la boucle principale
btfss PORTB , 2 ; tester RB2, sauter si vaut 1
bsf PORTA , 2 ; RB2 vaut 0, donc on allume la LED
btfsc PORTB , 2 ; tester RB2, sauter si vaut 0
bcf PORTA , 2 ; RB2 vaut 1, donc LED teinte
goto boucle ; et on recommence
mettent les sorties des PORTs 0. Comme a, lorsque vous configurerez les ports en
sortie, ils enverront par dfaut des niveaux 0V. Si votre lectronique demande, pour tre
scurise, dautres valeurs, vous de vous en charger.
Ne vous inquitez pas pour cette ligne. Sachez seulement quune valeur diffrente
dans ce registre augmente lgrement la consommation des PIC version 16C84. Cette ligne
est donc un petit plus pour les montages aliments par pile. Le registre EEADR sera vu lors
des accs lEEPROM interne. Notez que ce bug a t corrig sur le 16F84. Cette ligne nest
donc pas ncessaire dans ce cas.
La ligne suivante permet de se connecter sur la banque1. Jusqu nouvel ordre, les
instructions suivantes utilisent des registres situs banque1.
96
Suit la petite routine suivante, destine effacer la RAM. Souvenez-vous, et cest trs
important, qu la mise sous tension, la RAM contient des valeurs alatoires. Pour viter les
mauvaises surprises, jai intgr cette routine chaque dmarrage, qui assure que la RAM ne
contienne que des 0.
; Effacer RAM
; ------------
movlw 0x0c ; initialisation pointeur
movwf FSR ; pointeur d'adressage indirect
init1
clrf INDF ; effacer ram pointe par FSR
incf FSR,f ; pointer sur suivant
btfss FSR,6 ; tester si fin zone atteinte (>=0x40)
goto init1 ; non, boucler
btfss FSR,4 ; tester si fin zone atteinte (>=0x50)
goto init1 ; non, boucler
xxxxx ; ici se trouve la suite du programme
En premier lieu, on initialise le pointeur vers la zone manipuler (ici, la zone RAM
utilisateur). Cette zone commence ladresse 0x0C (voir tableau 4-2) et se termine ladresse
0x4F incluse. La zone situe dans la banque 1 nexiste pas pour ce PIC (image de la banque 0)
et na donc pas besoin dtre initialise.
Puis vous trouvez linstruction clrf INDF, qui signifie donc, si vous avez suivi, effacer
lemplacement mmoire dont ladresse se trouve dans le registre FSR. On efface donc la
mmoire situe lemplacement 0x0C.
Vient ensuite lincrmentation de FSR, donc, maintenant, FSR POINTE sur 0x0D.
On trouve alors 2 tests. Pour sortir de cette routine et arriver la ligne que jai indiqu (ici
se trouve la suite), il faudra donc viter les 2 lignes goto.
Vous tombez sur le premier goto si le bit 6 de FSR vaut 1. Pour viter ce goto, FSR devra
donc valoir au moins B01000000, ou encore 0x40. A ce moment, les adresses 0x0C 0x3F
sont donc mises 0.
On arrive au deuxime test. Le goto suivant sera donc saut si le bit 4 de FSR est 1. On
arrivera donc la ligne ici se trouve la suite uniquement lorsque les bits 4 et 6 de FSR seront
gaux 1. Ceci donne ladresse suivante : B01010000, soit 0x50.
Notez pour ceux qui ont suivi que vous auriez pu galement utiliser un compteur de
boucles et vous servir de linstruction decfsz. Ceci aurait cependant ncessit lutilisation
dune variable, variable qui se serait efface elle-mme par la prsente routine, avec plantage
du programme. Donc, la mthode prsente ici est donc la plus simple.
97
car elles ne nous intressent pas pour notre programme.
Tout dabord, nous devons initialiser RA2 en sortie, pour pourvoir agir sur la LED.
Linstruction sera donc
bcf TRISA , 2
Or, nous avons dclar dans les DEFINE, LED comme tant gal PORTA,2. Pour
permettre un remplacement facile de la LED sur une autre pin, que se passe-t-il si nous
crivons ?
bcf LED
Certains vont dire on teint la LED . Et bien, pas du tout. Cette instruction sera
remplace par lassembleur par
bcf PORTA , 2
bcf 0x05 , 2
Or, RP0 est toujours positionn 1 au moment de lexcution de cette ligne. On pointe
donc toujours sur la banque 1. Si vous regardez ce quil y a ladresse 0x05 dans la banque1,
cest dire ladresse 0x85, vous trouvez TRISA. Ainsi, lopration a plac RA2 en sortie.
; initialisations spcifiques
; ---------------------------
Repassez ensuite en banque 0 avant de quitter lintialisation. Cest une bonne pratique, car
beaucoup derreurs sont provoques par des erreurs de banque, ajoutez donc :
goto start
qui branche le programme principal. Pour le moment, cela peut paratre inutile, car le
programme principal suit directement cette instruction, mais nous allons ajouter plus loin un
sous-programme qui sera intercal entre les deux.
Voici quoi devrait maintenant ressembler votre routine dinitialisation, que vous
devriez maintenant avoir entirement comprise (pas besoin dune aspirine?).
98
Rassurez-vous, cela a lair dur au dbut, mais, une fois assimil, cest trs simple.
De plus, vous avez vu pratiquement tout ce quil faut savoir pour raliser un programme sans
routines dinterruptions.
;*********************************************************************
; INITIALISATIONS *
;*********************************************************************
init
clrf PORTA ; Sorties portA 0
clrf PORTB ; sorties portB 0
clrf EEADR ; permet de diminuer la consommation
bsf STATUS , RP0 ; slectionner banque 1
movlw OPTIONVAL ; charger masque
movwf OPTION_REG ; initialiser registre option
; Effacer RAM
; ------------
movlw 0x0c ; initialisation pointeur
movwf FSR ; pointeur d'adressage indirect
init1
clrf INDF ; effacer ram
incf FSR,f ; pointer sur suivant
btfss FSR,6 ; tester si fin zone atteinte (>=0x40)
goto init1 ; non, boucler
btfss FSR,4 ; tester si fin zone atteinte (>=0x50)
goto init1 ; non, boucler
; initialisations spcifiques
; ---------------------------
bcf LED ; LED en sortie (banque1)
bcf STATUS , RP0 ; repasser banque 0
goto start ; sauter au programme principal
Dans la fentre de rsultat de compilation, vous devez trouver une ligne du type
Ceci est un message davertissement (warning) qui vous signale qu la ligne 101 (dans
mon cas, mais suivant vos espaces ou commentaires, vous aurez un autre numro de ligne),
vous avez accd un registre qui nest pas situ en banque 0.
MPASM vous demande de vrifier que votre bit RP0 est positionn correctement. Allez
dans l diteur sur la ligne dont vous avez le numro. Vous tombez sur la ligne :
99
Un coup dil sur le tableau 4-2 vous indique que le registre OPTION est dans la
banque1. Mais comme votre RP0 a t positionn sur 1 cet endroit, il ny a pas de problme.
Quand vous aurez ralis de gros programmes, vous aurez normment de warning de ce
type . Si vous voulez viter ces warnings de banque, ajoutez la ligne
Errorlevel 302
directement sous la ligne #include de votre fichier source. Le - signifie que vous retirez ce
message des messages actifs, et le 302 est le numro du warning viter.
Nous voulons faire clignoter notre LED une frquence de 1Hz (1 clignotement par
seconde) . Nous allons donc crer un programme de la forme :
debut
- Jallume la LED
- Jattends seconde
- Jteins la LED
- Jattends seconde
- Je retourne au dbut
Nous voyons que nous utilisons 2 fois la temporisation de seconde. Nous crerons donc
un sous-programme que nous appellerons tempo . Notre programme principal aura donc
laspect suivant :
start
bsf LED ; allumer la LED
call tempo ; appeler la tempo de 0.5s
bcf LED ; teindre LED
call tempo ; appeler la tempo de 0.5s
goto start ; boucler
start
LEDON ; allumer la LED
call tempo ; appeler la tempo de 0.5s
LEDOFF ; teindre LED
call tempo ; appeler la tempo de 0.5s
goto start ; boucler
Choisissez la mthode que vous prfrez. Limportant, cest davoir compris les deux
mthodes.
Nous navons pas encore vu le timer0, ni les interruptions. Le but ici est de vous faire
comprendre le fonctionnement du 16F84. Pour raliser une tempo, il suffit dans notre cas de
faire perdre du temps au 16F84 entre chaque inversion de la LED.
100
Nous devons donc perdre approximativement 0.5s. Les secondes ne sont pas appropries
pour les PICs, qui travaillent une vitesse beaucoup plus leve. Nous utiliserons donc des
units de temps compatibles avec les PICs.
Notre PIC est cadenc la frquence de notre quartz, soit 4MHz. Or, le PIC excute un
cycle dinstruction tous les 4 cycles de lhorloge principale. Le PIC excutera donc
(4.000.000/4) = 1 million de cycles par seconde.
La plupart des instructions (hormis les sauts) sexcutent en 1 cycle, ce qui vous donne
approximativement un million dinstructions par seconde. Vous verrez parfois la
dnomination MIPS. Ceci signifie Million dInstructions Par Seconde. Notre PIC avec ce
quartz a donc une puissance de traitement de prs de 1MIPS.
Donc, notre tempo de 0.5s est donc une tempo de 500.000 microsecondes. Autrement dit,
nous devons perdre pour rien 500.000 cycles dans notre routine de temporisation. Vous
voyez donc que votre PIC, pour notre application, va passer son temps ne rien faire dutile.
La premire ide qui vient lesprit est de raliser une boucle qui va incrmenter ou
dcrmenter une variable.
Ralisons-la. Commenons donc par dclarer notre variable (cmpt1) dans la zone de
RAM. Ajoutons donc cette dclaration . Nous obtenons :
;*********************************************************************
; DECLARATIONS DE VARIABLES *
;*********************************************************************
CBLOCK 0x00C ; dbut de la zone variables
cmpt1 : 1 ; compteur de boucles 1
ENDC ; Fin de la zone
Crons maintenant lossature de notre sous-routine, que nous placerons entre la routine
dinitialisation et le programme principal. Noubliez pas de toujours utiliser des
commentaires :
;*********************************************************************
; SOUS-ROUTINE DE TEMPORISATION *
;*********************************************************************
;---------------------------------------------------------------------
; Cette sous-routine introduit un retard de 500.000 s.
; Elle ne reoit aucun paramtre et n'en retourne aucun
;---------------------------------------------------------------------
tempo
; nous allons placer notre code ici
return ; retour de la sous-routine
101
Ralisons maintenant notre boucle.
tempo
clrf cmpt1 ; effacer compteur1
boucle1
decfsz cmpt1 ; dcrmenter compteur1
goto boucle1 ; si pas 0, boucler
return ; retour de la sous-routine
Nous obtenons dans la fentre des rsultats une ligne supplmentaire de la forme :
Le numro de ligne peut varier suivant votre code source. Comme la compilation sest
effectue correctement, il sagit une fois de plus dun message de type warning. Positionnez-
vous dans lditeur sur la ligne incrimine (ligne 134 pour moi). Vous tes sur la ligne :
En effet, linstruction decfsz est de la forme decfsz f , d . Nous avons donc oubli
dindiquer la destination de lopration. MPLAB vous signale quil a utilis pour vous ,f
Faites donc attention, car si vous aviez voulu obtenir le rsultat dans w, votre programme
tait faux. Modifiez donc votre commande en ajoutant ,f
tempo
clrf cmpt1 ; 1 cycle
boucle1
decfsz cmpt1 , f ; 1 cycle si on ne saute pas, 2 si on saute. Donc, on
; ne sautera pas 255 fois et on sautera 1 fois
goto boucle1 ; 2 cycles multipli par 255 passages
return ; 2 cycles.
Soit un total de 772 cycles. On est loin des 500.000 cycles ncessaires. Pour la suite
des calculs, nous allons ngliger les 2 cycles du call et les 2 cycles du return (compars aux
500.000 cycles, cest effectivement drisoire).
102
Bon, nous allons allonger notre routine, en ralisant une seconde boucle qui va forcer
la premire boucle sexcuter 256 fois. Commenons par dclarer une nouvelle variable
cmpt2 :
tempo
clrf cmpt2 ; effacer compteur2
boucle2
clrf cmpt1 ; effacer compteur1
boucle1
decfsz cmpt1 , f ; dcrmenter compteur1
goto boucle1 ; si pas 0, boucler
decfsz cmpt2 , f ; si 0, dcrmenter compteur 2
goto boucle2 ; si cmpt2 pas 0, recommencer boucle1
return ; retour de la sous-routine
Vous voyez que notre premire boucle est toujours l, mais au lieu deffectuer le return
une fois termine, nous recommenons la boucle tant que cmpt2 ne soit pas galement gal
0. Nous allons donc excuter 256 fois notre boucle 1.
Dure de la boucle 1 : 257 cycles + 510 cycles + 1 cycle (clrf cmpt1) = 768 cycles.
Or cette boucle va tre excute 256 fois, donc 768*256 = 196608 cycles, auquel il
convient dajouter les quelques cycles dinitialisation etc.
Or, nous dsirons 500.000 cycles. Nous devrons donc utiliser cette boucle
(500.000/196608) = 2,54 fois. Nous ne savons pas faire de demi boucle. Nous effectuerons
donc 2 boucles. Nous allons nous arranger pour que nos deux premires boucles durent
500.000/2 = 250.000 cycles.
Chaque instruction ajoute dans la boucle1 est excute 256*256 fois. Chaque instruction
ajoute dans la boucle 2 est excute 256 fois. Chaque cycle extrieur aux boucles est excut
1 fois. Nous avons donc la possibilit de raliser des temporisations trs prcises. Ce nest pas
ncessaire ici. Cependant, nous allons quand mme amliorer la prcision.
Si nous ajoutons 1 cycle inutile dans la boucle1, nous ajouterons 256*256 = 65536
cycles. Nous devons en ajouter 250.000 196608 = 53392. Cela nous donnerait une erreur de
12000 cycles, soit 12 millimes de seconde (12ms). La prcision est largement suffisante pour
notre application, mais je rappelle que vous pouvez affiner cette prcision en effectuant les
calculs prcis. Je vous conseille mme de le faire vous-mme comme exercice. Vous pourrez
vrifier vos rsultats avec un chronomtre.
Pour perdre un cycle, nous ajouterons simplement linstruction NOP, qui ne fait rien.
Reste donc raliser la dernire boucle de 2. Crons une troisime variable cmpt3 et une
troisime boucle. (Rassurez-vous, il y a des mthodes plus simples, ceci est expliqu dans un
but didactique : il importe simplement davoir compris).
103
;*********************************************************************
; DECLARATIONS DE VARIABLES *
;*********************************************************************
CBLOCK 0x00C ; dbut de la zone variables
;*********************************************************************
; SOUS-ROUTINE DE TEMPORISATION *
;*********************************************************************
;---------------------------------------------------------------------
; Cette sous-routine introduit un retard de 500.000 s.
; Elle ne reoit aucun paramtre et n'en retourne aucun
;---------------------------------------------------------------------
tempo
movlw 2 ; pour 2 boucles
movwf cmpt3 ; initialiser compteur3
boucle3
clrf cmpt2 ; effacer compteur2
boucle2
clrf cmpt1 ; effacer compteur1
boucle1
nop ; perdre 1 cycle *256 *256 *2
decfsz cmpt1 , f ; dcrmenter compteur1
goto boucle1 ; si pas 0, boucler
decfsz cmpt2 , f ; si 0, dcrmenter compteur 2
goto boucle2 ; si cmpt2 pas 0, recommencer boucle1
decfsz cmpt3 , f ; si 0, dcrmenter compteur 3
goto boucle3 ; si cmpt3 pas 0, recommencer boucle2
return ; retour de la sous-routine
Lancez la compilation avec <F10>. Si tout sest bien pass, vous obtenez dans votre
rpertoire de travail le fichier LED_CLI.HEX
Placez le PIC sur la carte HORS TENSION, envoyez lalimentation et regardez bien :
Flicitations, voici votre premier programme embarqu. La porte est ouverte des
tonnes de nouvelles applications.
104
CONSEIL IMPORTANT
Si, ce stade, vous sautez au plafond en criant CA MARCHE (jai connu a), ne
vous prcipitez pas en hurlant pour faire admirer votre ralisation votre pouse. Je doute
quelle partage votre enthousiasme pour cette petite lampe qui clignote .
Le fichier tel quil devrait tre la fin de cette leon est disponible dans les fichiers joints.
105
Notes
106
12. Les interruptions
Les interlocuteurs reprendront leur conversation o elle en tait arrive, sitt le danger
cart (sils ont vit le piano, bien sr).
Vous voyez ici lopposition avec les ruptures de squences synchrones, provoques par le
programme lui-mme (goto, call, btfss).
Nous pouvons dire, sans nous tromper de beaucoup, quune routine dinterruption est un
sous-programme particulier, dclench par lapparition dun vnement spcifique. Cela a
lair un peu ardu, mais vous allez voir que cest trs simple.
Voici donc comment cela fonctionne :
107
- Le programme saute linstruction qui suit la dernire excute dans le programme
principal.
Il va bien sr de soi que nimporte quel vnement ne peut pas dclencher une
interruption. Il faut que 2 conditions principales soient remplies :
Que pouvons-nous dire en voyant cet ordinogramme ? Et bien, nous pouvons dj nous
dire que le programme principal ne sait pas quand il est interrompu, il est donc crucial de lui
remettre ses registres dans ltat o ils taient avant linterruption.
En effet, supposons que linstruction xxx ait positionn un flag (par exemple, le bit
dindicateur Z). Si par malheur, la routine dinterruption a modifi ce bit, le programme ne
pourra pas se poursuivre normalement.
Nous voyons galement que linstruction xxx termine son excution avant de se
brancher sur la routine dinterruption. Une instruction commence nest donc jamais
interrompue.
Bien entendu, les PICs rpondent au fonctionnement gnral ci-dessus, mais ils ont
galement leurs particularits. Voyons maintenant le principe des interruptions sur les PICs
- Tout dabord, ladresse de dbut de toute interruption est fixe. Il sagit toujours de
ladresse 0x04.
- Toute interruption provoquera le saut du programme vers cette adresse. Toutes les
sources dinterruption arrivant cette adresse, si le programmeur utilise plusieurs
sources dinterruptions, il lui faudra dterminer lui-mme laquelle il est en train de
traiter.
- Le contenu du PC est sauv sur la pile interne (8 niveaux). Donc, si vous utilisez des
interruptions, vous ne disposez plus que de 7 niveaux dimbrication pour vos sous-
programmes. Moins si vous utilisez des sous-programmes dans vos interruptions.
108
- Celui-ci est achev, puis le processeur sarrte un cycle pour charger ladresse 0x04
dans PC.
Remarquez que :
- Une interruption ne peut pas tre interrompue par une autre interruption. Les
interruptions sont donc invalides automatiquement lors du saut ladresse 0x04 par
leffacement du bit GIE (que nous allons voir).
109
12.4 Les sources dinterruptions du 16F84
- TMR0 : Dbordement du timer0 (tmr0). Une fois que le contenu du tmr0 passe de 0xff
0x00, une interruption peut tre gnre. Nous utiliserons ces proprits dans le
chapitre sur le timer 0.
- EEPROM : cette interruption peut tre gnre lorsque lcriture dans une case
EEPROM interne est termine. Nous verrons ce cas dans le chapitre sur lcriture en
zone eeprom.
- RB0/INT : Une interruption peut tre gnre lorsque, la pin RB0, encore appele
INTerrupt pin, tant configure en entre, le niveau qui est appliqu est modifi. Nous
allons tudier ce cas ici.
- PORTB : De la mme manire, une interruption peut tre gnre lors du changement
dun niveau sur une des pins RB4 RB7. Il nest pas possible de limiter linterruption
une seule de ces pins. Linterruption sera effective pour les 4 pins ou pour aucune.
Comment interdire ou autoriser les interruptions, comment dtecter quel est lvnement
dclencheur, et comment les grer ? Nous allons aborder ceci dabord de manire
symbolique, pour vous aider bien visualiser la procdure.
110
Quand vous comprendrez bien ce petit schma symboliques, vous aurez compris les
interruptions. Vous voyez tout de suite quil y a deux mthodes pour que le groom soit
prvenu.
- Pour la premire mthode, le groom doit venir voir les lampes intervalles rguliers
pour vrifier si personne na appel. Il doit donc venir SCRUTER le tableau de
signalisation. Cest la mthode de SCRUTATION.
- Avec la sonnette, le groom est INTERROMPU dans son travail par celle-ci. Il na pas
besoin de venir scruter inutilement, mais il sera drang dans son travail par la
sonnette. Cest la mthode des INTERRUPTIONS Notez dj les points suivants :
- Le locataire de la chambre ne peut dcider quelle mthode sera utilise, cest le groom
qui dcide de valider ou non les sonnettes.
- Le groom peut inhiber toutes les sonnettes en une seule fois, ou dcider quelle
chambre va pouvoir actionner la sonnette.
- Si le groom est interrompu dans son travail par la sonnette, il doit de toute faon aller
regarder les lampes pour voir qui a sonn. Sauf sil sait quil na autoris quune seule
chambre actionner la sonnette.
- Ce qui napparat pas sur ce schma simplifi, mais quil faut savoir, cest que, une
fois la lampe allume, elle le reste. Cest le groom qui doit lteindre manuellement.
111
Appliquons donc tout ceci en pratique sur le 16F84. Vous avez dj compris que lampes
et interrupteurs taient, dans le 16F84, des bits de registres particuliers. Voici maintenant le
registre principal de gestion des interruptions pour le 16F84.
Ce registre se situe ladresse 0x0B, dans les 2 banques. Il est donc toujours accessible. Il est
dtaill figure 4-5 page 17. Cest un registre de bits, donc, chaque bit a une fonction
particulire. Voici le dtail de ces bits :
b7 : GIE
Global Interrupt Enable bit. Il permet de valider ou dinvalider toutes les interruptions
dune seule fois. Ce bit correspond donc notre interrupteur de validation gnrale.
b6 : EEIE
Eeprom write complete Interrupt Enable bit. Ce bit permet de valider linterruption de fin
dcriture en eeprom (nous tudierons plus tard le mcanisme dcriture eeprom).
b5 : T0IE
Tmr0 Interrupt Enable bit : Valide linterruption gnre par le dbordement du timer0.
b4 : INTE
INTerrupt pin Enable bit : Valide linterruption dans le cas dune modification de niveau
de la pin RB0.
ATTENTION : rappelez-vous le bit 6 du registre OPTION, qui dtermine quel est le sens
de transition qui provoque linterruption. On pourra donc choisir si cest une transition 0->1
ou 1->0 qui provoque linterruption, mais pas les deux ensemble.
b3 : RBIE
b2 : T0IF
Tmr0 Interrupt Flag bit. Cest un Flag, donc il signale. Ici cest le dbordement du timer0
b1 : INTF
INTerrupt pin Flag bit : signale une transition sur la pin RB0 dans le sens dtermin par
INTEDG du registre OPTION (b6)
b0 : RBIF
112
Port Interrupt Flag bit : signale quune des entres RB4 RB7 a t modifie.
Remarque
Rappelez-vous que les flags ne se remettent pas 0 tout seuls. Cest votre programme qui
doit sen charger, sous peine de rester indfiniment bloqu dans une routine dinterruption.
Nous dirons que ces flags sont des FLAGS REMANENTS. Prenez garde que le reset de RBIF
doit tre prcd dune lecture ou dune criture du PORTB afin de mettre fin la condition
de gnration du flag dinterruption.
Remarquez dj que tous les bits dont le nom se termine par E (Enable) sont en fait des
commutateurs de validation (ce sont les interrupteurs de notre schma symbolique). Les bits
donc le nom se termine par F sont des Flags (indicateurs). Ils sont reprsents par des lampes
sur notre schma symbolique. Sur celui-ci nous avons 5 interrupteurs et 4 ampoules. Or nous
navons que 8 bits dans INTCON0. Que nous manque-t-il ?
Si vous regardez attentivement, il nous manque le bit EEIF. Mais, rassurez-vous, ce bit
existe bien, il est tout simplement dans le registre EECON1, que nous verrons dans la leon
sur les accs EEPROM. Nous allons donc transformer notre schma symbolique pour quil
corresponde la ralit dun PIC16F84.
Aprs ces explications dtailles, trop diront les habitus des processeurs, vous devez
maintenant avoir compris le fonctionnement des interruptions sur le 16F84. Analysons
maintenant quelques points de la routine dinterruption en elle-mme. Pour rester concrets,
nous allons mlanger thorie et pratique.
113
Et bien, comme nous lavons dj dit, votre programme interrompu ne sait pas quil la
t, donc vous devez remettre les registres qui permettent votre programme principal de
fonctionner dans ltat o ils taient au moment de linterruption.
Petit exemple :
Il est plus que probable que votre routine dinterruption va utiliser au moins une
instruction qui modifie le bit Z. Vous devrez donc restaurer le registre STATUS dans ltat
quil tait avant de sortir de la routine dinterruption. Sinon le test ne se fera pas sur la valeur
de mavariable, mais sur une valeur de Z modifie par la routine dinterruption.
De plus, il est peut prs certain que le registre w va tre modifi galement, donc il
vous faudra veiller le sauvegarder galement.
Par contre, STATUS est, comme nous venons de voir, restaurer par la routine
dinterruption.
En voil une bte question, allez-vous vous dire. En effet, avec un simple :
114
Il suffit de rflchir : Le problme est damener STATUS dans le registre W SANS
AFFECTER aucun bit de STATUS. Il suffit de chercher une instruction qui pourrait convenir.
Pourquoi pas linstruction swap ? Pour rappel, cette instruction inverse les 4 bits de poids
faibles avec les 4 bits de poids forts de loctet dsign .
swapf STATUS,w ; swap status avec rsultat dans w sans rien modifier
movwf status_temp ; sauver status swapp dans variable de sauvegarde
Pour restaurer, il faudra donc reswapper status_temp avant de le remettre dans STATUS.
Donc, nous pourrons utiliser la procdure suivante :
En effet, movwf ne modifie aucun bit du registre STATUS, swapf remet dans lordre
status_temp et place le rsultat dans w. constatons cependant que cette procdure a
linconvnient de modifier chaque fois le registre W. Nous devrons donc sauver W AVANT
de sauver STATUS (sans modifier STATUS pas encore sauv), et nous devrons restaurer W
APRES avoir restaur STATUS (et de nouveau sans modifier STATUS dj restaur)
Pour sauver W, pas de problme, linstruction suivante :
;**********************************************************************
; ROUTINE INTERRUPTION *
;**********************************************************************
;sauvegarder registres
;---------------------
org 0x004 ; adresse d'interruption
movwf w_temp ; sauver registre W
swapf STATUS,w ; swap status avec rsultat dans w
movwf status_temp ; sauver status swapp
115
; ici, on teste ventuellement de quelle interruption il sagit
;restaurer registres
;----------------------
swapf status_temp,w ; swap ancien status, rsultat 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 ; return from interrupt
Et voil votre squelette de routine dinterruption : vraiment pas compliqu, nest-ce pas ?
Il ny a plus qu complter, car le fichier m16F84.asm contient dj les routines de
sauvegarde et restauration (que nous venons dexpliquer) et les tests de type dinterruption
(que nous allons dtailler).
Et bien, vous ne pouvez pas interrompre une interruption par une autre. Si ctait le cas,
les sauvegardes des registres W et STATUS seraient crases par une seconde opration
(mais cest possible sur dautres processeurs). Donc, ds que le programme est branch sur
linterruption, le bit GIE est mis 0 automatiquement.
Pour quune nouvelle interruption puisse avoir lieu une fois celle en cours termine, il
faut remettre GIE 1. Ceci est excut automatiquement par RETFIE.
Et bien, cest exactement ce que fait RETFIE, mais un dtail prs, et ce dtail est de la
plus grande importance : RETFIE est une seule et mme instruction, donc ne peut pas tre
interrompu par une interruption.
Dans le cas o les 2 instructions prcdentes seraient utilises, une fois GIE mis un, si
un des flags dinterruption est toujours 1 (autre interruption, o la mme qui se reproduit
une autre fois), le programme se reconnecterait sur la routine dinterruption avant davoir
excut le RETURN, donc avant davoir restaur le PC.
116
Celui-ci continuerait occuper un emplacement sur la pile. En sachant que la pile est
limite 8 emplacements, il y aurait de nombreuses chances de plantage du programme par
dbordement de la pile.
Nous allons construire un programme qui inverse lallumage dune LED chaque
pression sur un bouton-poussoir. Modifiez votre petite platine dexprimentation de faon
connecter le bouton-poussoir sur lentre RB0 (dsol, quand jai dessin le schma, je
pensais expliquer les interruptions avec le timer).
La rsistance est interne au pic, il sagit dune des rsistances de rappel au +5V (pull-up)
quon peut activer par logiciel.
;**********************************************************************
; Ce programme est un programme didactique destin monter *
; le fonctionnement des interruptions *
; *
;**********************************************************************
; *
117
; NOM: Interruption par bouton-poussoir sur RB0 *
; Date: 13/02/2001 *
; Version: 1.0 *
; Circuit: Platine d'essais *
; Auteur: Bigonoff *
; *
;**********************************************************************
; *
; Fichier requis: P16F84.inc *
; *
; *
; *
;**********************************************************************
; Notes: Ce programme transforme un bouton-poussoir en *
; tlrupteur. Un pulse allume la LED, un autre *
; lteint *
;**********************************************************************
Vous allez dire que jexagre en vous faisant mettre des commentaires partout.
Croyez-moi sur parole, les commentaires permettent une maintenance aise du programme.
Ils vous feront gagner coup sr beaucoup plus de temps quils ne vous en feront perdre.
- b6 0, car on veut une interruption quand presse le bouton, donc quand le niveau
passe de 1 0 (flanc descendant)
;*********************************************************************
; ASSIGNATIONS *
;*********************************************************************
118
Assignons une constante pour cette valeur ;
Ensuite, dans la zone des DEFINE, nous dfinirons notre LED et notre bouton-poussoir :
;*********************************************************************
; DEFINE *
;*********************************************************************
#DEFINE Bouton PORTB , 0 ; bouton poussoir
#DEFINE LED PORTA , 2 ; LED
Dans la zone macros , nous pouvons crire 2 macros que nous utiliserons souvent. Ce
sont les instructions pour passer en banque 0 et banque1. Elles seront incluses dans le
nouveau fichier m16f84.asm nomm m16f84_new.asm . A la fin de cette leon,
supprimez lancien fichier et renommez m16F84_new en m16f84 .
;*********************************************************************
; MACRO *
;*********************************************************************
BANK0 macro
bcf STATUS , RP0 ; passer en banque 0
endm
BANK1 macro
bsf STATUS , RP0 ; passer en banque1
endm
Venons-en la zone des variables. Nous devons garder w_temp et status_temp, car ces
variables sont utilises dans la routine dinterruption pour sauver les registres W et STATUS.
Nous allons galement rcuprer notre petite routine de tempo de notre fichier
led_cli.asm . Nous aurons donc besoin des variables utilises dans cette routine. Tout ceci
nous donne donc pour linstant :
;*********************************************************************
; DECLARATIONS DE VARIABLES *
;*********************************************************************
CBLOCK 0x00C ; dbut de la zone variables
Nous avons dj vu la premire partie, qui est la sauvegarde des registres utiliss
119
;**********************************************************************
; ROUTINE INTERRUPTION *
;**********************************************************************
;sauvegarder registres
;---------------------
org 0x004 ; adresse d'interruption
movwf w_temp ; sauver registre W
swapf STATUS , w ; swap status avec rsultat dans w
movwf status_temp ; sauver status swapp
Ensuite, nous devons dterminer quelle est lorigine de linterruption en cours. Dans le
cas prsent, il sagit obligatoirement de linterruption RB0/INT, car nous navons autoris que
celle-l. Dans le cas prsent, nous pourrions donc nous passer de ce test. Mais le but ici est de
vous expliquer les mthodes utiliser. Nous garderons donc la totalit des explications afin
que vous puissiez utiliser nimporte quelle combinaison. Examinons donc cette partie :
Les 2 premires instructions examinent si nous avons affaire une interruption tmr0.
Vous allez me dire : pourquoi 2 lignes ? Il suffit dexaminer T0IF, tout simplement.
Et bien, ce nest pas si simple. Imaginons en effet que le tmr0, que nous nutilisons pas,
ait dbord. Le bit T0IF est donc mis 1 et na pas gnr dinterruption, car T0IE est 0. De
mme, si nous avions accept les interruptions timer et que linterruption soit due une autre
cause, nous aurions T0IE 1 et T0IF 0.
Nous ne devons donc traiter linterruption que si linterruption est en service, et que si le
flag est positionn, do le double test. Examinez ce double test et observez le fonctionnement
des btfsc et btfss :
Si T0IE vaut 0, on saute directement au test suivant par la ligne goto. Sil vaut 1, on teste
ensuite T0IF. Si celui-ci vaut 0, on arrive la ligne goto qui passe au test suivant. Sil vaut
galement 1, au appelle la sous-routine de traitement de linterruption timer0.
120
Remarques
Ensuite, nous trouvons la mme procdure pour les interruptions de type RB0 (dont nous
allons nous servir) et dinterruption RB4/RB7. Remarquez lemplacement prvu pour ajouter
le test pour linterruption eeprom. Nous complterons m16F84.asm ce niveau en tudiant les
procdures dcriture en eeprom. Toutes ces modifications ont t incluses dans le fichier
m16f84_new.asm .
intsw1
btfsc INTCON , INTE ; tester si interrupt RB0 autorise
btfss INTCON , INTF ; oui, tester si interrupt RB0 en cours
goto intsw2 ; non sauter au test suivant
call intrb0 ; oui, traiter interrupt RB0
bcf INTCON,INTF ; effacer flag interupt RB0
goto restorereg ; et fin d'interruption
; SUPPRIMER CETTE LIGNE POUR
; TRAITER PLUSIEURS INTERRUPT
; EN 1 SEULE FOIS
intsw2
btfsc INTCON,RBIE ; tester si interrupt RB4/7 autorise
btfss INTCON,RBIF ; oui, tester si interrupt RB4/7 en cours
goto intsw3 ; non sauter
call intrb4 ; oui, traiter interrupt RB4/7
bcf INTCON,RBIF ; effacer flag interupt RB4/7
goto restorereg ; et fin d'interrupt
intsw3
Enfin, nous trouvons la partie servant la restauration des registres sauvegards. Nous
avons dj vu cette procdure :
;restaurer registres
;-------------------
restorereg
swapf status_temp , w ; swap ancien status, rsultat 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 ; return from interrupt
121
12.10 Adaptation de la routine dinterruption
Nous allons maintenant modifier cette routine dinterruption pour ladapter notre cas
prcis. Nous navons quune seule source dinterruption valide, donc, si nous entrons dans
cette interruption, ce sera forcment pour traiter INT/RB0. Supprimons donc les tests.
Il nous reste donc :
;**********************************************************************
; ROUTINE INTERRUPTION *
;**********************************************************************
;sauvegarder registres
;---------------------
org 0x004 ; adresse d'interruption
movwf w_temp ; sauver registre W
swapf STATUS , w ; swap status avec rsultat dans w
movwf status_temp ; sauver status swapp
call intrb0 ; traiter interrupt RB0
;restaurer registres
;-------------------
Nous pourrions galement nous passer de la ligne call intrb0, et placer la procdure de
traitement directement sa place. Conservons cependant cet appel de sous-routine, car nous
ne sommes pas quelques instructions prs. En cas o vous devriez optimiser une application
lextrme, vous pourriez y penser. Dans le cas contraire, je vous conseille de donner priorit
la lisibilit de votre programme (oui, jinsiste encore).
;**********************************************************************
; INTERRUPTION RB0/INT *
;**********************************************************************
intrb0
return ; fin d'interruption RB0/INT
; peut tre remplac par
; retlw pour retour code d'erreur
Si vous utilisiez RETFIE ce moment, vous remettriez les interruptions en service avant
den sortir, donc plantage de votre programme.
122
Remarquez que vous pourriez utiliser retlw pour retourner une valeur prdfinie traite
dans votre routine dinterruption. Par exemple, retlw0 si on veut traiter dautres interruptions
et retlw 1 si on sort de la routine. Dans ce cas, la ligne
correspondante pourrait tre prcde du test de w retourn par la sous-routine. Ceci est
un exemple un peu complexe traiter ici, mais parfaitement envisageable lorsque vous
jonglerez avec les PICs.
12.11 Linitialisation
Nous obtenons :
;*********************************************************************
; INITIALISATIONS *
;*********************************************************************
init
clrf PORTA ; Sorties portA 0
clrf PORTB ; sorties portB 0
clrf EEADR ; permet de diminuer la consommation
BANK1 ; passer banque1
movlw OPTIONVAL ; charger masque
movwf OPTION_REG ; initialiser registre option
; Effacer RAM
; ----------------
movlw 0x0c ; initialisation pointeur
movwf FSR ; pointeur d'adressage indirect
init1
clrf INDF ; effacer ram
incf FSR,f ; pointer sur suivant
btfss FSR , 6 ; tester si fin zone atteinte (>=0x40)
goto init1 ; non, boucler
btfss FSR , 4 ; tester si fin zone atteinte (>=0x50)
goto init1 ; non, boucler
; configurer PORTS
; ---------------
bcfLED ; RA2 en sortie (TRISA)
123
Remarque
Une grande partie des erreurs dans les programmes sont provoqus par des erreurs de
slection de banques (surtout pour les PICs 4 banques). Je vous conseille dadopter comme
convention de toujours entrer dans une routine avec la banque 0, et de toujours sassurer que
vous tes en banque 0 avant den sortir. En cas de drogation, indiquez-le clairement dans
len-tte de votre sous-routine.
Lancez la compilation pour vrifier que vous navez pas fait derreurs. Vous devriez
obtenir ceci (au numro de ligne prs) :
Message[302] D:\DOCUME~1\LESSONS\DATAPIC\MYINTER.ASM 143 : Register in operand
not in bank 0. Ensure that bank bits are correct.
Build completed.
Nous allons maintenant raliser un tlrupteur. Quest-ce dire ? Et bien nous allons
raliser la fonction suivante : Une pression sur le bouton-poussoir allume la LED, une
seconde pression lteint. Je vais vous guider pas pas dans cette petite ralisation, en
essayant de vous montrer les problmes pratiques rencontrs dans une ralisation de ce type.
start
goto start ; boucler
;*********************************************************************
; PROGRAMME PRINCIPAL *
;*********************************************************************
124
start
nop ; instruction inutile
nop ; instruction inutile
nop ; instruction inutile
nop ; instruction inutile
nop ; instruction inutile
goto start ; boucler
END ; directive fin de programme
Nous avons programm le PIC de faon ce quune interruption sur flanc descendant
de INT/RB0 provoque une interruption. Il nous suffit donc dexcuter dans cette routine
dinterruption linversion du niveau de la LED. Ceci est ralis trs simplement avec un ou
exclusif . Nous pouvons donc crire :
;**********************************************************************
; INTERRUPTION RB0/INT *
;**********************************************************************
;----------------------------------------------------------------------
; inverse le niveau de RA2 chaque passage
;----------------------------------------------------------------------
intrb0
movlw B'00000100' ; bit positionn = bit inverser
BANK0 ; car on ne sait pas sur quelle banque
; on est dans une interruption (le programme
; principal peut avoir chang de banque). Ce nest
; pas le cas ici,mais c'est une sage prcaution
xorwf PORTA , f ; inverser RA2
return ; fin d'interruption RB0/INT
Voil, notre premier essai est termin. Nous allons passer ce programme au simulateur.
Mais avant, je vous donne lordinogramme du programme que nous avons ralis. Lorsque
vos programmes deviendront complexes, je vous conseille de recourir lordinogramme
avant de les crire.
Vous voyez que cette routine dinterruption est on ne peut plus simple, et correspond bien
ce quon pourrait simaginer de prime abord. Nous allons donc commencer par passer le test
du simulateur.
125
12.14 Passage au simulateur dune routine dinterruption
N oubliez pas que le simulateur doit tre en service, si ce nest pas le cas, faites-le
(voir chapitre sur le debugger). Slectionnez laffichage de la fentre special functions
registers) si ce nest dj fait.
Lanons la compilation avec <F10>. Ensuite pressez <F6> pour faire le reset du
programme, puis <F7>. Rptez <F7> en suivant lvolution du programme. Noubliez pas
quil va effectuer 68 boucles pour effacer la RAM, soyez patient. Profitez-en pour observer le
comportement de FSR pour ladressage indirect. Vous pouvez galement presser <F9>, et
ensuite <F5> aprs quelques instants.
Allez dans le menu debugger -> stimulus . Si par hasard vous avez des messages
derreur concernant un fichier, ignorez-les. Slectionnez longlet pin stimulus
Cliquez sur add Row pour obtenir un bouton daction. Une nouvelle ligne est cre
dans la fentre, avec un bouton intitul Fire . Cliquez une fois dans la colonne pin juste
ct du bouton. Les cases pin et action se remplissent. Elargissez les colonnes la
souris pour mieux voir.
Nous allons maintenant prciser laction de notre bouton. Dans la case type , nous
slectionnons asynch pour asynchrone . En effet, lvnement pourra intervenir
nimporte quel moment de lexcution du programme.
126
A laide du menu droulant de la case pin , nous allons dterminer quelle pin sera
stimule par laction sur le bouton. Comme notre bouton se trouve sur la pin RB0,
slectionnez cette pin.
Si vous regardez dans la case action , vous voyez que vous avez accs au mode de
fonctionnement du bouton. Vous avez le choix entre Pulse (gnre une impulsion), Low
(place un niveau 0), High (place un niveau 1), ou Toggle (inversion du niveau chaque
pression). Nous choisirons la moins pratique pour cet exemple, mais la plus explicite.
Choisissez donc Low . Votre bouton de stimulation est maintenant configur. Vous
devriez obtenir une fentre du style suivant :
Crez maintenant une nouvelle ligne, avec add row , et crez un second bouton,
mais avec le paramtre High dans la case action. Vous pouvez galement placer un
commentaire dans les cases comments . Ne vous gnez pas.
127
Examinons le registre PORTB dans la fentre daffichage des registres spciaux. Vous
voyez que tous les bits sont des 0. En effet, MPLAB ne peut pas connatre llectronique que
vous avez connect sur ses pins. Cest donc vous de lui indiquer le niveau que vous tes
sens avoir sur les dites pins. Pour ceux qui nauraient pas compris le fonctionnement de la
rsistance de rappel, voici une nouvelle fois le schma quivalant :
Nous voyons donc que, quand le bouton-poussoir nest pas press, nous avons un
niveau 1 sur RB0 provoqu par la rsistance de rappel que nous avons mise en service.
Pressons donc le second bouton une seule fois, et allons dans lditeur. Pressons <F7>
pour avancer dun pas et valider la modification de niveau. Examinez PORTB : RB0 est
maintenant pass 1. Notre bouton-poussoir nest pas enfonc. Pressez quelques fois <F7>
pour vrifier que rien dautre ne sest pass.
excute, vous constatez que la LED sest allume (RA2 est pass 1 sur le registre PORTA).
Avancez lentement jusqu ce que la ligne :
soit slectionne et ne pressez plus <F7>. A cet endroit, nous trouvons le retour de la routine
dinterruption vers le programme principal. Pressez une nouvelle fois <F7>.
Pour provoquer une interruption, il faut que le bit Enable ET le bit Flag dune des sources
dinterruptions soient 1. Or, il ny a quun seul bit Enable 1, et cest INTE.
128
Examinons donc INTF (cest le bit 1 de INTCON). Ce bit est toujours 1, donc nouvelle
interruption. Nous avons donc commis une erreur classique. Nous avons oubli deffacer le
flag la fin du traitement de notre interruption. Remarquez que cet effacement est intgr
dans la partie switch de la routine dinterruption du fichier m16f84.asm. Nous avons
effac cette ligne par mgarde en supprimant les diffrents tests (en fait je vous lai
volontairement fait supprimer par mgarde : jai not quon mmorise mieux suite une
erreur). Somme toutes, vous avez supprim la ligne linsu de votre plein gr .
Il nous faut donc ajouter la ligne suivante dans notre sous-routine intrb0
Recompilons notre programme avec <F10>, puis <F6>, et enfin, recommencez toute
la procdure que nous venons de voir.
Placez votre PIC dans le programmateur, et envoyez lui le fichier Myinter.hex . Placez
votre PIC sur la platine dessais (modifie) et pressez le B.P. plusieurs reprises. La LED ne
fonctionne pas du tout comme prvu, Elle ragit, mais de manire alatoire. Que se passe-t-
il ?
129
12.16 Se mettre lchelle de temps du PIC
Et bien, cest tout simple. Les PICs sont des composants trs rapides. Ils ne travaillent
pas la mme chelle de temps que nous. Essayons de nous transformer en PIC. Nous voyons
alors un norme Bouton poussoir.
Lorsque ce B.P. est press, cest alors une norme barre qui vient court-circuiter 2
contacts. Cette barre est lastique. Que voit le PIC ? Il voit une norme barre flexible qui
tombe dune norme hauteur sur 2 contacts mtalliques. Une fois la barre en contact, elle
REBONDIT plusieurs fois. A chaque pression sur le B.P., le PIC voit donc une srie de
fermeture et douverture du B.P., au lieu dune seule notre chelle de temps.
Noubliez donc jamais que les PICs ne travaillent pas une chelle de temps humaine.
Vous devez en tenir compte.
Nous allons utiliser nos connaissances actuelles pour rsoudre ce problme. Il devient
utile de dessiner un ordinogramme de ce que nous voulons faire :
Explications
130
Le programme principal effectue normalement ses initialisations, puis teste si une
demande de tempo a t introduite en positionnant le flag tempo . Si le flag nest pas mis,
il boucle sans fin.
Si le B.P. est press, une interruption est gnre, RA2 est invers, la routine
dinterruption positionne le flag tempo 1 et interdit toute nouvelle interruption de RB0.
Toute autre action sur RB0 sera donc sans effet (donc les rebonds ne sont pas pris en compte).
La routine dinterruption prend fin. Retour au programme principal, qui continue alors
tester le flag tempo. Celui-ci vient dtre positionn par la routine dinterruption. Le
programme principal appelle alors une routine de tempo (que nous avons dj vue dans la
leon principale).
Aprs coulement du temps ncessaire la fin des rebonds, le flag tempo est annul (pour
ne pas boucler sans fin), et les interruptions sont nouveau autorises, afin de permettre de
prendre en compte une nouvelle pression sur le B.P.
Vous voyez donc ici quil peut tre utile dans un programme dinterrompre et de relancer
les interruptions certains moments spcifiques.
;*********************************************************************
; SOUS-ROUTINE DE TEMPORISATION *
;*********************************************************************
;---------------------------------------------------------------------
; Cette sous-routine introduit un retard de 500.000 s.
; Elle ne reoit aucun paramtre et n'en retourne aucun
;---------------------------------------------------------------------
tempo
movlw 2 ; pour 2 boucles
movwf cmpt3 ; initialiser compteur3
boucle3
clrf cmpt2 ; effacer compteur2
boucle2
clrf cmpt1 ; effacer compteur1
boucle1
nop ; perdre 1 cycle
decfsz cmpt1 , f ; dcrmenter compteur1
goto boucle1 ; si pas 0, boucler
decfsz cmpt2 , f ; si 0, dcrmenter compteur 2
goto boucle 2 ; si cmpt2 pas 0, recommencer boucle1
decfsz cmpt3 , f ; si 0, dcrmenter compteur 3
goto boucle3 ; si cmpt3 pas 0, recommencer boucle2
return ; retour de la sous-routine
Nous allons modifier lgrement cette sous-routine. Nous pouvons enlever la boucle
extrieure, car, 500ms cest beaucoup plus que le temps de rebond du B.P. Enlevons
galement linstruction nop. Nous obtenons :
131
;*********************************************************************
; SOUS-ROUTINE DE TEMPORISATION *
;*********************************************************************
;---------------------------------------------------------------------
; Cette sous-routine introduit un retard
; Elle ne reoit aucun paramtre et n'en retourne aucun
;---------------------------------------------------------------------
tempo
clrf cmpt2 ; effacer compteur2
boucle2
clrf cmpt1 ; effacer compteur1
boucle1
decfsz cmpt1 , f ; dcrmenter compteur1
goto boucle1 ; si pas 0, boucler
decfsz cmpt2 , f ; si 0, dcrmenter compteur 2
goto boucle2 ; si cmpt2 pas 0, recommencer boucle1
return ; retour de la sous-routine
Nous ne nous sommes donc pas servi de la variable cmpt3. Nous pouvons donc la
supprimer de notre zone des variables. Tant que nous y sommes, nous allons avoir besoin
dun flag, cest dire dun bit. Crons-le dans cette zone.
;*********************************************************************
; DECLARATIONS DE VARIABLES *
;*********************************************************************
;*********************************************************************
; PROGRAMME PRINCIPAL
*
;*********************************************************************
start
btfss tempoF ; tester si tempo flag mis
goto start ; non, attendre qu'il soit mis
call tempo ; oui, excuter tempo
bcf tempoF ; effacer flag tempo
bsf INTCON , INTE ; remettre interrupts INT en service
goto start ; boucler
END ; directive fin de programme
132
Il ne reste plus qu modifier notre routine dinterruption en fonction de notre
ordinogramme. Nous obtenons :
;**********************************************************************
; INTERRUPTION RB0/INT *
;**********************************************************************
;----------------------------------------------------------------------
; inverse le niveau de RA2 chaque passage
; interdit toute nouvelle interruption
; valide le flag tempo
;----------------------------------------------------------------------
intrb0
movlw B'00000100' ; bit positionn = bit invers
BANK 0 ; car on ne sait pas sur quelle banque
; on est dans une interruption (le
; programme principal peut avoir chang
; de banque). Ce n'est pas le cas ici,
; mais c'est une sage prcaution
xorwf PORTA , f ; inverser RA2
bcf INTCON , INTF ; effacer flag INT/RB0
bcf INTCON , INTE ; interdire autre inter. RB0
bsf tempoF ; positionner flag tempo
return ; fin d'interruption RB0/INT
Compilons notre programme et chargeons le nouveau fichier .hex dans notre PIC.
Lanons lalimentation. Cela ne fonctionne toujours pas, pourquoi ? Et bien rflchissons ce
qui se passe.
Vous devez donc penser tout lorsque vous utilisez les interruptions. Si un programme
fonctionne au simulateur et pas sur le circuit rel, commencez par souponnez des problmes
de timing ?
Il nous suffit donc dajouter une instruction de reset du flag INTF avant de remettre les
interruptions INT en service.
Bien entendu, vous pouvez vous dire quil devient inutile deffacer ce flag dans la routine
dinterruption. Cest logique, mais il vaut mieux prendre de bonnes habitudes. Laissons donc
cette instruction.
Recompilez votre programme, et rechargez-le dans votre PIC. Alimentez votre montage.
Cette fois cela fonctionne parfaitement. Voici un montage trs pratique utiliser. Si vous
remplacez la LED par un petit relais ou un triac optocoupl, vous voil en possession dun
tlrupteur. Placez un bouton-poussoir dans chaque endroit do vous dsirez allumer la
lampe, et vous pouvez allumer ou teindre celle-ci depuis plusieurs endroits, sans utiliser
dinterrupteurs spciaux avec un tas de fils tirer.
133
A titre de bonus, voici le schma dun tlrupteur oprationnel fonctionnant avec votre
programme :
Nous avons utilis une temporisation de valeur quelconque. Cette temporisation inhibe
toute action sur le B.P. (cest son but) durant +- 250mS. Donc, vous pourrez presser au grand
maximum 4 fois sur le B.P. par seconde.
Mais quelle est la dure relle des rebonds ? Et bien, elle dpend de linterrupteur
utilis, technologie et taille. Pour connatre le temps de rebond de votre propre interrupteur,
diminuez progressivement la dure de la temporisation. Une fois que votre tlrupteur ne
fonctionne plus chaque pression, vous avez atteint la limite. Calculez alors la dure de votre
temporisation, vous aurez la dure approximative des rebonds.
Souvenez-vous, quune fois que vous utilisez les interruptions dans un programme, vous
ne pouvez jamais savoir le temps qui va sparer 2 instructions successives.
En effet, entre les instructions en question peut avoir t trait une ou plusieurs routine(s)
dinterruption.
De plus, pour toute squence dont le droulement en temps est critique et ne peut tre
interrompu, vous devez inhiber les interruptions. A votre charge de les remettre en service en
temps utile.
134
Une fois que vous utilisez les interruptions, votre programme devra affronter des
vnements asynchrones avec son droulement. Donc vous ne pourrez JAMAIS tester
toutes les ventualits possibles.
Ceci vous explique pourquoi des gestions de processus critiques en temps rel utilisent
plusieurs ordinateurs (navette spatiale). Ces ordinateurs tant dsynchroniss, un bug de cette
nature qui apparat sur un deux a peu de chance de se produire simultanment sur un second.
Pour savoir lequel a pos problme, il faut donc un troisime ordinateur.
Pensez toujours ceci si vous tes amens un jour raliser un programme dont dpend la
scurit de personnes ou de biens.
Si vous comprenez bien tout ceci, vous voyez que les bugs ventuels lis des erreurs
de programmation peuvent apparatre tout moment et de faon qui semble alatoire. Et vous
vous tonnez que votre ordinateur plante ?
12.20 Conclusions
Jespre avoir dmythifi ce concept, trop souvent imagin comme la mthode des
pros . En ralit, une fois de plus, pas de magie. Ce nest quune exploitation, certes parfois
complexe, de processus simples et faciles apprhender.
Gardez seulement lesprit que vous quittez le monde du synchrone pour entrer dans le
monde de lasynchrone, beaucoup plus difficile simuler totalement de faon efficace.
135
13. Le Timer 0
Dans ce chapitre, nous allons parler temporisations et comptages. Le 16F84 ne
comporte quun seul timer sur 8 bits, contrairement dautres PICs de la famille (comme le
16F876). Si on examine attentivement le fonctionnement du timer0, on voit quil sagit en fait
dun compteur.
Nous avons vu que le timer0 est en fait un compteur. Mais quallez-vous compter avec ce
timer? Et bien, vous avez deux possibilits :
- En premier lieu, vous pouvez compter les impulsions reues sur la pin RA4/TOKI.
Nous dirons dans ce cas que nous sommes en mode compteur
- Vous pouvez aussi dcider de compter les cycles dhorloge du PIC lui-mme. Dans ce
cas, comme lhorloge est fixe, nous compterons donc en ralit du temps. Donc, nous
serons en mode timer .
La slection dun ou lautre de ces deux modes de fonctionnement seffectue par le bit
5 du registre OPTION : T0CS pour Tmr0 Clock Source select bit.
Dans le cas o vous dcidez de travailler en mode compteur, vous devez aussi prciser
lors de quelle transition de niveau le comptage est effectu. Ceci est prcis grce au bit 4 du
registre OPTION : T0SE pour Timer0 Source Edge select bit.
Comment utiliser le timer0, et quelles sont les possibilits offertes ce niveau, voil de
quoi nous allons parler ici.
136
13.3.1 Le mode de lecture simple
La premire mthode qui vient lesprit est la suivante : Nous lisons le registre tmr0
pour voir ce quil contient. La valeur lue est le reflet du nombre dvnements survenus, en
prenant garde au fait que le tmr0 ne peut compter que jusque 255. En cas de dpassement, le
tmr0 recommence 0. Cest donc vous de grer cette possibilit.
Petit exemple :
Nous devons savoir ce niveau, que tout dbordement du timer0 (passage de 0xFF
0x00) entrane le positionnement du flag T0IF du registre INTCON. Vous pouvez donc
utiliser ce flag pour dterminer si vous avez eu dbordement du timer0, ou, en dautres
termes, si le temps programm est coul. Cette mthode linconvnient de vous faire perdre
du temps inutilement
Petit exemple :
Mais vous pourriez vous dire que vous ne dsirez pas forcment attendre 256
incrmentations de tmr0. Supposons que vous dsiriez attendre 100 incrmentations. Il suffit
dans ce cas de placer dans tmr0 une valeur telle que 100 incrmentations plus tard, tmr0
dborde.
exemple :
movlw 256-100 ; charger 256 100
movwf tmr0 ; initialiser tmr0
bcf INTCON,T0IF ; effacement du flag
loop
btfss INTCON,T0IF ; tester si compteur a dbord
goto loop ; non, attendre dbordement
xxx ; oui, poursuivre : 100 vnements couls
Ceci pourrait sembler correct, mais en fait toute modification de TMR0 entrane
un arrt de comptage de la part de celui-ci correspondant 2 cycles dinstruction. Il
faut donc tenir compte de cette perte, et placer 256-98 et non 256-100 dans le
timer (si le prdiviseur nest pas utilis)
137
13.3.3 Le mode dinterruption
Cest videmment le mode principal dutilisation du timer0. En effet, lorsque T0IE est
positionn dans le registre INTCON, chaque fois que le flag T0IF passe 1, une interruption
est gnre. La procdure utiliser est celle vue dans la leon sur les interruptions.
Supposons que vous vouliez, par exemple, mesurer un temps entre 2 impulsions sur le
broche RB0. Supposons galement que ce temps soit tel que plusieurs dbordements du tmr0
puissent avoir lieu. Une mthode simple de mesure du temps serait la suivante :
On a donc utilis les interruptions pour les multiples de 256, et la lecture directe de tmr0 pour
les units .
13.4 Le prdiviseur
Supposons que nous travaillions avec un quartz de 4MHz. Nous avons donc dans ce cas
(4000000/4) = 1.000.000 de cycles par seconde. Chaque cycle dhorloge dure donc
1/1000000me de seconde, soit 1s.
Si nous dcidons dutiliser le timer0 dans sa fonction timer et en mode interruption. Nous
aurons donc une interruption toutes les 256s, soit peu prs tous les quarts de millime de
seconde.
Si nous dsirons raliser une LED clignotante une frquence de +- 1Hz, nous aurons
besoin dune temporisation de 500ms, soit 2000 fois plus. Ce nest donc pas pratique.
Nous disposons pour amliorer ceci dun PREDIVISEUR .
Regardez le tableau de la page 16 du datasheet. Vous voyez en bas le tableau des bits PS0
PS2 du registre OPTION qui dterminent la valeur du prdiviseur.
Ces valeurs varient, pour le timer0, entre 2 et 256. Le bit PSA, quant lui, dtermine si le
prdiviseur est affect au timer0 ou au watchdog. Voici un tableau exprimant toutes les
possibilits de ces bits :
138
PSA PS2 PS1 PS0 /tmr0 /WD Temps tmr0 Temps typique Watchdog
(minimal)
0 0 0 0 2 1 512 s 18 ms (7ms)
0 0 0 1 4 1 1024 s 18 ms (7ms)
0 0 1 0 8 1 2048 s 18 ms (7ms)
0 0 1 1 16 1 4096 s 18 ms (7ms)
0 1 0 0 32 1 8192 s 18 ms (7ms)
0 1 0 1 64 1 16384 s 18 ms (7ms)
0 1 1 0 128 1 32768 s 18 ms (7ms)
0 1 1 1 256 1 65536 s 18 ms (7ms)
1 0 0 0 1 1 256 s 18 ms (7ms)
1 0 0 1 1 2 256 s 36 ms (14 ms)
1 0 1 0 1 4 256 s 72 ms (28 ms)
1 0 1 1 1 8 256 s 144 ms (56 ms)
1 1 0 0 1 16 256 s 288 ms (112 ms)
1 1 0 1 1 32 256 s 576 ms (224 ms)
1 1 1 0 1 64 256 s 1,152 Sec (448 ms)
1 1 1 1 1 128 256 s 2,304 Sec (996 ms)
Remarques importantes :
- Il ny a quun prdiviseur, qui peut tre affect au choix au timer du watchdog (que nous
verrons plus tard) ou au timer0. Il ne peut tre affect aux deux en mme temps.
- La valeur contenue dans le prdiviseur nest pas accessible. Par exemple, si vous dcidez
dutiliser un prdiviseur de 64, et quil y a un moment donn 30 vnements dj
survenus, vous navez aucun moyen de le savoir. Le prdiviseur limite donc la prcision
en cas de lecture directe.
- Lcriture dans le registre tmr0 efface le contenu du prdiviseur. Les vnements survenus
au niveau du prdiviseur sont donc perdus.
139
13.5 Application pratique du timer0
Nous allons mettre en uvre notre tmr0 dans une premire application pratique.
Reprenons donc notre premier exercice, savoir, faire clignoter une LED la frquence
approximative de 1Hz.
13.5.1 Prparations
;**********************************************************************
; *
; Fait clignoter une LED une frquence approximative de 1Hz *
; *
;**********************************************************************
; *
; NOM: LED CLIGNOTANTE AVEC TIMER0 *
; Date: 17/02/2001 *
; Version: 1.0 *
; Circuit: Platine d'essai *
; Auteur: Bigonoff *
; *
;**********************************************************************
; *
; Fichier requis: P16F84.inc *
; *
;**********************************************************************
; *
; Notes: Utilisation didactique du tmr0 en mode interruption *
;**********************************************************************
Le timer0 gnre, sans prdiviseur, une interruption toutes les 256s . Nous allons donc
utiliser le prdiviseur. Si nous prenons la plus grande valeur disponible, soit 256, nous aurons
donc une interruption toutes les (256*256) = 65536s.
Nous devrons donc passer (500.000/65536) = 7,63 fois dans notre routine dinterruption.
Comme nous ne pouvons pas passer un nombre dcimal de fois, nous choisirons 7 ou 8 fois,
suivant que nous acceptons une erreur dans un sens ou dans lautre.
Notez que si vous passez 7 fois, vous aurez compt trop peu de temps, il sera toujours
possible dallonger ce temps. Dans le cas contraire, vous aurez trop attendu , donc plus de
correction possible.
140
Il est vident que lacceptation dune erreur est fonction de lapplication. Si vous
dsirez faire clignoter une guirlande de Nol, lerreur de timing sera drisoire. Si par contre
vous dsirez construire un chronomtre, une telle erreur sera inacceptable. Commenons donc
par ignorer lerreur.
Nous allons dcider dutiliser une prdivision de 256 avec 7 passages dans la routine
dinterruption. Le temps obtenu sera donc en ralit de (256*256*7) = 458752 s au lieu de
nos 500.000s thoriques.
En reprenant notre tableau page16 sur le contenu du registre OPTION, nous devrons
donc initialiser celui-ci avec : B10000111, soit 0x87. En effet, rsistances de rappel hors-
service (on nen na pas besoin), source timer0 en interne et prdiviseur sur timer0 avec
valeur 256. Nous obtenons donc :
Ensuite nous devons dterminer la valeur placer dans le registre INTCON pour obtenir
les interruptions sur le timer0. Ce sera B10100000, soit 0xA0
;*********************************************************************
; DEFINE *
;*********************************************************************
#DEFINE LED PORTA,2 ; LED
Ecrivons donc notre routine dinterruption timer. Nous voyons tout dabord que nous
allons devoir compter les passages dans tmr0, nous allons donc avoir besoin dune variable.
Dclarons-la dans la zone 0X0C.
13.5.2 Linitialisation
Comme il est plus facile de dtecter une valeur gale 0 qu 7, nous dcrmenterons
donc notre variable de 7 0. Nous inverserons la LED une fois la valeur 0 atteinte. Nous
devons donc initialiser notre variable 7 pour le premier passage.
Nous effectuerons ceci dans la routine dinitialisation, avant le goto start. Profitons-en
galement pour placer notre port LED en sortie.
141
;*********************************************************************
; INITIALISATIONS *
;*********************************************************************
init
clrf PORTA ; Sorties portA 0
clrf PORTB ; sorties portB 0
clrf EEADR ; permet de diminuer la consommation
BANK1 ; passer banque1
movlw OPTIONVAL ; charger masque
movwf OPTION_REG ; initialiser registre option
; Effacer RAM
; ------------
movlw 0x0c ; initialisation pointeur
movwf FSR ; pointeur d'adressage indirect
init1
clrf INDF ; effacer ram
incf FSR,f ; pointer sur suivant
btfss FSR,6 ; tester si fin zone atteinte (>=0x40)
goto init1 ; non, boucler
btfss FSR,4 ; tester si fin zone atteinte (>=0x50)
goto init1 ; non, boucler
; initialiser ports
; -----------------
bcf LED ; passer LED en sortie
BANK0 ; passer banque 0
; initialisations variables
; -------------------------
movlw 7 ; charger 7
movwf cmpt ; initialiser compteur de passages
Tout dabord, on dcrmente notre compteur de passage, sil nest pas nul, on na rien
faire cette fois.
Ensuite, si le rsultat est nul , nous devons inverser la LED et recharger 7 dans le
compteur de passages. Voici le rsultat final :
142
;**********************************************************************
; INTERRUPTION TIMER 0 *
;**********************************************************************
inttimer
decfsz cmpt , f ; dcrmenter compteur de passages
return ; pas 0, on ne fait rien
BANK0 ; par prcaution
movlw b'00000100' ; slectionner bit inverser
xorwf PORTA , f ; inverser LED
movlw 7 ; pour 7 nouveaux passages
movwf cmpt ; dans compteur de passages
return ; fin d'interruption timer
Remarques
- Le dernier registre est dans la fentre des registres spciaux T0pre est un registre qui
nexiste pas physiquement dans le PIC. Cest MPLAB qui compte les prdivisions pour
les besoins de la simulation.
- Chaque fois que T0pre atteint la valeur de prdivision, tmr0 est incrment de 1. Ce
nest que lorsquil dbordera que nous aurons une interruption.
- Dans le programme principal, T0pre est incrment de 2 units chaque pression sur
<F7>. Cest normal, car ce programme ne comporte quun saut (goto), et chaque saut
prend 2 cycles.
Comme nous nallons pas passer des heures simuler ce programme, nous allons modifier
les registres en cours de simulation. Ceci est trs simple effectuer dans MPLAB6, puisquil
suffit de double-cliquer sur la valeur modifier, dans la fentre special function registers .
De plus, vous pouvez cliquer dans la colonne de votre choix, ce qui vous permet dentrer la
valeur en dcimal, hexadcimal, ou binaire.
143
Maintenant, chaque pression de <F7> incrmente tmr0 (pas de prdiviseur)
Ouvrez ensuite une fentre de visualisation des variables, avec view >watch. Affichez
ensuite la variable cmpt comme expliqu dans les chapitres prcdents.
Chargez le fichier .hex obtenu dans votre PIC et alimentez votre platine dessais. Comptez
les allumages de la LED obtenus en 1 minute. Vous devriez trouver aux alentours de 65/66
pulses par minute. Ceci vous montre la prcision obtenue.
144
13.8 Premire amlioration de la prcision
Quelle va tre la prcision obtenue ? Et bien, nous initialiserons cmpt 244, avec
prdiviseur 8. Dans ce cas, la dure obtenue sera de :
En une minute, nous aurons donc 60000000/999424 = 60,034 allumages. Voici donc
une prcision nettement meilleure.
Vous pouvez maintenant modifier vous-mme votre programme selon ces indications.
Vous voyez que vous devez modifier la valeur 07 en 244 2 endroits. Ce nest pas
pratique. Ajoutez donc une assignation, par exemple
Si vous avez un problme, le fichier fonctionnel de cet exercice est disponible sous la
dnomination Led_tmr.asm .
- Inconvnient : plus dinterruptions gnres, donc plus de temps perdu pour le programme
principal. Dans notre cas, cela na pas dimportance, le programme ne fait rien dautre,
mais ce ne sera pas toujours le cas.
Vous pouvez encore amliorer la prcision de votre programme. En effet, vous pouvez
ne pas utiliser de prdiviseur, donc utiliser plusieurs compteurs pour 1953,125 passages. Au
1953me passage, vous pourrez mme gnrer une dernire tempo en ajoutant une valeur au
tmr0. Par exemple :
145
- On devrait donc ajouter 256-32 = 224 tmr0, mais vu les 2 Tcy perdus systmatiquement
lors de toute modification de TMR0, on ajoutera 256-30 :
Bien entendu, 32s pour tout raliser, cest trs court, aussi nous devrons optimiser les
routines dinterruption au maximum. Suppression des tests et des sous-programmes etc. Mais
cela reste en gnral la limite du possible. Nous ne traiterons pas ce procd ici, car cela ne
prsente pas dintrt, dautant que les interruptions vont finir par occuper la majorit du
temps CPU.
Supposons que vous vouliez construire un chronomtre. La prcision est la donne la plus
importante dans ce cas, et passe bien avant la vitesse. Nous allons donc nous arranger pour
que les dmultiplicateurs tombent sur des multiples entiers. Comment ? Et bien simplement
en changeant le temps dune instruction, donc, en changeant le quartz du PIC.
Exemple :
Comme nous ne pouvons pas acclrer un PIC au dessus de sa vitesse maximale (nous
utilisons un PIC 4MHz), nous pouvons seulement le ralentir. Nous partons donc dune base de
temps trop rapide.
Par exemple : reprenons notre cas de dpart : prdiviseur 256, compteur de passages 7.
Dure avec un quartz de 4MHz : 256*256*7 par tempo, donc 256*256*7*2 par allumage, soit
917504 s. Or, nous dsirons 1000000s.
Cela nous donne donc une frquence dinstructions de 1/1,089913504s = 0,917504 MHz.
Comme la frquence des cycles internes est gale la frquence du quartz/4, nous aurons
donc besoin dun quartz de 0,917504 * 4 = 3,670016 MHz. (MHz car nous avons divis par
des s : or, diviser par un millionime revient multiplier par un million).
La seule contrainte est donc de savoir sil existe des quartz de cette frquence
disponibles dans le commerce. Dans le cas contraire, vous recommencez vos calculs avec
dautres valeurs de prdiviseurs et de compteur.
Si vous trouvez donc un quartz de frquence approprie, vous obtenez une horloge de
la prcision de votre quartz. Vous ajoutez un affichage, et voil une horloge quartz.
146
13.11 La mthode de luxe : La double horloge
La mthode prcdente prsente linconvnient de ralentir le PIC. Que faire si vous voulez
la fois une vitesse maximale et une prcision galement maximale ? Et bien, aucun
problme.
Vous alimentez votre PIC avec votre quartz et vous crez un autre oscillateur externe
avec votre quartz spcial timing. Vous appliquez le signal obtenu sur la pin RA4/TOKI et
vous configurez votre timer0 en mode compteur.
Donc, votre PIC tourne vitesse maximale, et les interruptions timer0 sont gnres par
une autre base de temps, plus adapte la mesure de vos vnements.
Dans ce petit exemple nous allons utiliser 2 sources dinterruption diffrentes, afin de
vous montrer un exemple concret de ce type dutilisation. Nous allons recrer notre
programme de tlrupteur, mais en remplaant la temporisation par une interruption sur le
timer0.
Remarquez que notre programme principal ne fait plus rien. Vous pouvez donc utiliser
dautres possibilits sur cette carte sans perturber le fonctionnement du tlrupteur.
147
Nous aurons donc une interruption pour RB0, et une autre pour tmr0. Vous voyez ci-
dessous lordinogramme qui va nous servir.
Crez votre routine dinterruption timer0 toutes les 260ms, soit prdiviseur 256, et 4
passages .
Une pression sur le B .P. allume la LED, une autre lteint. Si cela ne fonctionne pas,
cherchez lerreur ou servez-vous du simulateur. Je vous fourni le programme fonctionnel
dans le cas o vous seriez bloqus.
Remarque
Il est trs important de bien comprendre quil faut effacer tmr0 AVANT deffacer le flag
T0IF et de relancer les interruptions tmr0.
En effet, si vous faites le contraire, vous risquez que tmr0 dborde entre le moment de
leffacement du flag et le moment de leffacement de tmr0. Dans ce cas le flag serait remis
immdiatement aprs lavoir effac. Votre programme pourrait donc avoir des rats par
intermittence.
Il ne faut pas non plus oublier que toute modification de TMR0 entraine le nom comptage
des deux prochains Tcy.
13.13 Conclusion
Vous savez maintenant exploiter le timer0. Les mthodes voques ici sont une base de
travail pour des applications plus srieuses. Je vous conseille vraiment deffectuer toutes les
manipulations voques. Mme les erreurs vous seront profitables.
148
14. Les accs en mmoire eeprom
Je vais vous parler dans ce chapitre des procdures daccs dans leeprom interne du PIC.
Il ne faut pas confondre ceci avec lcriture dans une eeprom externe type 2416. Pour ce type
deeprom, il suffit de suivre les directives du datasheet du composant concern, jen
parlerai dailleurs dans la seconde partie du cours.
Ladresse physique de la zone eeprom commence, pour les PICs mid-range, ladresse
0x2100.
Cette adresse se situe hors de lespace dadressage normal des PICs (rappelez-vous,
maximum 8Kmots, donc adresse maxi : 0x1FFF), donc nous pouvons dj en dduire quil
nous faudra utiliser une procdure spciale pour y accder.
Ceci est galement vrai pour des registres spciaux des PICs. Par exemple, ladresse
0x2007 contient les paramtres que vous crivez dans _CONFIG. Vous pourriez donc
remplacer cette directive par une initialisation directe ladresse 0x2007. Je vous le
dconseille cependant pour des raisons de portabilit et dvolution rapide vers une autre
famille de PICs. De plus, pourquoi faire compliqu quand on peut faire simple ?
Le 16F84 dispose de 64 emplacements eeprom disponibles pour votre libre usage. Nous
allons voir comment les utiliser.
149
;**********************************************************************
; *
; Fait clignoter une LED une frquence dpendant d'une valeur en *
; eeprom *
; *
;**********************************************************************
; *
; NOM: LED CLIGNOTANTE AVEC TIMER0 et utilisation de l'eeprom *
; Date: 18/02/2001 *
; Version: 1.0 *
; Circuit: Platine d'essai *
; Auteur: Bigonoff *
; *
;**********************************************************************
; *
; Fichier requis: P16F84.inc *
; *
;**********************************************************************
; *
; Notes: Dmonstration de l'utilisation des donnes en eeprom *
; La base de temps de clignotement est contenue dans *
; l'eeprom. *
;
*
;**********************************************************************
Ajoutons ensuite une variable dans la zone des variables. Elle contiendra la valeur
recharger dans le compteur.
Dans notre programme initial, chaque fois que le compteur de passages dans le timer
arrivait 0, on le rechargeait avec la valeur 0x07. Maintenant, nous le rechargerons avec la
valeur contenue dans la variable reload . La procdure utilise est la suivante :
Je vous donne lordinogramme de ce que nous allons raliser dans un premier temps.
150
Vous pourriez remarquer quil peut sembler inutile de lire leeprom et de recopier son
contenu dans reload. Pourquoi donc ne pas utiliser la valeur eeprom directement dans le reste
de notre programme ? La rponse est simple. La procdure de lecture en eeprom est plus
complexe quune simple lecture en RAM. Il faut donc limiter les accs eeprom au maximum.
Commenons par modifier notre routine dinterruption. La seule ligne modifier cest
celle qui chargeait doffice la valeur 7 dans w. Maintenant, nous y mettons le contenu de
reload. Nous aurons donc :
inttimer
decfsz cmpt , f ; dcrmenter compteur de passages
return ; pas 0, on ne fait rien
BANK0 ; par prcaution
movlw b'00000100' ; slectionner bit inverser
xorwf PORTA , f ; inverser LED
movf reload , w ; charger valeur contenue dans reload
movwf cmpt ; dans compteur de passages
return ; fin d'interruption timer
Nous voyons sur notre ordinogramme que nous lisons notre eeprom afin de placer le
contenu dans notre variable. Mais nous devons bien quant mme initialiser cette eeprom au
moment de la programmation de notre PIC.
Vous vous doutez bien quil ne sert rien dinitialiser leeprom chaque dmarrage du
PIC, sinon, quel est lintrt dutiliser une zone mmoire qui rsiste au reset et la mise hors
tension ?
151
Nous initialiserons donc cette zone directement au moment de la programmation. Ceci
seffectue laide de la directive DE pour Data Eeprom, place dans la zone de donnes
eeprom, cest dire en 0x2100.
Crons donc une zone eeprom, tout de suite aprs celle des variables.
;*********************************************************************
; DECLARATIONS DE LA ZONE EEPROM *
;*********************************************************************
org 0x2100 ; adresse dbut zone eeprom
DE 0x07 ; valeur de recharge du compteur
Lancez la compilation de votre programme. Vous voulez sans doute vrifier que votre
eeprom contient bien la valeur 0x07 ? Rien de plus simple : lancez EEPROM memory
dans le menu Windows et vous voyez votre valeur.
Mais, allez-vous me rpondre, la valeur est ladresse 0x00 et pas ladresse 0x2100 ?
En effet, il faut distinguer 2 adresses. Ladresse physique de cet emplacement mmoire est
bien 0x2100. Cette adresse est uniquement accessible en mode programmation.
Par contre, votre programme accdera ces emplacements partir dune procdure
spciale et avec une adresse dite relative. Cette adresse daccs commence donc 0x00.
Donc, pour rsumer, pour accder ladresse 0x2100, vous utiliserez la procdure daccs
EEPROM avec ladresse 0x00. Et ainsi de suite : 0x2101 correspondra 0x01
Bien entendu, vous pouvez galement donner un nom ces adresses, tout comme pour les
variables. Utilisons donc le nom eereload pour dsigner la valeur de reload contenue en
eeprom ladresse 0x00. Ajoutons simplement un define dans la zone dinitialisation eeprom
ou encore
Dans notre ordinogramme nous allons avoir besoin de lire leeprom. 4 registres sont
utiliss pour accder leeprom. Nous allons maintenant les examiner.
Cest dans ce registre que va transiter la donne crire vers ou la donne lue en
provenance de leeprom. Ce registre est situ ladresse 0x08 banque 0.
152
14.5 Le registre EEADR
Dans ce registre, situ ladresse 0x09 banque 0, nous allons prciser sur 8 bits ladresse
concerne par lopration de lecture ou dcriture en eeprom. Nous voyons dj que pour cette
famille de PICs, nous ne pourrons pas dpasser 256 emplacements deeprom. Pour le 16F84,
la zone admissible va de 0x00 0x3F, soit 64 emplacements.
Ce registre, situ ladresse 0x88 en banque1, contient 5 bits qui dfinissent ou indiquent
le fonctionnement des cycles de lecture/criture en eeprom. Voici son contenu :
bits 7/6/5
non utiliss
bit 4 : EEIF
Pour EEprom write operation Interrupt Flag bit. Cest le flag qui est en liaison avec
linterruption EEPROM. Il passe 1 une fois lcriture en eeprom termine. Si le bit EEIE du
registre INTCON est 1, une interruption sera alors gnre
bit 3 : WRERR
WRite ERRor. Cest un bit derreur. Il passe 1 si une opration dcriture en eeprom a
t interrompue, par exemple par un reset.
bit 2 : WREN
bit 1 : WR
WRite. Dmarrage du cycle dcriture. Est remis 0 automatiquement une fois lcriture
termine.
bit 0 : RD
ReaD. Dmarrage dun cycle de lecture. Reste 1 durant un cycle, puis est remis 0
automatiquement
153
14.7 Le registre EECON2
Nous revoici en prsence dun registre fantme , puisque ce registre nexiste pas. Il
sagit tout simplement dune adresse 0x89 banque1, qui sert envoyer des commandes au PIC
concernant les procdures eeprom. Vous ne pouvez lutiliser quen vous servant des
instructions expliques plus bas.
Pour lire une donne en eeprom, il suffit de placer ladresse concerne dans le registre
EEADR. Ensuite, vous positionnez le bit RD 1. Vous pouvez ensuite rcuprer la donne
lue dans le registre EEDATA. Il ne faut pas bien sr oublier les diffrents changements de
banques.
Comme cette procdure est courte et toujours la mme, nous allons crer une macro
cette intention. Comme la macro doit contenir ladresse de lecture, nous raliserons une macro
avec passage de paramtre. Voici la macro ajouter. Vous devrez tre dans la banque 0 pour
appeler cette macro, et elle vous retourne la valeur lue dans le registre W.
READEE macro adeeprom ; macro avec 1 paramtre (argument)
movlw adeeprom ; charger adresse eeprom (argument reu)
movwf EEADR ; adresse lire dans registre EEADR
bsf STATUS , RP0 ; passer en banque1
bsf EECON1 , RD ; lancer la lecture EEPROM
bcf STATUS , RP0 ; repasser en banque 0
movf EEDATA , w ; charger valeur lue dans W
endm ; fin de la macro
Vous remarquez que vous passez un argument la macro. Vous dsignez cet ou ces
arguments aprs la directive macro.
Nous avons utilis ici largument adeeprom pour indiquez ladresse eeprom. Chaque
utilisation de adeeprom dans notre macro sera remplace par largument reu au moment de
lappel de la macro.
Pour utiliser cette macro, nous devons donc lui passer un argument. Par exemple :
Cette macro, comme toutes les modifications principales, seront ajoutes votre fichier
m16f84.asm. Je vous le fournis modifi sous la dnomination m16f84_n2.asm .
Revenons notre ordinogramme. Nous devons donc ajouter la lecture de leeprom dans
linitialisation, et placer cette valeur lue dans reload ET dans cmpt. Voici la routine modifie :
154
; initialisations variables
; ----------------------------
READEE eereload ; lire emplacement eeprom 0x00
movwf reload ; placer dans reload
movwf cmpt ; et initialiser compteur de passages
goto start ; sauter programme principal
Compilez votre programme et placez-le dans le PIC. La LED doit maintenant clignoter
une frquence de 1Hz. Si cela ne fonctionne pas, vrifiez ou consultez le fichier
eep_test1.asm fourni avec cette leon.
Maintenant vous allez me dire avec raison que cela ne sert rien de lire en eeprom si on
narrive pas y crire. Notre programme ne prsente donc rien de plus que ce que nous avions
auparavant. Cest tout fait justifi. Aussi allons-nous tudier la mthode dcriture. Comme
vous vous en doutez, cette mthode utilise les mmes registres.
Remarques
- Microchip recommande que cette procdure spcifique ne soit pas interrompue par
une interruption, donc nous couperons les interruptions durant cette phase.
- La fin de lcriture peut tre constate par la gnration dune interruption (si le bit
EEIE est positionn), ou par la lecture du flag EEIF (sil avait t remis 0 avant
lcriture), ou encore par consultation du bit WR qui est 1 durant tout le cycle
dcriture.
Nous allons crire une macro dcriture en eeprom. Cette fois, nous devrons passer 2
paramtres, savoir la donne crire (mais nous supposerons que nous lavons place dans
W), et ladresse dcriture.
155
WRITEE macro addwrite ; la donne se trouve dans W
LOCAL loop ; tiquette locale
movwf EEDATA ; placer data dans registre
movlw addwrite ; charger adresse d'criture
movwf EEADR ; placer dans registre
loop
bcf INTCON , GIE ; interdire interruptions
btfsc INTCON , GIE ; tester si GIE bien 0
goto loop ; non, recommencer
bsf STATUS , RP0 ; passer en banque1
bcf EECON1 , EEIF ; effacer flag de fin d'criture
bsf EECON1 , WREN ; autoriser accs criture
movlw 0x55 ; charger 0x55
movwf EECON2 ; envoyer commande
movlw 0xAA ; charger 0xAA
movwf EECON2 ; envoyer commande
bsf EECON1 , WR ; lancer cycle d'criture
bcf EECON1 , WREN ; verrouiller prochaine criture
bsf INTCON , GIE ; rautoriser interruptions
bcf STATUS , RP0 ; repasser en banque 0
endm
Remarques
- Jai utilis ici 3 instructions pour mettre GIE 0. Ceci tait ncessaire cause dun
bug dans le 16C84, mais a t corrig dans le 16F84. Le test de vrification nest plus
ncessaire partir de cette version. Mais ceci me donnait loccasion de vous montrer
les tiquettes locales. Laissez-le donc pour exemple.
- La directive LOCAL prcise que le symbole utilis dans cette macro nexistera qu
lintrieur de celle-ci. Sans cette directive, si vous utilisiez un seul appel de la macro
WRITEE dans votre programme, aucun problme. Si maintenant vous utilisiez 2 fois
cette macro, pour chaque appel MPASM remplacerait WRITEE par toute la liste
dinstructions contenues jusque la directive endm. Vous auriez donc dans votre
programme rel 2 fois ltiquette loop 2 emplacements diffrents. Ceci gnrerait
une erreur. La directive LOCAL informe MPASM que chaque utilisation de la macro
travaille avec une tiquette loop diffrente. Il ny a donc plus double emploi.
- Toute la partie surligne de jaune contient la squence impose par Microchip pour
lcriture en eeprom.
- Le nombre de cycle dcritures en eeprom est limit. La dure de vie de leeprom est
denviron 10 millions de cycles. Si votre programme comporte une erreur et quil crit
sans arrt des donnes dans leeprom, votre PIC sera hors service en un peu moins de
28 heures. Soyez donc vigilants et vrifiez votre programme.
- Avant dcrire dans leeprom, vous devez vrifier quune autre criture nest en cours.
Utilisez le bit WR du registre EECON1. Sil vaut 0, il ny a pas dcriture en cours.
156
14.10 Utilisation pratique de la mmoire eeprom
Maintenant, nous allons de nouveau modifier notre programme pour quil crive dans
leeprom. Nous allons incrmenter la dure de temporisation tous les 16 clignotements de la
LED (donc tous les 32 passages dans la routine dinterruption), et sauvegarder cette nouvelle
valeur dans leeprom.
Nous naurons pas besoin des interruptions eeprom ici, mais vous devez avoir compris le
principe des interruptions suffisamment bien pour pouvoir vous en servir en cas de besoin.
Nous allons donc procder la modification de notre routine dinterruption. Nous devons
ajouter un second compteur (cmpt2) en zone RAM. Dclarons donc cette variable.
Oui, je sais, il y avait moyen doptimiser tout a pour nutiliser quun compteur. Ce nest
pas le but de cet exercice. Autant rester clair et centrer notre attention sur le sujet de ce
chapitre.
La modification est trs simple, en ralit. Dans la routine dinterruption timer, nous
incrmenterons le compteur 2 qui sera utilis dans le programme principal.
Sur le 16C84, la fin de lautorisation des interruptions ntait prise en compte quaprs
linstruction suivante. Donc, entre bcf INTCON, GIE et linstruction suivante, une
interruption pouvait avoir lieu.
Il tait donc ncessaire, aprs la mise de 0 de GIE, de vrifier si cette mise 0 stait
effectivement ralise. Dans le cas contraire, cest quune interruption avait eu lieu cet
endroit, et il fallait donc recommencer lopration.
157
Voici le nouvel ordinogramme obtenu.
;**********************************************************************
; INTERRUPTION TIMER 0 *
;**********************************************************************
inttimer
; tester compteur de passages
; --------------------------
decfsz cmpt , f ; dcrmenter compteur de passages
return ; pas 0, on ne fait rien
; inverser LED
; ------------
BANK0 ; par prcaution
movlw b'00000100' ; slectionner bit inverser
xorwf PORTA , f ; inverser LED
Nous allons crire dans leeprom depuis notre programme principal. Il y a deux
raisons ne pas crire dans leeprom depuis notre routine dinterruption timer.
158
- Il faut, dans la mesure du possible, quitter le plus rapidement possible une routine
dinterruption, celles-ci tant en gnral dans un programme, rserves aux traitements
urgents des informations.
- Tout ce qui peut tre facilement plac ailleurs doit ltre. Nous ne pouvons par remettre
les interruptions en service (GIE) depuis une routine dinterruption. Or, notre macro
dcriture eeprom remet GIE 1. Si vous vouliez utiliser cette macro dans une routine
dinterruption, vous devriez au pralable supprimer la remise en service de GIE.
;*********************************************************************
; PROGRAMME PRINCIPAL *
;*********************************************************************
start
; tester si 16 inversions de LED
; ------------------------------
btfss cmpt2 , 5 ; tester si 32 passages
goto start ; non, attendre
clrf cmpt2 ; oui, effacer compteur2
; incrmenter reload
; ------------------------
incf reload , f ; incrmenter reload
incf reload , f ; incrmenter 2 fois c'est plus visible
Compilez le programme et chargez-le dans le PIC. Placez le montage sur votre platine
dessais. Remarquez que la LED clignote une frquence approximative de 1Hz. Au 17me
allumage, la frquence de clignotement diminue lgrement, et ainsi de suite tous les 16
passages.
Le fichier tel quil devrait tre la fin de cette leon est disponible sous la
dnomination eep_test.asm
159
14.11 Scurisation des accs en mmoire eeprom
Lorsque vous crivez dans la zone eeprom dun PIC, vous ne pouvez jamais tre sr
quune coupure de courant ne va pas interrompre la procdure. En consquence, vous devez
vous assurer que les donnes dans leeprom sont bien valides avant de les utiliser au
redmarrage suivant.
- Placez un en-tte dans le premier ou les premiers octets de votre eeprom. Par exemple,
nous placerons 0x55 dans loctet 0.
- Lors de lcriture de nouvelles valeurs dans leeprom, nous commenons par effacer
notre en-tte.
- Lors dun dmarrage du PIC, si len-tte est prsent, cela signifie que les donnes
eeprom sont valides. Dans le cas contraire, le cycle dcriture a t interrompu. A vous
alors de ragir en consquence, par exemple en rinscrivant dans leeprom les valeurs
par dfaut.
- Pour augmenter la scurit du systme pour les donnes critiques, vous pouvez placer
plusieurs octets den-tte.
14.12 Conclusion
Voici encore une nouvelle tape franchie dans votre connaissance du 16F84. Vous pouvez
maintenant utiliser la zone eeprom de votre PIC pour y stocker vos donnes rmanentes.
Nhsitez pas exprimenter, mais noubliez pas de vrifier votre programme pour viter
les critures inutiles et trop frquentes dans votre eeprom.
Pas de panique cependant, si votre programme est correctement crit, vous ntes pas prt
datteindre les 1.000.000 de cycles dcritures garantis.
160
15. Le watchdog
La valeur minimale de 7ms est celle que vous devrez utiliser dans la pratique.
En effet, Microchip vous garanti quaucun PIC ne provoquera un reset avant ces 7ms. Il
vous indique que le temps moyen de reset de ses PICs sera de 18ms, mais il ne vous garantit
pas ce temps, cest juste un temps gnralement constat .
Chaque fois que linstruction clrwdt est envoy au PIC, le timer du watchdog est remis
0, ainsi que la valeur contenue dans son prdiviseur. Si par accident cette instruction nest
pas reue dans le dlai prvu, le PIC est redmarr ladresse 0x00 et le bit TO du registre
STATUS est mis 0.
En lisant ce bit au dmarrage, vous avez donc la possibilit de dtecter si le PIC vient
dtre mis sous tension, ou si ce dmarrage est du un plantage de votre programme.
Nous avons vu dans les leons prcdentes que le prdiviseur pouvait tre affect au tmr0
ou au watchdog, via le bit PSA du registre OPTION. Si nous dcidons de mettre le
prdiviseur sur le watchdog (PSA = 1) , le tableau de la page 16 du datasheet nous donnera les
valeurs du prdiviseur obtenues suivant les bits PS0/PS2.
En ralit, pour le watchdog, il sagit dun postdiviseur, mais cela ne concerne que
llectronique interne du PIC. Vous navez pas vous tracasser pour cette diffrence.
161
Ce postdiviseur multiplie le temps de dbordement du timer du watchdog. Par exemple,
avec un diviseur de 2, vous obtenez un temps minimal de 7ms*2 = 14ms. En sachant que le
reset seffectuera en ralit en gnral aprs une dure de 18ms*2= 36ms.
Donc, avec un quartz de 4MHz, cela vous oblige envoyer linstruction clrwdt au moins
une fois tous les 14.000 cycles dinstructions. Dans la plupart des cas, le reset seffectuera en
ralit aprs 18ms*2 = 36ms, soit 36.000 cycles dinstructions.
Le watchdog est destin vrifier que votre programme ne sest pas gar dans une
zone non valide de votre programme (parasite sur lalimentation par exemple), ou sil nest
pas bloqu dans une boucle sans fin (bug du programme). Il sert galement rveiller un PIC
place en mode sleep , ce que nous verrons plus tard.
La premire chose faire, si vous dsirez profiter de cette protection intgre, est de
paramtrer la _CONFIG pour la mise en service du watchdog. La premire chose constater,
cest que :
Si vous indiquez _WDT_ON pour un programme qui ne gre pas le watchdog, celui-
ci redmarrera sans arrt, et donc ne fonctionnera pas, car il ne contiendra aucune instruction
clrwdt .
Cest une erreur frquente pour ceux qui ne matrisent pas les bits de configuration de
leur programmateur. Les bits de configurations indiqus dans le fichier sont en effet
modifiables par la plupart des logiciels de programmation, qui sont capables de forcer une
valeur de _CONFIG diffrente de celle prvue par le concepteur du programme PIC.
Ceci est dautant plus frquent que certains programmeurs oublient dinclure la directive
_CONFIG dans leur programme, ce qui ne permet pas la configuration automatique des
flags de configuration. Cest une trs mauvaise pratique, car lutilisateur final devra savoir (ou
deviner) quel est ltat des flags quil lui faudra configurer au moment de la programmation.
Ensuite, vous devez placer une ou plusieurs instructions clrwdt dans votre
programme en vous arrangeant pour quune instruction clrwdt soit reue dans les dlais
requis par votre PIC. Pour rappel, ne tenez pas compte du temps nominal de 18ms, mais plutt
du temps de la situation la plus dfavorable. Ce temps est de minimum 7ms. En prenant ce
temps comme temps maximum autoris, vous tes certain que vote programme fonctionnera
dans toutes les conditions.
162
Donc, si vous placez une instruction clrwdt dans une routine dinterruption, cette
instruction risque de sexcuter mme si votre programme est plant. Cest donc le contraire
du but recherch. En consquence :
La valeur de 7ms est la valeur minimale, la valeur de 18ms est la valeur gnralement
constate. Mais quelle est la valeur effective de votre propre PIC ?
Ensuite, supprimez la variable cmpt3 et modifiez la routine tempo pour enlever la boucle
extrieure.
;*********************************************************************
; SOUS-ROUTINE DE TEMPORISATION *
;*********************************************************************
;---------------------------------------------------------------------
; Cette sous-routine introduit un retard de 250ms.
; Elle ne reoit aucun paramtre et n'en retourne aucun
;---------------------------------------------------------------------
tempo
clrf cmpt2 ; effacer compteur2
boucle2
clrf cmpt1 ; effacer compteur1
boucle1
nop ; perdre 1 cycle
decfsz cmpt1 , f ; dcrmenter compteur1
goto boucle1 ; si pas 0, boucler
decfsz cmpt2 , f ; si 0, dcrmenter compteur 2
goto boucle2 ; si cmpt2 pas 0, recommencer boucle1
return ; retour de la sous-routine
Ajoutons la ligne
Juste aprs ltiquette init pour tre bien sr de remettre le watchdog 0 (en ralit, inutile).
163
Modifions pour finir le programme principal pour quil allume la LED aprs 250ms :
;*********************************************************************
; PROGRAMME PRINCIPAL *
;*********************************************************************
start
call tempo ; on attends 250ms
bsf LED ; allumer la LED
loop
goto loop ; on reste ici
END ; directive fin de programme
Recompilez votre programme, et rechargez-le dans votre PIC. Alimentez votre montage.
Explication
Et bien, notre watchdog na pas t remis zro depuis le dmarrage du PIC. Donc,
une fois le temps : dure de base * prdiviseur atteint, un reset est provoqu qui entrane
une extinction de la LED et un redmarrage sans fin du cycle.
Pour connatre la base de temps de notre watchdog personnel dans les circonstances
actuelles de tension et de temprature, nous devons donc diviser le temps entre 2 extinctions
(ou allumage) par le prdiviseur, cest dire 128.
Personnellement, jai chronomtr 2,2 secondes. Donc, mon watchdog travaille avec
un temps de base de : 2200ms / 128 = 17,2 ms. On est donc bien dans les environs des 18ms
typiques annonces. Remarquez que cest moins que les 18ms typiques. Donc, si javais
utilis un clrwdt toutes les 18ms, mon programme aurait plant sur ce PIC. Preuve que cest
bien la valeur de 7ms quil faut prendre en compte.
Effectuez de nouveau une copie de votre fichier Led_cli.asm et renommez cette copie
secur.asm . Crez un nouveau projet.
164
; Rsistance pull-up ON
; Prscaler wdt 128
start
bsf LED ; allumer la LED
call tempo ; appeler la tempo de 0.5s
bcf LED ; teindre LED (LEDOFF)
call tempo ; appeler la tempo de 0.5s
btfsc BOUTON ; tester bouton-poussoir
goto start ; pas press, boucler
plante
goto plante ; le programme n'est pas sens
; arriver ici
; simulation de plantage
END ; directive fin de programme
165
start
bsf LED ; allumer la LED
clrwdt ; effacer watchdog
call tempo ; appeler la tempo de 0.5s
bcfLED ; teindre LED (LEDOFF)
clrwdt ; effacer watchdog
call tempo ; appeler la tempo de 0.5s
btfsc BOUTON ; tester bouton-poussoir
goto start ; pas press, boucler
plante
goto plante ; le programme n'est pas sens
; arriver ici
; simulation de plantage
END ; directive fin de programme
Nous avions programm notre watchdog avec un prdiviseur de 128, ce qui nous
impose denvoyer une commande clrwdt toutes les 7*128 ms, soit toutes les 896ms.
Comme lappel notre tempo prend 500ms, nous devrons donc envoyer clrwdt avant ou
aprs chaque appel de tempo, pour ne pas dpasser ce temps.
Nous aurions pu, au lieu de ces 2 instructions, utiliser un seul clrwdt dans la sous-
routine tempo .
Vous naurez cependant pas toujours le choix. Si votre prdiviseur est dj occup
pour le timer0, par exemple, il ne vous restera pas dautres choix que denvoyer une
commande clrwdt toutes les 7ms.
Dans le cas prsent, vous auriez du placer une instruction de ce type au cur de la
routine de temporisation, car celle-ci dure plus de 7ms.
Rappelez-vous de ne pas utiliser cette instruction dans une routine dinterruption, car
cela est contraire au principe mme du watchdog (sauf cas trs spciaux). Vous pouvez
par contre utiliser clrwdt dans une sous-routine sans aucun problme.
166
15.9 Temps typique, minimal, et maximum
- Le temps typique (18ms) est le temps que met EN GENERAL le watchdog pour
provoquer le reset de votre programme en cas de plantage. Cest donc le temps de
raction normal (ou typique) du watchdog
- Le temps minimal (7ms), cest le dlai maximum dont vous disposez entre 2
instructions clrwdt pour viter un reset de votre programme non dsir.
- Le temps maximum (33ms), cest le temps de raction du watchdog dans le cas le plus
dfavorable en fonction du composant et des conditions dutilisation. Microchip vous
garantit ici que le reset seffectuera au maximum en 33 ms.
15.10 Conclusion
Vous tes maintenant en mesure de crer des programmes rsistants aux plantages
classiques, pour peu que vous utilisiez judicieusement le watchdog. En gnral, il est
prfrable de faire leffort de lutiliser, car le surplus de travail est ngligeable en contrepartie
de la scurit de fonctionnement obtenue.
- Vous crivez votre programme en y plaant comme prvu les instructions clrwdt, mais
VOUS NE METTEZ PAS LE WATCH-DOG EN SERVICE avec la directive
_CONFIG
- Vous mettez votre programme en PIC, et vous le debuggez en le laissant tourner
suffisamment de temps pour tre certain de labsence de bug.
- Une fois le programme fiabilis, vous reprogrammez votre PIC avec le watchdog en
service.
De cette faon, vous tes certain que votre watchdog ne va pas servir rcuprer une
erreur de programmation de votre part (en relanant le pic lors dun blocage dans une boucle
sans fin, par exemple).
167
Notes :
168
16. Le mode Sleep
Nous allons tudier dans cette leon un mode trs particulier des PICs, qui leur permet
de se mettre en sommeil afin de limiter leur consommation.
Le mode sleep ou power down est un mode particulier dans lequel vous pouvez
placer votre PIC grce linstruction sleep . Une fois dans ce mode, le PIC est plac en
sommeil et cesse dexcuter son programme. Ds rception de cette instruction, la squence
suivante est excute :
Une fois dans cet tat, le PIC est larrt. La consommation du circuit est rduite au
minimum. Si le tmr0 est synchronis lhorloge interne, il est galement mis dans
lincapacit de compter.
Par contre, il est trs important de se rappeler que le timer du watchdog possde son
propre circuit dhorloge. Ce dernier continue de compter comme si de rien ntait.
Le passage en mode sleep na rellement dintrt que sil est possible den sortir. Le
16F84 ne ragit dans ce mode quaux vnements suivants, qui sont seuls susceptibles de
replacer le 16F84 en mode de fonctionnement normal. Ces vnements sont les suivants :
- Application dun niveau 0 sur la pin MCLR. Ceci provoquera un reset du 16F84. Le
PIC effectuera un reset classique ladresse 0x00. Lutilisateur pourra tester les bits
TO et PD lors du dmarrage pour vrifier lvnement concern (reset, watch-dog, ou
mise sous tension).
- Ecoulement du temps du timer du watchdog. Notez que pour que cet vnement
rveille le PIC, il faut que le watchdog ait t mis en service dans les bits de
configuration.
169
Dans ce cas particulier, le dbordement du watchdog ne provoque pas un reset du PIC,
il se contente de le rveiller. Linstruction qui suit est alors excute au rveil.
Notez dans ce dernier cas, que pour quune telle interruption puisse rveiller le
processeur, il faut que les bits de mise en service de linterruption aient t positionns. Par
contre le bit GIE na pas besoin dtre mis en service pour gnrer le rveil du PIC.
Vous pouvez donc dcider par exemple de rveiller le PIC la fin du cycle dcriture
EEPROM. Pour ce faire, vous devez mettre le bit EEIE de INTCON 1 et lancer le cycle
dcriture, suivi par linstruction sleep Une fois lcriture termine, le PIC est rveill et
poursuit son programme.
Si votre PIC est rveill par une interruption alors que le BIT GIE de INTCON est mis
0, le programme se poursuivra tout simplement linstruction qui suit linstruction sleep .
Dans le cas o votre bit GIE est positionn, un rveil suite une interruption entranera la
squence suivante.
Notez que si vous ne voulez pas excuter linstruction qui suit linstruction sleep , il
vous suffit de placer cet endroit une instruction nop .
Si le bit GIE est positionn 0, et que les bits de mise en service et le flag dune
interruption sont tous deux 1 au moment de linstruction sleep (par exemple
INTE=INTF =1), linstruction sleep est tout simplement ignore par le processeur.
Ceci est logique, car les conditions de rveil sont dj prsentes avant la mise en sommeil.
Cest donc vous de remettre ventuellement ces bits 0. Le bit PD vous permettra de savoir
si votre instruction sleep sest excute (PD = 0).
Si le bit GIE est positionn 1, il va sans dire, mais je lcris tout de mme, que le cas
prcdent ne pourra survenir, vu quune interruption serait alors gnre, interruption qui
provoquerait leffacement du flag de INTE ou INTF. Except bien entendu si vous avez plac
votre instruction sleep lintrieur de la routine dinterruption.
170
Notez galement que dans le cas o linstruction sleep nest pas excute, votre
watchdog nest pas non plus remis 0. Si vous deviez le faire ce moment, et si vous ntes
pas sr de la bonne excution de sleep , ajoutez linstruction clrwdt avant cette
instruction.
Nous allons raliser un petit exercice sur la mise en veille de notre PIC.
Placez le prdiviseur sur le watchdog avec une valeur de 32. Ceci nous donne une
valeur typique de dbordement de 18ms*32 = 576 ms.
Placez ensuite votre LED en sortie dans la routine dinitialisation (attention, en banque1)
;*********************************************************************
; PROGRAMME PRINCIPAL *
;*********************************************************************
start
bsf LED ; Allumage de la LED
sleep ; mise en sommeil
bcf LED ; extinction de la LED
sleep ; mise en sommeil
goto start ; boucler
Le fonctionnement est trs simple. Aprs avoir allum ou teint la LED, le PIC est mis en
sommeil. Une fois le temps du watchgog coul, le PIC se rveille et excute linstruction
suivante. Voil donc un programme de clignotement de votre LED ultracourt et avec une
consommation minimale.
De plus, voici une autre faon simple de mesurer le temps de watchdog de votre
propre PIC.
Remarque
Notez que le temps de rveil de votre pic nest pas instantan. En effet, si vous utilisez
un quartz, le pic attendra 1024 cycles dhorloge avant de relancer le programme. Il vous
faudra en tenir compte.
171
Ce temps mort est ncessaire pour que loscillateur de prcision quartz atteigne
une certaine stabilit.
Attention donc, soyez conscients que le rveil de votre pic prendra un certain temps.
Une autre application typique est un programme dans lequel le PIC na rien faire dans
lattente dun vnement extrieur particulier. Dans ce cas, plutt que dutiliser des boucles
sans fin, une instruction sleep pourra faire efficacement laffaire.
Le mode sleep assure une mise en veille du PIC. Son rle premier tant lconomie
dnergie, il incombe de baisser la consommation globale du composant. Pour ce faire, il ne
suffit pas de placer le pic en mode sleep, il faut encore veiller tout son environnement.
Tout dabord, il faut savoir que le passage en mode sleep ne modifie pas ltat des pins
configures en sortie. Si au moment de passer en mode sleep votre pic allumait une led, alors
elle restera allume (et consommera du courant). Autrement dit, placez, avant de passer en
sleep, toutes les pins configures en sortie, soit 1, soit 0, de faon ce quaucune ne
provoque une consommation de courant.
Toutes les entres non utilises ainsi que lentre Tocki devront tre forces soit la
masse, soit Vdd, car si vous les laissez flottantes, chaque transition accidentelle de niveau
consommera un petit courant. Notez que vous arrivez au mme rsultat en configurant les pins
inutilises comme sorties.
16.8 Conclusion
172
17. Le reste du datasheet
Et voil, nous arrivons au bout de ltude de notre 16F84. Dans ce chapitre, je vais
parcourir avec vous le datasheet du 16F84 pour voir tout ce dont nous navons pas parl
jusqu prsent.
Cest donc une sorte de fourre-tout que je vous propose ici. Je nentrerai cependant pas
dans les descriptions techniques dtailles, car ceci nintressera que les lectroniciens. Ceux-
ci tant parfaitement aptes comprendre une figure telle que la figure 3-1. Pour les autres,
ceci napportera rien de plus lutilisation des PICs.
Comme les datasheet sont sans cesse mis jour chez Microchip, je joins la leon
celui qui ma servi jusqu prsent pour faire ces cours, et qui sappelle 16F84.pdf
Figure 3-1, justement, vous voyez comment est construit un 16F84. Comme je le disais
plus haut, ceci ne prsente quun intrt limit pour lutilisation pratique du processeur.
Cependant, vous pouvez remarquer les largeurs de bus internes qui vous rappellent les
limitations des modes dadressage. Vous voyez par exemple que le PC (Program Counter) na
quune largeur de 13 bits.
Le cur du 16F84, comme dans tout processeur, est lALU. Cest dans cette Unit
Arithmtique et Logique que seffectuent tous les calculs. Notez la liaison entre le registre W
et lunit ALU.
Figure 3-2, vous voyez clairement la division dun cycle dhorloge en 4. Chacun des 4
clocks ncessaires la ralisation dune instruction est dtaille. Vous voyez lexemple 3-1
qui montre lexcution dun bout de programme.
Notez que durant quune instruction est excute, la suivante est dj charge ( fetch ).
Ceci explique que lors dun saut, linstruction suivante charge ntant pas celle qui doit tre
excute, il faut alors un cycle supplmentaire pour charger la bonne instruction.
Sur la figure 4-1 vous voyez lorganisation mmoire du PIC. Notez que la pile et le PC
sont situs hors de lespace dadressage, et donc sont inaccessibles par le programme.
173
17.4 Les registres spciaux
Le tableau 4-1 vous donne une vue globale de tous les registres spciaux. La premire
colonne vous donne ladresse du registre , la seconde le nom symbolique du registre, ensuite
le nom de chaque bit.
Lavant-dernire colonne vous donne la valeur de chaque bit aprs une mise sous tension,
tandis que la dernire colonne fait de mme pour les autres types de reset (watchdog et
MCLR). Les bits nots 0 ou 1 sont ceux dont le niveau est celui indiqu. Les bits nots u
sont les bits non affects par un reset (unchanged = inchang). Les bits nots x sont les
bits dont ltat ne peut tre connu ce moment.
Les figures 5-1 5-4 permettront aux lectroniciens de comprendre les spcificits des
ports IO au niveau de leurs caractristiques lectriques. Vous verrez alors, comme je vous lai
indiqu, que la pin RA4, par exemple, est une sortie collecteur ouvert , ou plus
prcisment drain ouvert , configuration qui ne permet pas dimposer un niveau haut sur
la sortie.
Lexplication et la position de ces 14 bits sont donns figure 8-1. Noubliez pas quil
sagit ici dun mot de 14 bits (tout comme les instructions).
ORG 0x2007
DA B111111111111110
174
17.7 Les diffrents types doscillateurs
La figure 8-3 nous montre la configuration que nous avons utilise pour lhorloge de notre
PIC. Cest lutilisation avec quartz externe. La rsistance RS est inutile pour un quartz
classique. Si vous utilisez un rsonateur cramique avec condensateurs intgrs, au lieu dun
quartz, vous pourrez supprimer les condensateurs C1 et C2.
La table 8-1 montre les diffrentes valeurs utiliser en fonction des frquences, ainsi que
les modes correspondants slectionns par les bits de configuration FOSC1 et FOSC0 si vous
utilisez un rsonateur cramique.
La figure 8-4 indique comment utiliser une horloge externe au lieu de loscillateur interne.
Rappelez-vous dans ce cas de ne jamais paramtrer votre _CONFIG sur RC sous peine de
destruction de votre PIC.
Les figures 8-5 et 8-6 vous montrent comment construire un oscillateur externe. Je vous
conseille titre personnel dutiliser dans ce cas le 74HCU04 qui fonctionne bien pour des
frquences suprieures ou gales 4MHz.
Jutilise pour ma part dans ce cas un schma driv du montage parallle indiqu. Mon
montage, sur 4MHz, utilise une R de 3,3Mohms la place des 47Kohms, je remplace la R
ajustable par une fixe de 2Kohms, et je supprime la R ajustable lextrme gauche du
schma. Je remplace les deux condensateurs par des 27pF.
Nutilisez ce mode que si vos constantes de temps dans votre programme ne sont pas
critiques. Connectez suivant la figure 8-7 et utilisez une Rsistance de lordre de 47Kohms et
un condensateur de lordre de 27 picofarads (27pF).
Noubliez pas dans tous les cas que la vitesses dexcution dune instruction est le quart
de la vitesse dhorloge. Utilisez la formule suivante pour calculer le temps dun cycle de votre
programme. Soit F la frquence de lhorloge fournie et T le temps dun cycle :
T = 4 / F.
175
Donc, si je veux un temps de cycle de 1,5 s (microseconde), il me faudra une horloge
cadence :
Noubliez pas dans vos calculs de tenir compte de lerreur toujours existante. La tolrance
de votre horloge est directement tributaire de la mthode utilise. Une horloge quartz
donnera une bien meilleure prcision quun simple rseau RC.
A titre dexemple, supposons que vous dsiriez construire une horloge avec une carte
PIC. Nous allons valuer lordre de grandeur des erreurs obtenues en fonction du type
doscillateur retenu.
Nous supposerons que votre logiciel est correctement ralis, et que lerreur de mesure
de temps, ce niveau, est nulle.
Si vous choisissez ce mode pour une horloge, alors vous avez vraiment fait le mauvais
choix. En effet, la frquence de loscillateur varie alors en fonction de la temprature, de la
prcision des composants, varie dans le temps, et en plus est diffrente dun composant
lautre. Ne vous tonnez pas, alors, si vous obtenez une erreur de 12 heures toutes les 24
heures. A rejeter.
Si maintenant vous avez dcid dutiliser un rsonateur cramique, la table 12-1 vous
donne les prcisions obtenues en fonction de quelques marques et modles tests par
Microchip. Ces valeurs nous donnent une prcision de lordre de 0.5%.
Sachant que dans une journe, il y a 24 heures, et que chaque heure contient 3600
secondes, nous pouvons dire quune journe compte : 24 * 3600s = 86400 s.
Une erreur de 0.5% nous donne donc une erreur estime de 86400 * 5 * 10-3 = 432
secondes. Votre horloge risque donc de driver de plus de 6 minutes par jour.
Passons au quartz. Celui-ci va nous donner une erreur typique, et comme indiqu sur le
tableau 12-2, de lordre de 50 PPM (Part Par Million), soit 0,000005%. Calculons donc la
drive de notre horloge :
Ce petit apart avait pour but de vous faire sentir par un exemple concret lordre de
grandeur des prcisions pouvant tre obtenues par des mthodes courantes.
176
Notez, que pour notre exemple dhorloge, nous pouvions obtenir des prcisions encore
plus grandes. Nous pouvions par exemple utiliser un circuit dhorloge externe spcifiquement
conu pour de telles applications, ou encore compter les sinusodes du rseau.
En effet, cette dernire mthode est trs fiable, car les socits de production dlectricit
corrigent la frquence en permanence, avec obligation de respecter un nombre exact de cycles
au bout de 24 heures (50Hz = 50 cycles par seconde).
17.8 Le reset
Figure 8-8 vous avez le schma du circuit de reset interne. Ne vous inquitez pas, tout le
travail a t fait pour vous. Retenez ceci : pour faire fonctionner le PIC normalement, reliez la
pin MCLR au +5V. La mise la masse de cette broche provoque un reset du PIC.
SI vous voulez par exemple un bouton reset sur votre montage, reliez la pin MCLR au +5
via une rsistance de 10Kohms. Placez votre bouton reset entre la pin MCLR et la masse,
comme dans ce petit schma.
Le tableau 8-3 vous montre tous les vnements lis au reset, et leurs effets sur le PC (o
le programme se branchera) et le registre STATUS. Je vous traduis le tableau ci-dessous.
177
Le tableau 8-4 est trs intressant, car il vous montre le contenu de chaque registre
aprs un reset et aprs un rveil. Rappelez-vous que les valeurs x renseignent un tat
inconnu, u signifie inchang par rapport la valeur prcdente, et q signifie que ltat
dpend de la cause de lvnement (voir tableau ci-dessus).
Ds que vous placez votre PIC sous tension, un circuit interne analyse la tension
dalimentation. Un reset automatique est gnr ds que cette tension monte dans la zone 1,2
1,7 volts. Ceci est le reset de mise sous tension (Power On Reset). Notez dj que ce circuit
ne provoque pas un reset si la tension baisse. Cest vous de grer ce cas particulier sil vous
pose problme.
Notez par contre que dautres PICs grent ce problme, comme le 16F876. Je laborderai
donc dans la seconde partie.
Ensuite, aprs coulement du temps prcdent, nous avons un temps supplmentaire sous
forme dun comptage de 1024 oscillations de lhorloge principale (Oscillator Start-up Timer).
Ceci permet de sassurer dun fonctionnement stable de cette horloge. Cet OST nest pas
utilis pour le mode doscillateur RC, et est en service pour les mises sous tension et les
rveils (pas pour les autres formes de reset, pour lequel loscillateur est sens tre dj dans
un tat stable).
La figure 8-10 vous montre le chronogramme typique dune mise sous tension. Jexplique
rapidement. Sachez que le dplacement horizontal de gauche droite reprsente le temps.
La ligne 1 montre larrive de lalimentation (VDD). Une fois cette alimentation arrive
1,2/1,7V, le processus de mise sous tension est amorc.
La seconde ligne vous montre que le dmarrage du processus ne dpend pas du niveau de
la ligne MCLR. Dans cet exemple, cette ligne passe ltat haut un peu plus tard. Si vous
lavez relie au +5V, elle passera 1 en mme temps que la ligne VDD sans aucune sorte
dinfluence.
Ensuite, vous voyez que le reset interne (POR) est valid ds que lalimentation est passe
au point prcit. Scoule ensuite ventuellement le temps de 72ms du PWRT sil est mis en
service.
A la fin de ce temps, lOST dmarre ses 1024 cycles dhorloge pour les modes concerns.
La procdure est alors termine.
178
Si ce moment MCLR est 1, le PIC dmarre directement (tableau 8-10). Si MCLR est
toujours 0, le Pic dmarrera instantanment ds le passage de MCLR 1 (tableau 8-11).
Le tableau 8-13 vous montre ce qui se passerait si lalimentation montait trop lentement
en tension, alors que MCLR est reli lalimentation.
Dans ce cas, le reset interne serait termin avant ltablissement de la tension normale, ce
qui nest pas conseill. Dans ce cas, utilisez le schma de la figure 8-9 pour ralentir la monte
en tension sur MCLR et allonger le temps du reset.
Les figures 8-14 et 8-15 vous donnent les mthodes de protection utiliser en cas de
baisse de la tension sans arrt complet.
A partir du chapitre 11, vous trouvez toutes les spcifications lectriques de votre
composant. Ceci intresse les lectroniciens concepteurs de montages particuliers. Pour un
usage courant, les explications des leons prcdentes suffisent largement. Pour des
applications pointues au niveau des spcificits lectriques, il vous faudra tudier ces tableaux
plus en dtail. Je pense donc inutile de dtailler ces caractristiques dtailles.
Voil un point crucial. Que deviendra votre programme si vous changez de modle de
PIC ? Voici ce que vous devez faire pour assurer la portabilit de votre programme
- Vous devez utiliser les fichiers .inc de Microchip correspondant au PIC sur lequel
va tourner votre programme. Par exemple P16f84.inc .
- Vous devez lire les nouveaux datasheets pour analyser les diffrences entre le
composant initial et le nouveau. Au besoin effectuez des modifications dans votre
source.
- Vous pouvez ensuite recompiler votre programme, aprs avoir remplac la ligne
include par celle contenant le nouveau fichier include
Notez donc que votre programme sera dautant plus facilement portable que vous aurez
suivi les consignes donnes dans ce cours, que vous aurez utilis au maximum les
dclarations, define et macros, et que vous aurez comment votre programme.
Notez galement que si vous avez compris ce qui prcde, UN FICHIER .HEX CONCU
POUR UN COMPOSANT NE PEUT JAMAIS ETRE UTILISE TEL QUEL POUR UN
AUTRE COMPOSANT, sauf cas trs rares.
179
Nesprez donc pas placer tel quel votre fichier 16F84 dans un 16F876. Dans la seconde
partie du cours, jexpliquerai comme procder pour effectuer la migration de votre
programme.
La premire ligne montre que PWRTE a chang de niveau. En effet, PWRTE 1 mettait
en service le timer sur reset de 72ms pour le 16C84. Pour le 16F84, il faut mettre ce bit 0.
Notez dj que si vous avez utilis la directive _CONFIG, il vous suffira de recompiler
votre programme, car le nouveau fichier p16F84.inc intgre automatiquement la
modification. Si par contre vous avez voulu utiliser une criture directe en 0x2007, en dpit
des avertissements de ces leons, il vous faudra modifier votre programme.
Ensuite vous voyez que la capacit en RAM utilisateur (variables) est passe de 36 octets
68 octets.
Puis vous constatez que Microchip a ajout un filtre sur la pin MCLR afin dviter que des
parasites ne provoquent un reset inopinment. Ceci allonge cependant la longueur de
limpulsion ncessaire pour provoquer un reset souhait.
Vous voyez galement que la mise 0 des bits 7 et 6 de EEADR ne provoque plus une
modification du courant consomm par le PIC. Cest une correction de bug. En effet, sur le
16C84, le fait de laisser ces pins ltat haut augmentait le courant consomm. Je vous en ai
dj parl.
Notez ensuite que le fameux CP (code protect) qui contenait un seul bit sur le 16C84,
passe maintenant 9 bits. Ceci permet de crer diffrents types de code protect diffrents sur
les autres PICs de la famille (protection data, protection eeprom etc.).
Une fois de plus, si vous aviez utilis les directives _CONFIG, il vous suffit de
recompiler votre programme aprs avoir simplement remplac le type de composant dans la
directive include . Pour les autres, il vous faudra relire le datasheet en entier pour chaque
nouvelle version du mme composant, et de modifier le programme en consquence.
180
Constatez enfin la correction dun bug interne lorsque vous placiez le bit GIE 0.
Dsormais, une interruption ne pourra plus tre gnre au cycle suivant. La boucle loop
qui tait ncessaire pour vrifier la bonne mise hors service des interruptions nest plus
ncessaire sur le 16F84. Cette boucle tait de la forme :
loop
bcfINTCON , GIE ; Arrter les interruptions
btfsc INTCON , GIE ; Tester si une interruption na pas remis GIE
1
goto loop ; si, alors on recommence
17.13 Conclusion
Je vous ai souvent volontairement fait faire des erreurs, que jai corriges par la suite. Jai
fait cette dmarche dans le but de vous faciliter la vie, en vous montrant ce qui taient parfois
de fausses vidences, et en vous expliquant la bonne dmarche pour obtenir un rsultat fiable.
Je ne vous laisse pas encore tomber, car je vais vous expliquer quelques astuces bien
pratiques pour les programmes les plus courants. Mais dj maintenant, vous tes capables de
travailler seul.
181
Notes :
182
18. Astuces de programmation
Dans ce chapitre, nous allons examiner quelques mthodes simples pour se tirer de
situations classiques.
Quoi de plus simple que deffectuer une comparaison entre 2 nombres. Il suffit deffectuer
une soustraction. Soit par exemple comparer mem1 avec mem2 :
Il vous suffit ensuite de tester les bits C et Z du registre STATUS pour connatre le rsultat :
Si vous dsirez simplement comparer lidentit entre 2 valeurs, sans modifier C, vous
pouvez galement utiliser linstruction xor
Supposons que vous avez une valeur dans W et que vous dsirez soustraire 5 de cette
valeur. Le premier rflexe est le suivant :
sublw 5
Cest une erreur classique, car vous avez en ralit effectu (5-w) au lieu de (w-5). Il vous
faudra donc effectuer le complment 2 de cette valeur pour obtenir le bon rsultat. Effectuez
plutt ceci :
addlw -5
Et oui, ajouter 5 correspond soustraire 5. Faites-le par crit si vous ntes pas
convaincu. Par contre, la gestion du bit C ncessitera un peu plus de gymnastique, je vous
laisse y rflchir.
183
18.3 Les multiplications
Comment effectuer une multiplication ? Et bien tout simplement de la mme manire que
nous leffectuons manuellement.
Nous allons crer une routine qui multiplie ensemble 2 nombres de 8 bits. Le rsultat
ncessitera donc 16 bits, donc 2 octets. En effet, pour obtenir le nombre de digits maximal du
rsultat dune multiplication, il suffit dadditionner le nombre de digits des diffrentes
oprandes.
Ralisons donc une multiplication manuelle. Nous allons multiplier 12 par 13. Nous
allons travailler avec 4 bits multiplis par 4 bits, avec rsultat sur 8 bits. Ceci afin de rduire
notre explication. Excutons donc notre multiplication manuellement.
1 1 0 0 12
X 1 1 0 1 13
1 1 0 0 12
0 0 0 0 0 0
1 1 0 0 0 0 48
1 1 0 0 0 0 0 96
1 0 0 1 1 1 0 0 156
184
Vous pouvez tenter dcrire ce programme. Ceci reste pratique pour des multiplications de
4 par 4 bits. Pour des multiplications de 8 bits par 8 bits, vous allez devoir raliser des tas
dadditions de nombres de 16 bits avec des nombres de 16 bits. De plus vous devrez dcaler le
multiplicateur, ce qui impliquera, soit de le modifier (ce qui nest peut-tre pas toujours
souhaitable), soit de le sauvegarder, ce qui consomme 1 octet supplmentaire.
En rflchissant un peu, on peut se dire que plutt que de dcaler le multiplicateur vers la
gauche, nous pouvons dcaler le rsultat vers la droite. Ceci revient au mme, mais vous
navez plus que des additions de 8 bits, toujours dans le poids fort du rsultat
Voici comment cela fonctionne avec notre exemple, pour ne pas faire trop long :
- On multiplie 1100 par 1. On place le rsultat fond gauche du rsultat. Dans rsultat on
a : 11000000
- On dcale le rsultat vers la droite : rsultat = 01100000
- On multiplie 1100 par 0 . On ajoute au rsultat : rsultat = 01100000
- On dcale le rsultat vers la droite : rsultat = 00110000
- On multiplie 1100 par 1. On ajoute au rsultat gauche : rsultat :11000000 + 00110000
= 11110000
- On dcale le rsultat vers la droite : rsultat = 01111000
- On multiplie 1100 par 1. On ajoute au rsultat gauche : rsultat : 11000000 + 01111000
= 100111000 (9 bits). Le bit8 (en vert) est dans le carry.
- On dcale le rsultat vers la droite : rsultat = 10011100 = D156
Notez quon ajoute toujours au quartet de poids fort (centrage gauche). Dans le cas
dune multiplication de 8 bits par 8 bits, on ajoutera donc loctet de poids fort. Par moment,
nous aurons dbordement de laddition sur 9 bits. Souvenez-vous que le report se trouve dans
le carry. Or, dans un dcalage, le carry est amen dans le rsultat, donc on rcupre
automatiquement notre 9me bit, qui deviendra le 8me aprs dcalage vers la droite.
Cette procdure est trs simple mettre en programme : la preuve, voici le pseudo-
code pour une multiplication 8 bits par 8 bits.
Effacer le rsultat
Pour chacun des 8 bits du multiplicateur
Si bit de droite du multiplicateur = 1
Ajouter multiplicande au poids fort du rsultat
Dcaler 16 bits du rsultat vers la droite
Dcaler multiplicateur vers la droite
Bit suivant
Si nous plaons de plus le dcalage du multiplicateur en-tte, avant le test de bit, nous
rcuprons le bit tester dans le carry. Le programme devient :
Effacer le rsultat
Pour chacun des 8 bits du multiplicateur
Dcaler multiplicateur vers la droite
Si carry = 1
Ajouter multiplicande au poids fort du rsultat
Dcaler 16 bits du rsultat vers la droite
185
Bit suivant
Remarquez que ceci est trs simple. Nous allons mettre ce pseudo-code sous forme de
programme. Nous utiliserons la variable multi comme multiplicateur, multan comme
multiplicande, resulH comme rsultat poids fort et resulL comme poids faible. multemp est le
multiplicateur temporaire qui sera modifi. cmpt est le compteur de boucles Voici donc le
programme :
Vous pouvez crer un petit projet et tester ce programme dans le simulateur. Vous
verrez quil fonctionne parfaitement. Vous pouvez en faire une sous-routine ou une macro
ajouter dans votre propre fichier include.
Les 2 lignes en gris effectuent un dcalage du rsultat sur 16 bits. Le bit perdu dans
resulH est rcupr dans le carry et remis comme bit7 dans resulL. Astuce de
programmation : si laddition prcdente eu lieu (ligne bleue), le 9me bit rsultant de
laddition est dans le carry, et se retrouve donc comme b7 dans resulH. Par contre, sil ny a
pas eu laddition, le carry est forcment 0 du fait du test (en jaune). Vous voyez maintenant
lintrt davoir test le bit faible du multiplicateur en se servant du carry.
Dans le cas prcdent, nous avons effectuer une multiplication entre 2 variables qui
peuvent prendre nimporte quelle valeur. Dans le cas o vous utilisez une constante, cest
dire que vous connaissez le multiplicateur au moment de la conception de votre programme,
vous devez essayer, pour des raisons doptimisation de raisonner en multiplications par 2.
En effet, pour effectuer une multiplication par 2 il suffit de dcaler la valeur vers la
gauche. Cest trs rapide mettre en uvre. Ne pas oublier cependant de mette C 0 avant le
dcalage, pour ne pas entrer un bit non dsir dans le mot dcal.
Supposons donc que vous deviez, dans votre programme, effectuer des multiplications par
10 (dcimal). Et bien nous allons essayer de ramener ceci en multiplications par 2. Cest tout
simple :
186
Pour multiplier par 10, il faut :
Voici donc une multiplication par 10 trs rapide. On a fait *2, *2, +1, *2). Donc 3 dcalages
et une simple addition.
En gnral, on peut sarranger pour obtenir les rsultats des multiplications par des
constantes en utilisant cette mthode.
Voici un petit programme qui multiplie un nombre de 4 bits contenu dans mem1 par
10. Rsultat dans resul. Vous pouvez adapter pour un nombre de 8 bits trs facilement :
Voici encore une astuce. Imaginez que vous deviez copier 15 variables dun emplacement
mmoire vers un autre (ou encore comparer 2 zones mmoires diffrentes etc.). En fait vous
allez rapidement vous heurter un problme. Vous ne disposez que dun seul pointeur FSR
pour pointer sur vos variables.
Ralisons donc ce programme : mem1 est ladresse de dpart de la premire zone, mem2
ladresse de dpart de la seconde zone
187
Ce programme est valable lorsque vous navez pas le choix des zones de dpart et de
destination. Maintenant, qui vous empche de placer vos variables dans des endroits qui vous
arrangent ? Plaons mem1 et mem2 dans la zone de variables :
Il ny a donc que le bit 5 de FSR qui change entre source et destination. Pour modifier des
bits, pas besoin de laccumulateur, donc pas besoin de sauver et recharger la valeur
transfrer.
Avec les PICs qui utilisent plusieurs banques, comme le 16F876, vous pouvez
galement utiliser la mme adresse dans 2 banques diffrentes, et passer dune lautre en
modifiant le bit IRP du registre STATUS.
.
Supposons que nous avons besoin dun tableau de taille importante. Par exemple un
tableau de 200 lments. O placer ce tableau ? Dans la RAM il ny a pas assez de place,
dans leeprom non plus. Ne reste donc plus que la mmoire de programme.
188
Supposons un cas simple : nous voulons crer un tableau contenant le carr des nombres
de 0 15. Nous pourrions utiliser un petit sous-programme de la forme suivante :
Vous voyez tout de suite quil faudra plusieurs instructions par valeur du tableau. En cas
dun tableau de 200 lments, on naura pas assez de mmoire programme pour tout crire.
Nous allons donc utiliser une autre astuce.
Le cur de lastuce est dutiliser linstruction retlw qui permet de retourner une valeur
passe en argument. Ecrivons donc notre tableau sous forme de retlw : cela donne :
retlw 0 ; carr de 0 = 0
retlw 1 ; carr de 1 = 1
retlw 4 ; carr de 2 = 4
retlw 9 ; carr de 3 = 9
retlw 16 ; carr de 4 = 16
retlw 25 ; carr de 5 = 25
retlw 36 ; carr de 6 = 36
retlw 49 ; carr de 7 = 49
retlw 64 ; carr de 8 = 64
retlw 81 ; carr de 9 = 81
retlw 100 ; carr de 10 = 100
retlw 121 ; carr de 11 = 121
retlw 144 ; carr de 12 = 144
retlw 169 ; carr de 13 = 169
retlw 196 ; carr de 14 = 196
retlw 225 ; carr de 15 = 225
Il ne nous reste plus qu trouver une astuce pour nous brancher sur la bonne ligne de
notre tableau/programme. Si nous nous souvenons que nous pouvons effectuer des oprations
sur le PCL, nous pouvons utiliser cette proprit.
Supposons donc que le nombre lever au carr soit contenu dans le registre w. Si, une
fois sur la premire ligne du tableau, nous ajoutons w PCL, nous sauterons directement sur
la bonne ligne. Compltons donc notre sous-routine. Il nous suffit donc dajouter avant notre
tableau la ligne :
carre
addwf PCL , f ; ajouter w PCL
189
A ce stade, vous devez vous rappeler que ladresse pour une opration sur le registre PCL
est complte par le contenu de PCLATH. Vous devez donc initialiser correctement celui-ci
avec le numro de la page de 8 bits de ladresse de votre tableau.
Par exemple, si votre tableau est ladresse 0x200, vous devrez mettre 0x02 dans
PCLATH.
De plus, lopration sur PCL ne modifiera pas automatiquement PCLATH, donc votre
tableau ne devra pas dpasser 256 lments, et, de plus, ne devra pas dborder sur la page de
8 bits suivante. Une page tant la plage adresse par les 256 valeurs possibles de PCL, sans
toucher PCLATH.
Comment viter ceci ? Tout simplement en imposant au tableau une adresse de dpart
telle que le tableau tienne tout entier dans la mme page de 256 emplacements.
Ceci permet alors dutiliser un tableau de 256 lments. Voici donc les emplacements
disponibles pour un tableau dune telle taille :
Adresse B00000 00000000, soit adresse 0x00. Pas utilisable, car adresse de reset
Adresse B00001 00000000, soit adresse 0x100. Premier emplacement utilisable
Adresse B00010 00000000, soit adresse 0x200. Second emplacement utilisable
Adresse B00011 00000000, soit adresse 0x300. Dernier emplacement utilisable.
Il va de soi que si vous avez besoin dun plus petit tableau, vous pouvez le commencer
ailleurs, en veillant bien ne pas occasionner de dbordement. Vous pouvez donc ajouter la
ligne : org 0x300 avant ltiquette de dbut de sous-routine.
Notez que ce que jexplique ici est valable pour les tableaux dont la fin est dans la mme
page que le dbut. Or, comme la ligne addwf est incluse dans la page, il faut soustraire
cette ligne des 256 emplacements disponibles. Nous obtenons donc :
;*********************************************************************
; TABLEAU DES CARRES *
;*********************************************************************
;---------------------------------------------------------------------
; N'oubliez pas que la directive "END" doit se
; trouver aprs la dernire ligne de votre programme. Ne laissez donc
; pas cette directive dans le programme principal.
;---------------------------------------------------------------------
org 0x300 ; adresse du tableau
carre
addwf PCL , f ; ajouter w PCL
retlw .0 ; carr de 0 = 0
retlw .1 ; carr de 1 = 1
retlw .4 ; carr de 2 = 4
retlw .9 ; carr de 3 = 9
retlw .16 ; carr de 4 = 16
retlw .25 ; carr de 5 = 25
retlw .36 ; carr de 6 = 36
retlw .49 ; carr de 7 = 49
retlw .64 ; carr de 8 = 64
retlw .81 ; carr de 9 = 81
retlw .100 ; carr de 10 = 100
retlw .121 ; carr de 11 = 121
retlw .144 ; carr de 12 = 144
190
retlw .169 ; carr de 13 = 169
retlw .196 ; carr de 14 = 196
retlw .225 ; carr de 15 = 225
END ; directive fin de programme
Il ne nous reste plus qu construire un petit programme principal qui fasse appel cette
sous-routine.
;**********************************************************************
; DEMARRAGE SUR RESET *
;**********************************************************************
org 0x000 ; Adresse de dpart aprs reset
;*********************************************************************
; PROGRAMME PRINCIPAL *
;*********************************************************************
start
clrf nombre ; effacer nombre
loop
movf nombre , w ; charger nombre
call carre ; prendre le carr du nombre
incf nombre , f ; incrmenter nombre
btfss nombre , 4 ; tester si nombre >15
goto loop ; non, nombre suivant
goto start ; oui, on recommence 0
Afin de permettre PCLATH de pointer sur la page 0x300 lors du calcul dincrmentation de
PCL.
repere
ORG (repere+31)& 0x3E0 ; adresse du tableau
191
Il est important de comprendre que cest lensemble des instructions retlw qui
doivent se trouver dans la mme page. Dans le cas prcdent (petit tableau), vous notez quil
y a une instruction qui se trouve dj dans cette page, ce qui fait 1 emplacement de moins
disponible.
Toujours pour le cas dun tableau de 256 lments, nous voyons que nous devons
imprativement commencer le tableau un offset de 0 (PCL = 0). Inutile donc de faire une
addition de 0 , il suffit de placer directement w dans PCL, quelque soit ladresse de
cette imputation, du moment que PCLATH soit correctement configur. Nous obtenons donc :
carre
movwf PCL , f ; ajouter w PCL (adresse = suite du programme
principal)
org 0x300 ; adresse effective du tableau(256 emplacements
disponibles)
retlw 8 ; premier lment du tableau : adresse 0x300
retlw 4 ; second lment du tableau : adresse 0x301
Un des reproches quon entend souvent au sujet des PICs est le nombre restreint des
variables disponibles. Il ne faudrait cependant pas croire que, sous prtexte que nous
programmions en assembleur, nous ne disposions pas de variables locales.
Pour rappel, ce sont des variables qui ne seront utilises qu lintrieur dune sous-routine, et
qui ne servent plus une fois la sous-routine termine. Partons donc dun programme
imaginaire qui utilise deux sous-routines.
- La seconde est la sous-routine fonction . Elle reoit un paramtre dans W, doit sauver
le rsultat dans une variable, et utilise 2 autres variables pour ses calculs intermdiaires.
- La condition pour lutilisation de variables locales identiques, est quune des routines
nappelle pas lautre.
192
18.7.1 Dtermination des variables locales
Si nous examinons les routines, nous constatons que les 2 variables de la sous-routine
tempo ne sont utiles qu lintrieur de celle-ci. Nous pouvons donc utiliser des variables
locales.
Que serait notre zone de variables sans lutilisation des variables locales ? Et bien
crons notre zone de variables :
CBLOCK 0X0C
Cmpt1 : 1 ; compteur 1 pour routine tempo
Cmpt2 : 1 ; compteur 2 pour routine tempo
Resultat : 1 ; rsultat pour routine fonction
Interm1 : 1 ; rsultat intermdiaire1 pour fonction
Interm2 : 1 ; rsultat intermdiaire2 pour fonction
ENDC
Nous voyons que nous aurons besoin de 5 variables. Utilisons maintenant les variables
locales.
Premirement, nous allons rserver les emplacements mmoires ncessaires pour les
variables locales. Le plus grand nombre de variables locales utilises par une fonction, est de
2. Nous aurons donc 2 variables locales. Dclarons-les.
Ensuite, il nous reste une variable globale ajouter. Crons notre zone data :
CBLOCK 0X0C
Local1 : 1 ; variable locale 1
Local2 : 1 ; variable locale 2
Resultat : 1 ; rsultat pour fonction
ENDC
Il ne nous faudra donc plus que 3 variables au lieu des 5 initiales. Pour mieux nous y
retrouver, nous pouvons attribuer les mmes noms que prcdemment pour nos variables
locales, en ajoutant simplement des DEFINE ou des EQU.
Et voil, pas besoin du C pour utiliser les variables locales trs simplement.
193
18.8 Division par une constante
Pour diviser un nombre par une constante, il suffit de multiplier ce nombre par une autre
constante qui vaut : 256 divis par la constante initiale.
On obtient un rsultat sur 16 bits, le rsultat de la division se trouve dans loctet de poids
fort.
Exemple :
Pour diviser un nombre par 10, il suffit de le multiplier par (256/10). En hexadcimal,
256/10 donne 0x19 ou 0x1A (il faut bien arrondir)
Imaginons que notre variable contienne la valeur 120 dcimal, soit 0x78.
Si on multiplie 0x78 par 0x1A, a donne 0x0C30. Le poids fort est donc 0x0C, ce qui
donne 12 en dcimal.
18.9 Conclusion
194
19. La norme ISO 7816
Le but de cette annexe est de vous montrer comment raliser une application pratique
en dpassant les limites apparentes du PIC. Jai choisi de crer lossature dun programme de
gestion dune carte ISO7816, car cest un sujet dactualit (ne me demandez pas pourquoi, je
ferai semblant de ne pas le savoir).
De plus, cest un excellent prtexte pour montrer quil est possible dutiliser un 16F84,
pourtant dpourvu de la gestion srie, pour communiquer de cette manire avec le monde
extrieur.
Cette annexe se limitera la norme en gnral, sans entrer dans une application
spcifique de cette norme. Le but nest pas en effet de construire votre propre application (par
exemple une serrure code), mais plutt de vous montrer comment la concevoir vous-mme.
Inutile donc de menvoyer du courrier pour savoir comment cette norme est utilise en
pratique pour telle ou telle application non publique, je ny rpondrai pas.
Voyons tout dabord quelques spcificits de la norme 7816 qui va nous servir crer
notre application.
Vous trouverez ces cartes partout dans le commerce de composants lectroniques, sous
la dnomination carte pour serrure code . Elles permettent de raliser des tas
dapplications, et les lecteurs sont disponibles partout. Vous aurez besoin pour communiquer
avec cette carte dune interface dont vous trouverez le schma sur Internet sous la
dnomination phnix , et dun logiciel de communication ou du logiciel fourni avec
linterface.
- La carte ne dispose pas de sa propre horloge, elle est fournie par linterface, ou matre, et
est gnralement sous la barre des 4MHz.
- Le temps sparant chaque bit est dfini par la norme comme tant de 1 bit mis toutes les
372 impulsions de lhorloge du matre. Ceci donne un dbit de lordre de 9600 bauds avec
un quartz de 3,57 MHz (3570000/372), ou encore 10752 bauds avec notre quartz de 4Mhz
- La transmission est du type asynchrone, avec 1 start-bit, 8 bits de data, 1 bit de parit
paire, et 2 stop-bits.
- La communication est du type half-duplex, cest dire que les entres et les sorties
seffectuent par alternance et en se servant de la mme ligne physique.
195
Nous allons dans cet exercice utiliser des commandes bidon de la norme ISO7816.
Il faut savoir que notre carte devra rpondre des commandes organises suivant le protocole
standard de cette norme.
La carte ne prend jamais linitiative de lchange dinformations. Elle ne fait que
rpondre des commandes de la forme :
- INS : cest linstruction proprement dite, ou encore la commande. Cest cet octet qui
dtermine lopration effectuer par la carte.
- LEN : peut reprsenter 2 choses. Soit cest le nombre doctets qui suit la commande, dans
ce cas la carte sattendra recevoir LEN octets supplmentaires avant de traiter la
commande dans sa totalit. Soit ce sera la longueur de la chane de rponse que le matre
sattend recevoir en provenance de la carte. Cest linstruction qui permet dtablir le
rle de LEN.
Notez quil existe des modes tendus pour la norme ISO7816, qui permet la fois
denvoyer et de recevoir plusieurs octets en une seule opration. Ce mode est dfini comme
mode T=1. Dans notre cas, nous supposons que linformation ne circule que dans un sens
pour une instruction donne (Mode T=0).
- A la mise en service, le matre gnre un RESET sur la pin MCLR, la carte rpond avec un
certain nombres doctets. Cette rponse sappelle ATR, pour Answer To Reset (rponse
au reset).
196
Donc, si nous supposons par exemple linstruction imaginaire 0x14 de la classe 0xD5 qui
ncessite une rponse de la part de la carte (instruction carte vers matre). Le matre prcise
P1 =0x01 et P2 = 0x02. Nous aurons donc (en imaginant les octets de data) :
- Le matre envoie : D5 14 01 02 10
- Nous en dduisons que le matre attend 16 octets en rponse (0x10 = D16)
- La carte rpond : 14 (accus de rception)
- La carte envoit : 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F (par exemple), soit 16
octets de rponse, exclus laccus de rception et le status.
- La carte envoit : 90 00 : status employ en gnral pour indiquer que lopration sest bien
passe
Si, par contre, dans les mmes conditions, nous imaginons linstruction 0x15
accompagne doctets destination de la carte (instruction matre vers carte), nous aurons :
- Le matre envoit : D5 15 01 02 10
- La carte rpond : 15 (accus de rception)
- Le matre envoit : 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F (par exemple)
- La carte rpond : 90 00
Vous voyez que seul le sens de circulation des 16 octets de data change de direction. Cest
donc toujours le matre qui envoie la trame de dpart, et la carte qui envoie laccus de
rception et le status.
Les changes dinformation entre le matre et la carte se font sur une liaison srie
asynchrone. Pour comprendre la suite de ce chapitre, il faut donc comprendre ce que cela
signifie.
Le mode srie est dfini pour signaler que tous les bits dun octet vont tre envoys en
srie les uns derrire les autres. Ceci par opposition au mode parallle pour lequel tous les bits
seraient envoys en mme temps, chacun, de ce fait, sur un fil spar.
Asynchrone est loppos de synchrone, cest--dire quil sagit dune liaison qui ne
fournit pas une horloge destine indiquer le dbut et la fin de chaque bit envoy.
Nous aurons donc besoin dun mcanisme destin reprer la position de chaque bit.
Notez quil sagit ici dun mode asynchrone particulier, tant donn que la carte utilise la
mme horloge que le matre. La vitesse ne sera donc exceptionnellement pas donne en
bauds, mais en nombre dimpulsions dhorloge. Un bit toutes les 372 impulsions dhorloge.
Pour recevoir correctement les bits envoys, il faut convenir dun protocole de
communication. Ce dernier doit comprendre les informations suivantes :
197
Nous allons maintenant expliquer ces concepts et indiquer quelles sont les valeurs
employes dans la norme ISO 7816.
19.2.1 Le start-bit
Au repos, la ligne se trouve ltat haut. Lmetteur fait alors passer la ligne ltat
bas : cest le start-bit. Cest ce changement de niveau qui va permettre de dtecter le dbut de
la rception des bits en srie.
Les valeurs admissibles sont 1 ou 2 start-bit(s). La norme ISO 7816 ncessite un start-
bit.
Aprs avoir reu le start-bit, on trouve les bits de donnes, en commenant par le bit 0.
Les normes usuelles utilisent 7 ou 8 bits de data. Pour la norme ISO 7816, nous aurons 8 bits
de donnes, ce qui nous donne des valeurs admissibles de 0 0xFF pour chaque octet reu.
On dira quon utilise une parit paire si le nombre de bits 1 dans les bits de donnes
y compris le bit de parit est un nombre pair.
Notez que le bit de parit nest pas indispensable dans une liaison srie asynchrone.
Nous avons donc 3 possibilits, savoir pas de parit, parit paire, ou parit impaire.
Dans le cas de la norme ISO 7816, nous devrons utiliser une parit paire.
19.2.4 Le stop-bit
Aprs la rception des bits prcdents, il est impratif de remettre la ligne ltat haut
pour pouvoir dtecter le start-bit de loctet suivant. Cest le rle du stop-bit. Les valeurs
admissibles sont de 1 ou 2 stop-bits.
Dans la norme ISO 7816, nous utiliserons 2 stop-bits, cest dire tout simplement un
stop-bit dune dure quivalente la dure de 2 bits.
198
19.2.5 Vitesse et dbit
La dure de chaque bit est une constante et dpend de la vitesse de transmission. Par
exemple, pour une vitesse de 9600 bauds, cest dire 9600 bits par seconde, chaque bit durera
1s/9600 = 104,17 S.
Le temps ncessaire pour recevoir un octet entier est la somme du temps ncessaire
pour recevoir chacun des bits de cet octet. Dans le cas de la norme ISO 7816, nous utiliserons
1 start-bit + 8 bits de donnes + 1 bit de parit + 2 stop-bits = 12 bits. Le temps total pour
recevoir un octet est donc de 1250 S.
Dbit maximum = 1 / (nbre de bits * dure dun bit), soit pour la norme ISO 7816 :
CECI POUR UNE VITESSE DE TRANSFERT DE 9600 BAUDS. Notez que cette valeur
nest pas impose par la norme, il est donc possible daugmenter ce dbit.
Nous parlons ici de dbit maximum car ceci est le cas dans lequel un octet commence ds
la fin du prcdent, ce qui nest pas obligatoire pour une liaison asynchrone.
Nous allons dabord reprsenter ce que nous venons de voir sous forme dun
graphique. Sur laxe vertical nous avons les niveaux, sur laxe horizontal, le temps. Chaque
carr reprsente la dure dun bit.
Examinons ce graphique. La ligne est ltat haut depuis un temps indtermin. Survient
le start-bit, qui commence 2 carrs aprs notre axe vertical. Nous voyons que le meilleur
moment pour lire le bit 0 est de le mesurer au milieu de sa largeur afin dobtenir le moins de
risque derreur possible.
Souvenez-vous que pour la norme ISO 7816, la largeur dun bit vaut 372 impulsions
dhorloge. Comme notre PIC divise dj la frquence dhorloge par 4, cela nous fera une
largeur de bit quivalent 372/4 = 93 impulsions dhorloge.
199
Le bit 0 sera donc lu 93 + 46 cycles dhorloge aprs le dbut du start-bit. Ensuite nous
pourrons lire tous les bits un intervalle de temps quivalent 93 instructions.
- Si nous souhaitons faire suivre cette lecture par la lecture dun autre octet, nous devons
nous positionner quelque part dans les 2 stop-bits afin dtre prt dtecter le start-bit
suivant. Nous devons donc attendre entre 0.5 et 2.5 bits.
- Si nous souhaitons envoyer un octet aprs cette lecture, nous ne pourrons pas le faire
avant la fin du second stop-bit, soit au minimum aprs 2.5 cycles.
Par curiosit, quel est donc loctet que nous avons reu dans cet exemple ? Et bien tout
simplement :
B0 = 1
B1 = 0
B2 = 0
B3 = 1
B4 = 0
B5 = 1
B6 = 0
B7 = 1
Parit = 0
Loctet reu est donc B10101001 , soit 0XA9. Profitons-en pour vrifier la parit.
Nombre de bits 1 reus = 4, donc parit paire, cest donc conforme la norme ISO 7816.
Sur les cartes du commerce, de type carte pour serrure code , les connexions
utilises sont gnralement les suivantes :
200
;***********************************************************************
; Ce fichier est la base de dpart pour la gestion d'une carte *
; rpondant la norme ISO7816. *
; *
;***********************************************************************
; *
; NOM: ISO7816 *
; Date: 10/03/2001 *
; Version: 1.1 *
; Circuit: Carte pour serrure code *
; Auteur: Bigonoff *
; *
;***********************************************************************
; *
; Fichier requis: P16F84.inc *
; *
;***********************************************************************
; *
; - MCLR Commande de reset de la carte Entre *
; - RB4 SDA - data pour eeprom externe Bi-directionnel *
; - RB5 SCL - horloge pour eeprom externe Sortie *
; - RB7 DATA - donnes mode srie Bi-directionnel *
; *
;***********************************************************************
Comme lcart entre 2 bits est de 93 instructions, nous travaillerons sans prdiviseur,
ce qui nous impose de rediriger le prdiviseur vers le watchdog.
201
19.6 La base de temps
temp_1b
movlw -91 ; cart entre 2 bits + 2 cycles darrt
addwf TMR0 , f ; ajouter la valeur actuelle
temp_suite
bcf INTCON , T0IF ; effacer flag
temp_wait
btfss INTCON , T0IF ; attendre dbordement timer
goto temp_wait ; pas fini, attendre
return ; et sortir
Comment cette routine fonctionne-t-elle ? Et bien vous remarquez que vous avez 2
points dentre, temp_1bd et temp_1b. Commenons par examiner ce dernier point.
Quel est le nombre de ces instructions ? Et bien tout simplement le nombre contenu
dans TMR0, puisque le prcdent passage avait attendu sa remise 0. Il ne faut donc pas
placer 91 dans tmr0, mais bien AJOUTER 91 au contenu actuel de TMR0.
De cette faon, nous sommes assurs que le dbordement du TMR0 se fera exactement
93 cycles aprs le prcdent dbordement, quelque soit le nombre dinstructions excut entre
les 2 appels. Ceci, bien entendu condition que le timer nai pas dbord avant, mais ceci
impliquerait que nous navons pas le temps de tout excuter entre 2 bits, donc que le PIC nest
pas suffisamment rapide, ou notre application pas suffisamment optimise en temps
dexcution.
Tout de suite aprs, nous replaons le flag T0IF 0, et nous attendons simplement que
le dbordement du timer entrane le repositionnement du flag.
202
Examinons maintenant le point dentre temp_1bd : Nous commenons par initialiser
TMR0 avec 38, pour dmarrer la temporisation de 40 instructions partir de ce point.
Comme cest au dbut de lacquisition que nous avons besoin dun demi-bit, il ny a pas
eu de bit prcdent, donc nous devons placer cette valeur et non faire une addition. De plus,
entre la dtection du start-bit et linitialisation de TMR0, il sest pass quelques instructions.
On peut grossirement considrer quil sest pass 6 instructions, ce qui nous donne une
valeur charger de (46 6) = -40, et en tenant compte des 2 cycles perdus : -38.
Quelle est en ralit notre marge derreur ? Et bien tout simplement la moiti de la
dure dun bit, cest dire 46 cycles, afin de ne pas tomber sur le bit contigu. Nous ne
sommes donc pas 1 cycle prs, mais il faut rester le plus prcis possible pour le cas o une
drive de lappareil connect augmenterait notre imprcision. Il faut penser que le concepteur
du logiciel du matre a peut-tre lui aussi profit de cette tolrance.
Maintenant que vous avez compris comment recevoir un octet en mode srie
asynchrone, il est temps dcrire notre sous-programme de rception dun octet. Dans cet
exercice, nous ne vrifierons pas si le bit de parit reu est correct. Je vous laisse de soin
dintgrer ce test vous-mme si cela vous intresse. Dans ce cas, vous devrez lire 9 bits et
vrifier si le nombre de 1 reus est pair. Il y a plusieurs mthodes possibles.
;*********************************************************************
; Rception d'un octet provenant du matre *
;*********************************************************************
;---------------------------------------------------------------------
; Caractre lu dans W. La parit pas n'est pas vrifie
;---------------------------------------------------------------------
Receive
; attendre dbut start-bit
; ------------------------
203
call temp_1bd ; attendre 1bit et demi
; rception du caractre
; ----------------------
Recloop
bcf STATUS , C ; Carry = 0
btfsc SERIAL ; tester si bit = 0
bsf STATUS , C ; Carry = bit reu
rrf caract , f ; faire entrer le bit par la gauche
call temp_1b ; attendre milieu caractre suivant
decfsz cmptbts , f ; dcrmenter compteur de bits
goto Recloop ; pas dernier, suivant
Au final, le premier bit lu se retrouve donc en b0, le dernier restant en b7, ctait bien le
but recherch.
Nous devons donc attendre entre 0.5 et 2.5 bits. La sous-routine 1.5 bit est en plein
dans cette zone et est directement utilisable.
Le prsent sous-programme utilise des variables que nous dclarerons plus loin.
Noublions pas que notre carte nmet quen rponse une interrogation du matre .
Donc, notre sous-programme dmission sera appel aprs le sous-programme de rception
dun octet.
204
se rappeler que notre routine de rception sachvera quelque part au milieu des stop-bits, il
faudra galement laisser lmetteur le temps de finir denvoyer la fin de ses stop-bits.
;*********************************************************************
; Envoi d'un octet vers le lecteur de carte *
;*********************************************************************
;---------------------------------------------------------------------
; envoie l'octet contenu dans le registre w vers le lecteur de carte
;---------------------------------------------------------------------
Send
movwf caract ; Sauver caractre envoyer
call temp_1bd ; attendre 1 bit et demi
BANK1 ; passer banque1
bcf SERIAL ; port srie en sortie
BANK0 ; repasser banque 0
; envoyer start-bit
; --------------------
bcf SERIAL ; envoyer 0 : start-bit
clrf parite ; effacer bit de parit
205
; envoyer parit
; --------------
movf parite , w ; charger parit paire calcule
xorwf PORTB , w ; Si serial diffrent de bit envoyer
andlw 0x80 ; on ne modifie que RB7
xorwf PORTB , f ; alors inverser RB7
call temp_1b ; attendre fin de parit
; envoyer 2 stop-bits
; -------------------
BANK1 ; passer banque1
bsf SERIAL ; repasser en entre (et niveau haut)
BANK0 ; passer banque 0
call temp_1b ; attendre temps entre 2 bits
call temp_1b ; attendre temps entre 2 bits
return ; et retour
Si vous tes attentifs, vous avez remarquer une lgre inversion en ce qui concerne la
fin du protocole. En effet, plutt que denvoyer un niveau 1 (stop-bit) puis dattendre 2 bits et
enfin de repasser en entre, nous sommes pass en entre puis avons attendu 2bits.
Ceci est strictement identique, car la rsistance de rappel au +5V du PORTB, que nous
avons active se charge dimposer un niveau haut sur RB7 ds que cette pin est remise en
entre, un niveau haut correspondant un stop-bit.
La routine servant envoyer les 8 bits utilise linstruction xorwf au lieu de tester si
le bit mettre vaut 1 ou 0. La routine commence par placer le bit mettre en position b7.
Pourquoi b7 ? Et bien tout simplement parce que cest galement b7 dans le PORTB que
nous devrons modifier. Nous utilisons en effet RB7. La procdure utilise permet de
positionner en mme temps le bit de parit.
Effectuez lopration manuellement sur papier pour vous en convaincre. Tentez dcrire
une routine utilisant btfss et btfsc et comparez les rsultats obtenus.
Un petit mot concernant lenvoi du bit proprement dit, cest dire les 3 instructions :
Nous commenons ici par lire le PORTB et nous effectuons un xorlw avec le bit
envoyer contenu dans W . Comme W ne contient que ce bit, RB0 RB6 ne seront pas
modifis par les oprations suivantes.
Si le bit7 contenu dans W est diffrent de celui prsent sur RB7, nous obtenons b7
= 1 dans W. Dans le cas o b7 de W est identique RB7, nous obtenons 0. Noublions pas en
effet que le ,W permet de placer le rsultat dans W .
206
Ceci parat un peu tordu , mais si vous essayez dcrire cette routine autrement,
vous verrez quen effectuant plusieurs essais, vous arriverez un rsultat identique, tout ceci
cause de la parit grer. Sauf si vous acceptez de modifier les autres lignes du PORTB.
Remarquez que vous pouvez ignorer la vrification du bit de parit en rception, cest
votre problme. Par contre, vous tes oblig de positionner correctement celle-ci lmission,
car il y a de fortes chances pour que le matre vrifie cette parit.
19.9 Initialisation
Nous allons maintenant tudier le corps de notre programme principal. Comme tout
programme qui se respecte, nous commencerons par linitialisation. Celle-ci va tre trs
simple, elle se limite initialiser le registre OPTION.
;*********************************************************************
; INITIALISATIONS *
;*********************************************************************
org 0x000 ; Adresse de dpart aprs reset
init
BANK1 ; passer banque1
movlw OPTIONVAL ; charger masque
movwf OPTION_REG ; initialiser registre option
BANK0 ; passer banque 0
ATR signifie Answer To Reset, cest dire rponse un reset. Cest une commande
envoye par la carte lors dune mise sous tension ou lors dun reset gnr par le matre via la
broche MCLR .
Tout dabord, nous allons attendre un peu que le matre soit prt recevoir notre ATR.
Il peut tre ncessaire dajuster ce temps en fonction des caractristiques du matre, qui a
probablement dautres choses faire au dmarrage que de soccuper directement de votre
carte.
;*********************************************************************
; PROGRAMME PRINCIPAL
*
;*********************************************************************
start
; on commence par attendre un peu
; -------------------------------
call temp_1bd ; attendre 1 bit et demi
Ensuite, nous pouvons envoyer lATR. Pour des raisons de facilit, nous avons crit
notre ATR dans la zone eeprom interne. Jai choisi un ATR de 5 caractres que jai invent.
Consultez les caractristiques du matre pour connatre les ATR valides de votre application.
;===============================================================
; ENVOI DE L'ATR =
;===============================================================
;---------------------------------------------------------------
; Envoi d'un ATR fictif : l'ATR est dans les 5 octets de 0x04
207
; 0x00 de l'eeprom interne. L'ATR est cris en sens inverse
;---------------------------------------------------------------
movlw 0x5 ; pour 5 octets
movwf cmpt1 ; dans compteur de boucles = adresse
ATR_loop
decf cmpt1 , w ; adresse lire = compteur de boucles-1
call Rd_eeprom ; Lire un octet eeprom interne
call Send ; Envoyer sur le dcodeur
decfsz cmpt1 , f ; dcrmenter compteur
goto ATR_loop ; pas fini, suivant
Remarques
;*********************************************************************
; DECLARATIONS DE LA ZONE EEPROM *
;*********************************************************************
org 0x2100 ; adresse dbut zone eeprom
La norme ISO 7816 demande que chaque mission dune rponse de la carte soit suivi
de 2 octets de status qui indiquent la manire dont a t interprte la commande.
208
Jai invent des status pour cet exercice. Le status 80 00 indiquera que la
commande a t excute correctement. Jutiliserai galement le status 60 40 pour
indiquer que la commande nexiste pas.
Nous allons donc crer 2 sous-programme. Un qui envoie le status standard, lautre
qui envoie nimporte quel status.
;===============================================================
; ENVOI DU STATUS STANDARD =
;===============================================================
;---------------------------------------------------------------
; Envoie le status standard, dans ce cas on a pris 0x80 0X00
;---------------------------------------------------------------
Statstd
movlw 0x80 ; prendre 1er octet status
call Send ; l'envoyer
clrw ; effacer w
call Send ; envoyer 00
goto classe ; et traiter classe
;================================================================
; ENVOI D'UN STATUS SPECIFIQUE =
;================================================================
;----------------------------------------------------------------
; Envoie d'abord l'octet contenu dans w, puis l'octet contenu dans status2
;----------------------------------------------------------------
Statxx
call Send ; on envoie valeur
movf status2 , w ; charger byte envoyer
call Send ; on envoie 2me octet du status
;=================================================================
; LECTURE DE LA CLASSE =
;=================================================================
;-----------------------------------------------------------------
; on considre dans cet exemple qu'il n'y a qu'une seule classe valide.
; on attend l'arrive de la classe et on ne la traite pas
;-----------------------------------------------------------------
classe
call Receive ; Lire le byte venant du matre
209
;===============================================================
; LECTURE DE INS,P1,P2,LEN =
;===============================================================
;---------------------------------------------------------------
; INS sera plac dans la variable Ser_ins P1 sera plac dans
; Ser_P1 et P2 dans Ser_P2
; La longueur du champs de data sera dans Ser_len
;---------------------------------------------------------------
movlw Ser_Ins ; pointer sur emplacement instruction
movwf FSR ; initialiser pointeur indirection
read_loop
call Receive ; Lire un octet
movwf INDF ; sauver dans emplacement prvu
incf FSR , f ; pointer sur suivant
btfss FSR , 0x4 ; Tester si adresse 0x10 atteinte
goto read_loop ; non, octet suivant
Vous pouvez constater lutilisation de ladressage indirect pour sauvegarder les octets
reus dans 4 emplacements conscutifs. Nous choisirons les adresses 0x0C 0x0F, ce qui
nous permet facilement de dtecter la fin de la commande. En effet, une fois le 4me octet
sauv, FSR pointe sur 0x10, il suffit donc de tester son bit 4 pour tester la fin de la boucle,
sans avoir besoin dun compteur de boucles supplmentaire.
Une fois la commande reue, nous devons traiter les diffrentes commandes reues.
Dans notre exemple didactique, jai implment une seule instruction. La seule instruction
valide est linstruction 0x25.
;==============================================================
; SWITCH SUIVANT INSTRUCTION RECUE =
;==============================================================
;--------------------------------------------------------------
; Nous allons imaginer que nous allons ragir une instruction 0x25
; Toute autre instruction sera considre comme incorrecte
;--------------------------------------------------------------
; tester instruction reue
; ------------------------
movf Ser_Ins , w ; charger instruction reue
sublw 0x25 ; comparer avec 0x25
btfsc STATUS , Z ; tester si identique
goto Ins25 ; oui, traiter instruction 25
210
Nous voyons ici que si linstruction reue est 0x25, nous sautons au traitement de
linstruction. Dans le cas contraire, nous envoyons le status 60 40 qui signifie dans notre
cas instruction incorrecte .
;================================================================
; TRAITER INSTRUCTION 25 =
;================================================================
Ins25
; envoyer cho de la commande
; ---------------------------
movf Ser_Ins , w ; charger commande reue
call Send ; renvoyer en cho
; renvoyer P1 + P2
; ----------------
movf Ser_P1 , w ; charger P1
addwf Ser_P2 , w ; + P2
call Send ; envoyer rsultat
Il nous reste maintenant dclarer les variables utilises. Jai dcid ici dutiliser des
variables locales lorsque ctait possible :
211
;*********************************************************************
; DECLARATIONS DE VARIABLES *
;*********************************************************************
; routine ATR
; -----------
#DEFINE cmpt1 local1 ; compteur d'octets pour ATR
; pour STATUS
; -----------
#DEFINE status2 local1 ; octet 2 du status
; pour instruction 25
; -------------------
#DEFINE cmpt2 local1 ; compteur d'octets
19.17 Conclusion
Vous savez maintenant communiquer en liaison srie asynchrone. De plus vous avez
les notions de base ncessaire pour raliser une carte rpondant la norme ISO7816. Nul
doute que vous trouviez de nombreuses applications mettant en uvre la thorie vue ici.
Je vous rappelle quil sagit ici dun exemple imaginaire. Inutile donc de mcrire pour
me demander comment transformer cet exemple pour lutiliser en pratique en tant que cl
pour une serrure code quelconque. Je rappelle que je ne rpondrai pas.
Jai reu galement un nombreux courrier de lecteurs qui ont cru avis de
commencer la lecture du cours par ce chapitre. Il ne faut pas mettre la charrue avant les
bufs, et si ce chapitre est plac en fin de cours, cest que jai estim quil ncessitait la
comprhension de ce qui prcde.
212
Annexe1 : Questions frquemment poses (F.A.Q.)
Je vais tenter de rpondre ici un maximum de questions que se posent les utilisateurs
en gnral.
Si votre programme est correct, les 3 conditions suivantes doivent tre remplies :
Vous ne devez pas oublier que les interruptions utilisent aussi la pile. Si vous utilisez
les interruptions, vous navez droit qu 7 niveaux dimbrication (moins les sous-routines
utilises ventuellement par la routine dinterruption).
Vous avez oubli de signaler MPLAB que vous utilisez le simulateur. Allez dans le
menu debugger -> select tool et slectionnez MPLAB SIM . Configurez ensuite
comme expliqu dans le chapitre concern.
Si ce nest pas le cas, ouvrez votre fichier .asm dans le bloc-notes de windows et
vrifiez quil se prsente correctement, avec les mises la ligne correctes. Si ce nest pas le
cas, cest que le fichier a t crit avec un diteur qui ne gnre pas les bons retour de ligne.
213
Dans ce cas, essayer un copier/coller de ce fichier dans un fichier vide cr avec un autre
diteur.
Je ne veux pas entrer ici dans le concret, car je veux pas faire de publicit pour un ou
lautre produit sur le march.
Je suis sidr de voir que dans la presse dite spcialise , certains auteurs
continuent de prconiser lutilisation de programmateurs qui ne rpondent pas ces
prescriptions. Ceci me vaut un abondant courrier de lecteurs qui se retrouvent dans
limpossibilit de programmer certains de leurs composants (dont les 16F84A qui sont en
mode code protect ).
En tout tat de cause, FUYEZ les programmateurs qui tirent leur alimentation du port
srie, ils sont sources de la plupart des problmes de programmation.
214
Par contre, pour le logiciel, je vous recommande le meilleur dentre-eux ( mon avis),
et, de plus, entirement gratuit.
Ce logiciel est IC-PROG, et son auteur, Bonny Gijzen, est dune gentillesse toute
preuve, nhsitez pas le remercier par email (en anglais) si vous dcidez dutiliser son
programme. Il a eu la grande gentillesse de mettre son programme jour spcialement pour
moi (donc pour vous), afin de permettre certaines options utilises dans la seconde partie du
cours. Vous pouvez donc lui dire que vous avez trouv son lien dans mon petit cours.
En fait un message stack overflow peut signifier que vous avez dpass les 8 niveaux
de sous-programme autoriss. En effet, je rappelle quil ny a que 8 emplacements sur la pile
(stack), et que donc, une nouvelle tentative dempilement, suite une sous-routine ou une
interruption provoquera lcrasement de la pile.
Dans la plupart des cas, cependant, il sagit dune erreur dans la structure de votre
programme. Le message stack overflow intervient si vous empilez plus de 7
emplacements, le message stack underflow intervient si vous dpilez plus que ce que vous
avez empil (par exemple, return sans call ).
Pour rsoudre ces problmes, si vous navez pas dpass les 8 niveaux (voir A1.2),
vrifiez les points suivants :
- Chaque appel via un call doit revenir au programme appelant par un return ou un
retlw
- Chaque return ou retlw rencontr doit avoir t prcd du call correspondant
- La sortie dune sous-routine avec un goto doit mener un point o on trouvera un
return
- Une routine ne doit pas sappeler elle-mme (sauf fonctions rcursives : rares avec une
telle taille de pile).
215
A1.10 Quelles sont les diffrences entre 16F84 et 16F84A ?
Voici une question qui revient rgulirement dans mon courrier. Je vous livre ici les
principales diffrences entre ces composants :
Ceci signifie que le chemin pour accder votre source excde 62 caractres, ce qui
peut tre le cas si vous utilisez des noms trop longs ou trop de sous-rpertoires. Par exemple :
C:\Mon_repertoire\sources\Sources_MPLAB\Cours\Cours_Part1\Exercices\test1.Asm
Il vous suffit dans ce cas de dplacer votre rpertoire dans un dossier plus proche de la
racine, ou de raccourcir les noms utiliss. Voici un exemple correct :
C:\Cours_pics_1\Exercices\test1.asm
216
Contribution sur base volontaire
La ralisation de ces cours ma demand beaucoup de temps et dinvestissements
(documentations, matriel, abonnements, etc.).
Aussi, pour me permettre de poursuivre, je vous demande, si cela est dans vos possibilits,
et si vous apprciez ce que je fais, de contribuer un peu, chacun selon ses possibilits et ses
dsirs.
J'ai donc besoin de votre aide pour continuer l'aventure. En effet, je ne dispose plus
vraiment de la capacit de consacrer l'intgralit de mon temps libre crire des cours et des
programmes sans recevoir un petit "coup de pouce".
Cependant, je ne voulais pas tomber dans le travers en verrouillant l'accs aux fichiers, et
en imposant un payement pour les obtenir. En effet, je tiens ce qu'ils restent disponibles
pour tous.
J'ai donc dcid d'instaurer un systme de contribution sur base volontaire en permettant
celui qui le dsire, et en fonction de ses propres critres, de m'aider financirement. Le but
n'tant pas de me faire riche, mais plutt de m'aider "joindre les 2 bouts".
Il ne s'agit donc pas d'un payement, ni d'une obligation. Il s'agit simplement d'une
assistance sans promesse d'aucun sorte, et sans contrainte. Je continuerai rpondre au
courrier de tout le monde, sans distinction, et sans interrogation ce sujet.
Une bonne mthode consiste donc, pour celui qui le dsire, tlcharger le document
choisi, le lire ou l'utiliser, puis dcider si cela vaut ou non la peine de m'aider sur base de
l'usage que vous en faites.
Pour remercier ceux qui ont contribu, soit par lenvoi dune lettre, soit par la cration
dun site dutilit publique, joffrirai le logiciel BigoPic V2.0.
Noubliez pas de mettre votre email en caractre dimprimerie, pour que je puisse vous
rpondre.
Je rponds toujours au courrier reu. Aussi, si vous nobtenez pas de rponse, nhsitez
surtout pas me contacter pour vrifier sil ny a pas de nouveau un problme.
Merci davance tous ceux qui mont aid ou maideront poursuivre ce travail de longue
haleine.
217
218
Utilisation du prsent document
Communiquez lauteur (avec politesse) toute erreur constate afin que la mise jour
puisse tre effectue dans lintrt de tous.
Cependant, certains ne lont pas fait, et nont pas mis leur site rgulirement jour en
fonction des nouvelles versions. Ceci implique que je reois rgulirement du courrier de
personnes qui me signalent des erreurs corriges depuis longtemps, et des utilisateurs qui
saperoivent avec dpit quils viennent dimprimer une version obsolte du cours. Vu le
nombre de pages, a ne fait pas plaisir tout le monde.
Aussi, pour ces raisons, et par facilit de maintenance pour moi, jai dcid que ce cours
serait disponible uniquement sur mon site : http://www.abcelectronique.com/bigonoff ou
www.bigonoff.org . Aussi, si vous trouvez mon cours ailleurs, merci de men avertir.
Bien entendu, jautorise (et jencourage) les webmasters placer un lien sur le site,
inutile den faire la demande. Bien entendu, je ferai de mme en retour si la requte men est
faite. Ainsi, jespre toucher le maximum dutilisateurs.
Le prsent ouvrage peut tre utilis par tous, et copi dans son intgralit, condition de
ne rien modifier.
Tous les droits sur le contenu de ce cours, et sur les programmes qui laccompagnent
demeurent proprit de lauteur, et ce, mme si une notification contraire tend dmontrer le
contraire (charte de lhbergeur).
Lauteur ne pourra tre tenu pour responsable daucune consquence directe ou indirecte
rsultant de la lecture et de lapplication du cours ou des programmes.
Toute utilisation commerciale est interdite sans le consentement crit de lauteur. Tout
extrait ou citation dans un but dexemple doit tre accompagn de la rfrence de louvrage.
Lauteur espre quil na enfreint aucun droit dauteur en ralisant cet ouvrage et na
utilis que les programmes mis gracieusement la disposition du public par la socit
Microchip. Les datasheets sont galement disponibles gracieusement sur le site de cette
socit, savoir : http://www.microchip.com
Si vous avez aim cet ouvrage, si vous lutilisez, ou si vous avez des critiques, merci
de menvoyer un petit mail. Ceci me permettra de savoir si je dois ou non continuer cette
aventure avec les parties suivantes.
219
Certains continuent envoyer des messages sur mon ancienne adresse. Prenez
connaissance de la bonne adresse (bigocours@hotmail.com), pour ne pas encombrer des
adresses non concernes. Vous risquez de plus dattendre longtemps votre rponse.
- Je ne ralise pas les programmes de fin dtude pour les tudiants (mme en payant), cest
une demande qui revient toutes les semaines dans mon courrier. Tout dabord je nai pas
le temps, et ensuite je ne pense pas que ce soit un bon service. Enfin, pour faire un peu
dhumour, si je donnais mes tarifs, ces tudiants risqueraient un infarctus.
- Je nai malheureusement pas le temps de debugger des programmes complets. Inutile donc
de menvoyer vos programmes avec un message du style Ca ne fonctionne pas, vous
pouvez me dire pourquoi ? . En effet, je passe plus de 2 heures par jour pour rpondre au
courrier, si, en plus, je devais debugger, jy passerais la journe. Vous comprenez bien que
cest impossible, pensez que vous ntes pas seul poser des questions. Posez plutt une
question prcise sur la partie qui vous semble inexacte.
- Si vous avez des applications personnelles, nhsitez pas les faire partager par tous. Pour
ce faire, vous pouvez me les envoyer. Attention cependant, faites prcder votre envoi
dune demande, je vous redirigerai alors sur une autre bote, celle-ci tant limite 512K.
- Avec cette version, jessaye de rpondre aux demandes lgitimes des personnes qui
travaillent sur diffrentes plates-formes (Mac, Linux, Windows, etc.). Si, cependant, la
version fournie est inexploitable sur votre machine, merci de me le faire savoir. Notez
cependant que ce cours utilise MPLAB pour les exercices, il faudra donc ventuellement
adapter ces exercices en fonction du logiciel quil vous sera possible dutiliser.
Je remercie tous les webmasters des sites repris sur mon site, et qui contribuent
permettre la poursuite de la grande aventure du net gratuit.
Merci tous ceux qui mont inform des erreurs dans les diffrentes versions
Merci tous ceux qui mont crit pour mapporter leur soutien : croyez-moi, a motive :
sans ces personnes, il ny aurait pas eu de seconde partie.
220
- Mise jour rvision 6 le 20/04/2002 : quelques corrections, amliorations de points
suscitant des questions frquentes, passage en format pdf sous compression rar pour
permettre lutilisation sur toutes les machines, masculinisation du terme pic
- Mise jour rvision 8 le 25/10/2002 : Petite correction chapitre 2.4. Lnonc cit en
exemple ne correspond pas celui effectivement dvelopp. Correction du lien vers le site
Microchip en page 27. Modification de la dfinition de CISC et RISC page 17.
- Mise jour rvision 9 le 01/11/2002 : Fautes dorthographe pages 82, 83, 85, 86, 87, 89,
90, 94.
- Mise jour rvision 10 le 04/12/2002 : suppression dune ligne qui prte confusion page
183, quelques correctifs mineurs pages 99, 100, 104,108, 122, 124, 128, 129, 131,132,
134, modification de contribution page 209.
- Mise jour rvision 14 le 11/12/2003 : Modification du schma page 134, correctifs pages
201,190,191 (modification de radix suite au passage de MPLAB5 MPLAB6).
- Mise jour rvision 15 le 13/02/2004 : Correction dune erreur rptitive sur les exemples
et le cours, au niveau de linitialisation de EEADR (changement de banque une ligne trop
tt), pages 96,99,123,142 et fichiers dexemples et de maquette.
- Mise jour rvision 17 le 09/06/2004 : corrections page 34, 198,annexes, ajout dune
astuce de programmation, table des matires, modification de mon adresse courrier.
- Mise jour rvision 18 le 02/08/2004 : Ajout du temps de rveil page 171, remarque page
113
- Mise jour rvision 19 le 27/03/06 : correctifs pages 11, 12, 13, 15, 17, 19, 21, 24, 26, 27,
29, 30, 33, 37, 38, 40, 47, 50, 52, 54, 63, 72, 80, 83, 85, 93, 96, 114, 131, 133, 135, 171,
197, 198, 220, remises en page des portions de codes suite une modification accidentelle
des tabulations, mise jour page 20, remarque pages 24 et 58. Ajout dune annexe.
- Mise jour rvision 20 le 03/04/06 : Ajout dun petit chapitre sur la consommation
minimale en mode sleep
221
- Mise jour rvision 21 le 13/10/06 : correctifs mineurs (surlignages, parenthses,
orthographe) pages 19, 25, 39, 40, 41, 47, 51, 52, 53, 54, 57, 61, 67, 68, 69, 71, 72, 76,
80, 81, 86, 98, 118, 120, 128, 152, 178, passage des nombres H00xx sur 8 bits. Ajout
dune remarque page 44. Rvision 21b, remise en place du schma de loptocoupleur qui
avait disparu.
- Mise jour rvision 22 le 24/01/07 : Modifications importantes dans tout ce qui traite du
timer0 suite loubli de prendre en compte les 2 cycles perdus lors de toute modification
de TMR0. Modifications et adaptations pages 29, 44, 52, 95 y compris les fichiers asm
concerns. Divers correctifs mineurs (tabulations, espaces, ponctuations, orthographe...),
petite modification page 54 concernant le simulateur (lexplication tait reste sur la
version 5). Modification page 21 au niveau de lexplication de la mention -xx que
javais oubli dadapter aux diverses expriences effectues ce sujet.
Sur mon site, vous trouverez galement des livres de reports dinformation, qui vous
permettront de vous exprimer sur ce cours, et sur les autres fichiers proposs en
tlchargement. Posez de prfrence vos questions par email.
Ralisation : Bigonoff
222