You are on page 1of 202

LA PROGRAMMATION DES PICS

PAR BIGONOFF

PREMIERE PARTIE PIC16F84 Rvision 6

1. INTRODUCTION............................................................................................................................................. 8 2. LES SYSTMES DE NUMROTATION ..................................................................................................... 9 2.1 LE SYSTME DCIMAL.................................................................................................................................... 9 2.2 LE SYSTME BINAIRE ..................................................................................................................................... 9 2.3 LE SYSTME HEXADCIMAL ......................................................................................................................... 10 2.4 LES OPRATIONS .......................................................................................................................................... 12 2.5 LES NOMBRES SIGNS .................................................................................................................................. 12 2.6 LES OPRATIONS BOOLENNES. ................................................................................................................... 13 2.6.1 Le complment ..................................................................................................................................... 13 2.6.2 La fonction ET ou AND ............................................................................................................ 14 2.6.3 La fonction OU ou OR ............................................................................................................. 14 2.6.4 La fonction OU EXCLUSIF ou Exclusif OR ou XOR ........................................................ 15 3. COMPOSITION ET FONCTIONNEMENT DES PICS ............................................................................ 16 3.1 QUEST-CE QUUN PIC ? .............................................................................................................................. 16 3.2 LES DIFFRENTES FAMILLES DES PICS ......................................................................................................... 17 3.3 IDENTIFICATION DUN PIC........................................................................................................................... 17 3.4 ORGANISATION DU 16F84............................................................................................................................ 18 3.4.1 La mmoire programme ....................................................................................................................... 18 3.4.2 La mmoire eeprom.............................................................................................................................. 19 3.4.3 La mmoire Ram .................................................................................................................................. 19 4. ORGANISATION DES INSTRUCTIONS ................................................................................................... 20 4.1 GNRALITS .............................................................................................................................................. 20 4.2 LES TYPES DINSTRUCTIONS......................................................................................................................... 20 4.2.1 Les instructions orientes octet ...................................................................................................... 20 4.2.2 Les instructions orientes bits ........................................................................................................ 21 4.2.3 Les instructions gnrales.................................................................................................................... 21 4.2.4 Les sauts et appels de sous-routines..................................................................................................... 21 4.3 PANORAMIQUE DES INSTRUCTIONS .............................................................................................................. 22 4.4 LES INDICATEURS DTAT ............................................................................................................................ 23 4.4.1 Lindicateur dtat Z ...................................................................................................................... 24 4.4.2 Lindicateur dtat C ...................................................................................................................... 24 5. LES DBUTS AVEC MPLAB ...................................................................................................................... 25 5.1 PRPARATION LUTILISATION ................................................................................................................... 25 5.2 CRATION DE NOTRE PREMIER PROJET ......................................................................................................... 26 6. ORGANISATION DUN FICHIER .ASM ............................................................................................. 29 6.1 LES COMMENTAIRES .................................................................................................................................... 29 6.2 LES DIRECTIVES ........................................................................................................................................... 29 6.3 LES FICHIERS INCLUDE ........................................................................................................................... 29 6.4 LA DIRECTIVE _CONFIG............................................................................................................................. 30 6.5 LES ASSIGNATIONS ...................................................................................................................................... 31 6.6 LES DFINITIONS .......................................................................................................................................... 31 6.7 LES MACROS ................................................................................................................................................ 32 6.8 LA ZONE DES VARIABLES ............................................................................................................................. 32 6.9 LES TIQUETTES........................................................................................................................................... 33 6.10 LA DIRECTIVE ORG ............................................................................................................................. 33 6.11 LA DIRECTIVE END ............................................................................................................................. 33 7. RALISATION DUN PROGRAMME ....................................................................................................... 34 7.1 CRATION DE NOTRE PREMIER PROGRAMME ................................................................................................ 34 7.2 LASSEMBLAGE DUN PROGRAMME ............................................................................................................. 35 8. LA SIMULATION DUN PROGRAMME................................................................................................... 37 8.1 LANCEMENT ET PARAMTRAGE DU SIMULATEUR......................................................................................... 37 3

8.2 EXPLICATION DES REGISTRES FONDAMENTAUX ........................................................................................... 39 8.2.1 Les registres PCL et PCLATH ................................................................................................. 40 8.2.2 Le registre W .................................................................................................................................. 41 8.2.3 Le registre STATUS ........................................................................................................................ 41 8.3 LANCEMENT DE LA SIMULATION .................................................................................................................. 42 9. LE JEU DINSTRUCTIONS ......................................................................................................................... 46 9.1 LINSTRUCTION GOTO (ALLER )......................................................................................................... 46 9.2 LINSTRUCTION INCF (INCREMENT FILE) ............................................................................................ 47 9.3 LINSTRUCTION DECF (DECREMENT FILE).......................................................................................... 48 9.4 LINSTRUCTION MOVLW (MOVE LITERAL TO W) .............................................................................. 48 9.5 LINSTRUCTION MOVF (MOVE FILE)................................................................................................... 48 9.6 LINSTRUCTION MOVWF (MOVE W TO FILE) ....................................................................................... 50 9.7 LINSTRUCTION ADDLW (ADD LITERAL AND W)............................................................................... 50 9.8 LINSTRUCTION ADDWF (ADD W AND F) .......................................................................................... 51 9.9 LINSTRUCTION SUBLW (SUBTRACT W FROM LITERAL) .................................................................... 51 9.10 LINSTRUCTION SUBWF (SUBTRACT W FROM F).............................................................................. 53 9.11 LINSTRUCTION ANDLW (AND LITERAL WITH W) ........................................................................... 53 9.12 LINSTRUCTION ANDWF (AND W WITH F) ....................................................................................... 54 9.13 LINSTRUCTION IORLW (INCLUSIVE OR LITERAL WITH W)............................................................... 54 9.14 LINSTRUCTION IORWF (INCLUSIVE OR W WITH FILE) ..................................................................... 55 9.15 LINSTRUCTION XORLW (EXCLUSIVE OR LITERAL WITH W)........................................................... 55 9.16 LINSTRUCTION XORWF (EXCLUSIVE OR W WITH F) ....................................................................... 56 9.17 LINSTRUCTION BSF (BIT SET F)......................................................................................................... 56 9.18 LINSTRUCTION BCF (BIT CLEAR F) ................................................................................................... 57 9.19 LINSTRUCTION RLF ( ROTATE LEFT THROUGH CARRY) .................................................................... 57 9.20 LINSTRUCTION RRF ( ROTATE RIGHT THROUGH CARRY) .................................................................. 58 9.21 LINSTRUCTION BTFSC (BIT TEST F, SKIP IF CLEAR) ......................................................................... 59 9.22 LINSTRUCTION BTFSS (BIT TEST F, SKIP IF SET) .............................................................................. 60 9.23 LINSTRUCTION DECFSZ (DECREMENT F, SKIP IF Z) ........................................................................ 61 9.24 LINSTRUCTION INCFSZ (INCREMENT F, SKIP IF ZERO) .................................................................... 62 9.25 LINSTRUCTION SWAPF (SWAP NIBBLES IN F).................................................................................. 62 9.26 LINSTRUCTION CALL (CALL SUBROUTINE) ..................................................................................... 62 9.27 LINSTRUCTION RETURN (RETURN FROM SUBROUTINE)................................................................. 63 9.28 LINSTRUCTION RETLW (RETURN WITH LITERAL IN W) ................................................................... 66 9.29 LINSTRUCTION RETFIE (RETURN FROM INTERRUPT) ...................................................................... 67 9.30 LINSTRUCTION CLRF (CLEAR F) ...................................................................................................... 67 9.31 LINSTRUCTION CLRW (CLEAR W) ................................................................................................... 67 9.32 LINSTRUCTION CLRWDT (CLEAR WATCHDOG).............................................................................. 68 9.33 LINSTRUCTION COMF (COMPLEMENT F) ......................................................................................... 68 9.34 LINSTRUCTION SLEEP (MISE EN SOMMEIL)....................................................................................... 69 9. 35 LINSTRUCTION NOP (NO OPERATION).............................................................................................. 69 9.36 LES INSTRUCTIONS OBSOLTES .................................................................................................................. 69 10. LES MODES DADRESSAGE .................................................................................................................... 70 10.1 LADRESSAGE LITTRAL OU IMMDIAT ...................................................................................................... 70 10.2 LADRESSAGE DIRECT ................................................................................................................................ 70 10.3 LADRESSAGE INDIRECT ............................................................................................................................ 70 10.3.1 Les registres FSR et INDF ................................................................................................................. 71 10.4 QUELQUES EXEMPLES ................................................................................................................................ 72 11. RALISATION DUN PROGRAMME EMBARQU ............................................................................. 73 11.1 LE MATRIEL NCESSAIRE ......................................................................................................................... 73 11.2 MONTAGE DE LA PLATINE DESSAIS ........................................................................................................... 73 11.3 CRATION DU PROJET ................................................................................................................................ 74 11.4 EDITION DU FICHIER SOURCE ..................................................................................................................... 75 11.5 CHOIX DE LA CONFIGURATION ................................................................................................................... 75 11.6 LE REGISTRE OPTION............................................................................................................................... 76 11.7 EDITION DU PROGRAMME........................................................................................................................... 78 11.8 LE REGISTRE PORTA ................................................................................................................................ 80 4

11.8.1 Fonctionnement particulier des PORTS............................................................................................. 82 11.9 LE REGISTRE TRISA.................................................................................................................................. 82 11.10 LES REGISTRES PORTB ET TRISB .......................................................................................................... 83 11.11 EXEMPLE DAPPLICATION ........................................................................................................................ 84 11.12 LA ROUTINE DINITIALISATION ................................................................................................................ 84 11.13 LES RSULTATS DE LA COMPILATION ....................................................................................................... 87 11.14 LE PROGRAMME PRINCIPAL ...................................................................................................................... 88 11.15 LA SOUS-ROUTINE DE TEMPORISATION .................................................................................................... 89 12. LES INTERRUPTIONS............................................................................................................................... 93 12.1 QUEST-CE QUUNE INTERRUPTION ? ........................................................................................................ 93 12.2 MCANISME GNRAL DUNE INTERRUPTION ............................................................................................ 93 12.3 MCANISME DINTERRUPTION SUR LES PICS ............................................................................................. 94 12.4 LES SOURCES DINTERRUPTIONS DU 16F84................................................................................................ 95 12.5 LES DISPOSITIFS MIS EN UVRE ................................................................................................................. 96 12.6 LE REGISTRE INTCON (INTERRUPT CONTROL) ...................................................................................... 97 12.7 SAUVEGARDE ET RESTAURATION DE LENVIRONNEMENT .......................................................................... 99 12.7.1 Les registres sauvegarder ............................................................................................................. 100 12.7.2 La mthode de sauvegarde............................................................................................................... 100 12.7.3 Particularit de linstruction RETFIE ....................................................................................... 102 12.8 UTILISATION DUNE ROUTINE DINTERRUPTION ....................................................................................... 102 12.9 ANALYSE DE LA ROUTINE DINTERRUPTION ............................................................................................. 105 12.10 ADAPTATION DE LA ROUTINE DINTERRUPTION ..................................................................................... 107 12.11 LINITIALISATION .................................................................................................................................. 108 12.12 CONSTRUCTION DU PROGRAMME PRINCIPAL .......................................................................................... 109 12.13 CONSTRUCTION DE LA ROUTINE DINTERRUPTION ................................................................................. 110 12.14 PASSAGE AU SIMULATEUR DUNE ROUTINE DINTERRUPTION ................................................................ 111 12.15 PREMIRE CORRECTION : RESET DU FLAG ............................................................................................. 113 12.16 SE METTRE LCHELLE DE TEMPS DU PIC ........................................................................................... 114 12.17 LE PROBLME DE LANTI-REBOND ......................................................................................................... 115 12.18 FINALISATION DU PROGRAMME ............................................................................................................. 116 12.19 REMARQUES IMPORTANTES ................................................................................................................... 119 12.20 CONCLUSIONS ........................................................................................................................................ 120 13. LE TIMER 0................................................................................................................................................ 121 13.1 LES DIFFRENTS MODES DE FONCTIONNEMENT ........................................................................................ 121 13.2 LE REGISTRE TMR0................................................................................................................................... 121 13.3 LES MTHODES DUTILISATION DU TIMER0 ............................................................................................. 121 13.3.1 Le mode de lecture simple................................................................................................................ 122 13.3.2 Le mode de scrutation du flag .......................................................................................................... 122 13.3.3 Le mode dinterruption .................................................................................................................... 123 13.3.4 Les mthodes combines .................................................................................................................. 123 13.4 LE PRDIVISEUR ....................................................................................................................................... 123 13.5 APPLICATION PRATIQUE DU TIMER0......................................................................................................... 125 13.5.1 Prparations..................................................................................................................................... 125 13.5.2 Linitialisation.................................................................................................................................. 126 13.5.3 La routine dinterruption ................................................................................................................. 127 13.6 MODIFICATION DES REGISTRES DANS LE SIMULATEUR ............................................................................. 128 13.7 MISE EN PLACE SUR LA PLATINE DESSAIS ............................................................................................... 129 13.8 PREMIRE AMLIORATION DE LA PRCISION ............................................................................................ 130 13.9 SECONDE AMLIORATION DE LA PRCISION ............................................................................................. 130 13.10 LA BONNE MTHODE - ADAPTATION DE LHORLOGE ............................................................................ 131 13.11 LA MTHODE DE LUXE : LA DOUBLE HORLOGE ...................................................................................... 132 13.12 EXEMPLE DUTILISATION DE 2 INTERRUPTIONS ..................................................................................... 132 13.13 CONCLUSION.......................................................................................................................................... 133 14. LES ACCS EN MMOIRE EEPROM ............................................................................................ 134 14.1 TAILLE ET LOCALISATION DE LA MMOIRE EEPROM ........................................................................... 134 14.2 PRPARATION DU PROGRAMME................................................................................................................ 134 14.3 INITIALISATION DE LA ZONE EEPROM ....................................................................................................... 136 5

14.4 LE REGISTRE EEDATA ........................................................................................................................... 137 14.5 LE REGISTRE EEADR .............................................................................................................................. 138 14.6 LE REGISTRE EECON1 ............................................................................................................................ 138 14.7 LE REGISTRE EECON2 ............................................................................................................................ 139 14.8 ACCS EN LECTURE DANS LA MMOIRE EEPROM ................................................................................ 139 14.9 LACCS EN CRITURE LA ZONE EEPROM .............................................................................................. 140 14.10 UTILISATION PRATIQUE DE LA MMOIRE EEPROM ............................................................................ 142 14.11 SCURISATION DES ACCS EN MMOIRE EEPROM ............................................................................. 145 14.12 CONCLUSION.......................................................................................................................................... 145 15. LE WATCHDOG........................................................................................................................................ 146 15.1 LE PRINCIPE DE FONCTIONNEMENT .......................................................................................................... 146 15.2 LE PRDIVISEUR ET LE WATCHDOG .......................................................................................................... 146 15.3 LES RLES DU WATCHDOG ....................................................................................................................... 147 15.4 UTILISATION CORRECTE DU WATCHDOG .................................................................................................. 147 15.5 CE QUIL NE FAUT PAS FAIRE.................................................................................................................... 147 15.6 MESURE DU TEMPS REL DU WATCHDOG ................................................................................................. 148 15.7 SIMULATION DU PLANTAGE DUN PROGRAMME ....................................................................................... 149 15.7.1 Correction avec utilisation du watchdog ......................................................................................... 150 15.8 CHOIX DE LA VALEUR DU PRDIVISEUR ................................................................................................... 151 15.9 TEMPS TYPIQUE, MINIMAL, ET MAXIMUM ................................................................................................ 152 15.10 CONCLUSION.......................................................................................................................................... 152 16. LE MODE SLEEP ...................................................................................................................................... 153 16.1 PRINCIPE DE FONCTIONNEMENT ............................................................................................................... 153 16.2 LA SORTIE DU MODE SLEEP ................................................................................................................ 153 16.3 RVEIL AVEC GIE HORS SERVICE. ........................................................................................................... 154 16.4 RVEIL AVEC GIE EN SERVICE................................................................................................................. 154 16.5 MISE EN SOMMEIL IMPOSSIBLE ................................................................................................................ 154 16.6 UTILISATION DU MODE SLEEP ............................................................................................................ 155 16.7 CAS TYPIQUES DUTILISATION ................................................................................................................. 155 16.8 CONCLUSION............................................................................................................................................ 156 17. LE RESTE DU DATASHEET ................................................................................................................... 157 17.1 LA STRUCTURE INTERNE .......................................................................................................................... 157 17.2 LA SQUENCE DE DCODAGE ................................................................................................................... 157 17.3 ORGANISATION DE LA MMOIRE .............................................................................................................. 157 17.4 LES REGISTRES SPCIAUX ........................................................................................................................ 158 17.5 LLECTRONIQUE DES PORTS ................................................................................................................... 158 17.6 LE REGISTRE DE CONFIGURATION ............................................................................................................ 158 17.7 LES DIFFRENTS TYPES DOSCILLATEURS ................................................................................................ 159 17.7.1 La prcision de loscillateur ............................................................................................................ 160 17.8 LE RESET .................................................................................................................................................. 161 17.9 LA MISE SOUS TENSION ............................................................................................................................ 162 17.10 CARACTRISTIQUES LECTRIQUES ......................................................................................................... 163 17.11 PORTABILIT DES PROGRAMMES ............................................................................................................ 163 17.12 LES MISES JOUR DES COMPOSANTS...................................................................................................... 164 17.13 CONCLUSION.......................................................................................................................................... 165 18. ASTUCES DE PROGRAMMATION ....................................................................................................... 166 18.1 LES COMPARAISONS ................................................................................................................................. 166 18.2 SOUSTRAIRE UNE VALEUR DE W ............................................................................................................... 166 18.3 LES MULTIPLICATIONS ............................................................................................................................. 167 18.4 MULTIPLICATION PAR UNE CONSTANTE ................................................................................................... 169 18.5 ADRESSAGE INDIRECT POINTANT SUR 2 ZONES DIFFRENTES .................................................................. 170 18.6 LES TABLEAUX EN MMOIRE PROGRAMME .............................................................................................. 171 18.7 LES VARIABLES LOCALES ......................................................................................................................... 175 18.7.1 Dtermination des variables locales ................................................................................................ 176 18.7.2 Construction sans variables locales................................................................................................ 176 18.7.3 Construction avec variables locales................................................................................................. 177 6

18.8 CONCLUSION............................................................................................................................................ 177 19. LA NORME ISO 7816 ................................................................................................................................ 178 19.1 SPCIFICITS UTILES DE LA NORME ISO 7816.......................................................................................... 178 19.1.1 Les commandes ISO 7816 ................................................................................................................ 178 19.1.2 Le protocole dchange dinformations ........................................................................................... 179 19.2 LES LIAISONS SRIE ASYNCHRONES ......................................................................................................... 180 19.2.1 Le start-bit........................................................................................................................................ 181 19.2.2 Les bits de donne ............................................................................................................................ 181 19.2.3 Le bit de parit ................................................................................................................................ 181 19.2.4 Le stop-bit ........................................................................................................................................ 181 19.2.5 Vitesse et dbit.................................................................................................................................. 182 19.3 ACQUISITION DES BITS ............................................................................................................................. 182 19.4 CARACTRISTIQUE DES CARTES STANDARD ....................................................................................... 183 19.5 CRATION ET INITIALISATION DU PROJET ................................................................................................. 183 19.6 LA BASE DE TEMPS ................................................................................................................................... 185 19.7 RCEPTION DUN OCTET........................................................................................................................... 186 19.8 LMISSION DUN CARACTRE ................................................................................................................. 188 19.9 INITIALISATION ........................................................................................................................................ 190 19.10 ENVOI DE LATR ................................................................................................................................... 191 19.11 LENVOI DU STATUS ............................................................................................................................... 192 19.12 RCEPTION DE LA CLASSE ...................................................................................................................... 193 19.13 RCEPTION DE INS, P1, P2, ET LEN...................................................................................................... 193 19.14 CONTRLE DE LINSTRUCTION REUE.................................................................................................... 194 19.15 TRAITEMENT DUNE INSTRUCTION ......................................................................................................... 195 19.16 LES VARIABLES ...................................................................................................................................... 195 19.17 CONCLUSION.......................................................................................................................................... 196 ANNEXE1 : QUESTIONS FRQUEMMENT POSES (F.A.Q.)............................................................... 197 A1.1 JE NARRIVE PAS DITER MON FICHIER SOURCE ................................................................................... 197 A1.2 JE TROUVE QUE 8 SOUS-PROGRAMMES, CEST PEU .................................................................................. 197 A1.3 JE NUTILISE QUE 8 IMBRICATIONS, ET POURTANT MON PROGRAMME PLANTE........................................ 197 A1.4 MON PROGRAMME SEMBLE NE JAMAIS SORTIR DES INTERRUPTIONS ....................................................... 197 A1.5 JE NARRIVE PAS AJOUTER UN NUD MON PROJET ............................................................................ 198 A1.6 JE NARRIVE PAS UTILISER LE SIMULATEUR, LES OPTIONS SONT EN GRIS............................................ 198 A1.7 JE REOIS UN MESSAGE DERREUR EOF AVANT INSTRUCTION END....................................................... 198 A1.8 COMMENT DSASSEMBLER UN FICHIER .HEX ? .................................................................................. 198 A1.9 UTILISATION DES MINUSCULES ET DES MAJUSCULES............................................................................... 198 A1.10 LE CHOIX DUN PROGRAMMATEUR........................................................................................................ 199 A1.11 JAI UNE ERREUR DE STACK ............................................................................................................. 199 B. UTILISATION DU PRSENT DOCUMENT........................................................................................... 200

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. 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 de faire profiter le plus grand nombre de votre travail. 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 mail 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 ! Jai utilis personnellement la version 5.20 de MPLAB. Si vous utilisez une autre version, vous trouverez peut-tre des diffrences. Je ne doute pas que vous arriviez surmonter ces petites difficults. Notez que lors de cette rvision, jutilise maintenant la version 5.50, et ceci sans aucune modification visible au niveau de linterface utilisateur.

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 une plus grande importance que le 2. En ralit, chaque chiffre, que lon peut appeler DIGIT, une valeur qui dpend de son RANG . Quel est ce rapport ? Il sagit tout simplement de llvation de la BASE utilise lev la puissance de son RANG . Cela a lair complexe crire, mais est trs simple comprendre. Quand vous avez compris ceci, vous comprendrez automatiquement nimporte quel systme de numrotation. Reprenons, par exemple notre nombre 502. Que signifie-t-il ? 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. 2.2 Le systme binaire 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, vous avez suivi.
9

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 : B10010101 = 1*2 + 0*21 + 1*2 + 0*23 + 1* 24 + 0*25 + 0*26 + 1*27 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 : B 10010101 = 1+4+16+128 = 149 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. On procde simplement de la manire suivante (il y en a dautres) : Quel est le plus grand exposant de 2 contenu dans 149 ? Rponse 7 (27 = 128) On sait donc que le bit7 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 verront 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. 2.3 Le systme hexadcimal 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.

10

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 : Tableau de conversion des diffrents quartet (un demi-octet) Binaire B0000 B0001 B0010 B0011 B0100 B0101 B0110 B0111 B1000 B1001 B1010 B1011 B1100 B1101 B1110 B1111 Hexadcimal 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF Dcimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

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.

11

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. Petit exemple : Que vaut B1011 + B 0110 ? Et bien, on procde exactement de la mme faon que pour une opration en dcimal. B1011 + B1110 -------------On additionne les chiffres de droite, et on obtient 1+0 = 1 On crit 1 On additionne 1 + 1 , et on obtient 10 (2 nexiste pas en binaire). On crit 0 et on reporte 1 On additionne 0+1+le report et on obtient 10. On crit 0 et on reporte 1 On additionne 1+1+le report et on obtient 11. On crit 1 et on reporte 1 Reste le report que lon crit, soit 1. La rponse est donc B11001, soit 25. 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. 2.5 Les nombres signs 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. Pour rendre un nombre ngatif, il faut procder en 2 tapes. On inverse la totalit du nombre. On ajoute 1 On obtient alors ce quon appelle le COMPLEMENT A DEUX du nombre. Exemple : soit le nombre 5 : B00000101 Comment crire 5 ? on inverse tous les bits (complment 1) on ajoute 1 (complment 2) 5 =
12

B11111010 B11111011

Pour faire la conversion inverse, on procde de faon identique. On inverse tous les bits On ajoute 1 B00000100 B00000101

Et on retrouve notre 5 de dpart, ce qui est logique, vu que (-5) = 5. 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. Remarquez que les oprations continuent de fonctionner. Prenons 3 + 5 B 11111101 (-3) + B 00000101 (5) ----------------------------= B100000010 (2) Et la, me direz vous, a ne fait pas 2 ? Et bien si, regardez bien, il y a 9 bits , or le processeur nen gre que 8. Le 9me est donc tomb dans un bit spcial que nous verront plus tard. Dans le registre du processeur, il reste donc les 8 bits de droite, soit 2, qui est bien gal (3 )+ 5. 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. Sachez que les nombres signifient uniquement ce que le concepteur du programme a dcid quils reprsentent. Sil travaille avec des nombres signs ou non, ou si cet octet reprsente tout autre chose. La seule chose qui importe cest de respecter les conventions que vous vous tes fixes lors de la cration de cet octet. Cest donc vous de dcider de quoi vous avez besoin pour tel type de donnes. 2.6 Les oprations boolennes. 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. Exemple : NOT B10001111 donne B01110000 .
13

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. 2.6.2 La fonction ET ou AND Appele galement multiplication bit bit, o AND et souvent note & 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). Premire ligne : 0 AND 0 = 0. Ce type de tableau sappelle table de vrit Bit1 Bit2 AND 0 0 0 0 1 0 1 0 0 1 1 1 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 : Soit B11001100 AND B 11110000 donne B11000000 A quoi sert cette instruction ? Et bien, elle est utilise pour MASQUER des bits qui ne nous intressent pas. Prenez lexemple ci-dessus : Le 2me octet contient 4 bits 1 et 4 bits 0. Regardez le rsultat obtenu : Les 4 premiers bits de loctet 1 sont conservs (1100), lemplacement des 4 autres nous trouvons des 0. 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. La table de vrit suivante explique le fonctionnement de cette fonction.
14

Bit1 Bit2 0 0 0 1 1 0 1 1

OR 0 1 1 1

Petit exemple B10001000 OR B11000000 donne B11001000 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. 2.6.4 La fonction OU EXCLUSIF ou Exclusif OR ou XOR 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. Voici donc la table de vrit. Bit1 Bit2 XOR 0 0 0 0 1 1 1 0 1 1 1 0 Petit exemple : B10001000 XOR B11000000 donne B01001000 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 consacre 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.

15

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. 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. 3.1 Quest-ce quun PIC ? 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 leur propre microcontrleurs. Les PICs sont des composants dits RISC (Reduce Instructions Construction Set), 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 Construction Set). Chez les CISC, on diminue la 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 le temps dun cycle. Si on utilise par exemple un quartz de 4MHz , on obtient donc 1000000 de cycles/seconde, or, comme le PIC excute pratiquement 1 instruction par cycle, hormis les sauts, cela vous donne une puissance de lordre de 1MIPS (1 Million dInstructions Par Seconde).

16

Pensez que les pics peuvent monter 20MHz. Cest donc une vitesse de traitement plus quhonorable. 3.2 Les diffrentes familles des PICs La famille des PICs est subdivise lheure actuelle 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. 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. Notez ds prsent que le datasheet du 16F84 nest quune petite partie de la documentation complte. Pour obtenir la documentation complte, vous ajoutez encore plus de 600 pages en tlchargeant chez Microchip les datasheets pour la gamme Mid-Range. 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. 3.3 Identification dun PIC Pour identifier un PIC, vous utiliserez simplement son numro. Les 2 premiers chiffres indiquent la catgorie du PIC, 16 indique un PIC Mid-Range. Vient ensuite parfois une lettre L : Celle-ci indique que le PIC peut fonctionner avec une plage de tension beaucoup plus tolrante. Ensuite, vous trouvez : 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 dveloppement, et non la version couramment rencontre. 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)
17

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. 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. 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. Une version 10 peut donc toujours tre employe sans problme en lieu et place dune 04. Pas linverse, naturellement. Ceci par opposition aux composants DYNAMIQUES (comme les microprocesseurs de votre ordinateur), donc la frquence dhorloge doit rester dans des limites prcises. Nessayez donc pas de faire tourner votre PIII/500 166MHz, car cest un composant dynamique. 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 . 3.4 Organisation du 16F84 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. 3.4.1 La mmoire programme 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. 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.

18

3.4.2 La mmoire eeprom La mmoire eeprom (Electrical Erasable Programmable Read Only Memory), est constitue de 64 octets que vous pouvez lire et crire depuis votre programme. Ces octets sont conservs aprs une coupure de courant et sont trs utiles pour conserver des paramtres semi-permanents. Leur utilisation implique une procdure spciale que nous verrons par la suite, car ce nest pas de la RAM, mais bien une ROM de type spcial. Il est donc plus rapide de la lire que dy crire. Si vous programmez souvent des eeproms (2416) vous aurez constat dj ce phnomne. 3.4.3 La mmoire Ram La mmoire RAM 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. Malheureusement, lindication mapped in bank 0) vous indique quaccder ces 68 octets depuis la banque 0 ou la banque 1 donne en fait accs la mme case mmoire. Vous voyez dans la partie suprieure le nom de tous les registres spciaux utiliss dans le PIC. Nous les verrons tous, rassurez-vous. Chaque registre provoque un fonctionnement spcial du PIC ou la mise en service dune fonction particulire. Vous remarquerez enfin que certains registres sont identiques dans les 2 banques (FSR par exemple). Cela signifie quy accder depuis la banque 0 ou 1 ne fait pas de diffrence. 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.

19

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. 4.2 Les types dinstructions Vous constaterez donc quil existe 4 type dinstructions : 4.2.1 Les instructions orientes octet 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). Reste 7 bits pour encoder loprande (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.

20

4.2.2 Les instructions orientes bits Ce sont des instructions destines manipuler directement des bits dun registre particulier. Elles sont codes de la manire suivante : 4 bits pour linstruction (dans lespace rest libre par les instructions prcdentes) 3 bits pour indiquer le numro du bit manipuler (bit 0 7 possible), et de nouveau : 7 bits pour indiquer loprande.

4.2.3 Les instructions gnrales 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 : Linstruction est code sur 6 bits Elle est suivie dune valeur IMMEDIATE code sur 8 bits (donc de 0 255).

4.2.4 Les sauts et appels de sous-routines Ce sont les instructions qui provoquent une rupture dans la squence de droulement du programme. Elles sont codes de la manires suivante : Les instructions sont cods sur 3 bits La destination code sur 11 bits

Nous pouvons dj en dduire que les sauts ne donnent accs qu 2K de mmoire programme (211). Ceci ne pose aucun problme, le 16F84 ne disposant que de 1K mots de mmoire. Pour coder une adresse de saut lintrieur de la mmoire programme, il faut donc 10 bits (210 = 1024 = 1K). 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 voyez 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.

21

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 La premire colonne indique le MNEMONIQUE et les OPERANDES pour chaque opration. Les mnmoniques sont des mots rservs (donc que vous ne pouvez utiliser que pour cet usage) compris et interprts par le programme dassemblage. 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). Pour ne pas se compliquer la tche, et pour employer la mme dnomination que le commun des mortels, jadopterai le terme assembleur dans les 2 cas, mme si je commets l une faute de langage. Autant rester simple. Le contexte distinguera les deux termes. Sil y a un doute, jemploierais les termes explicites. En ralit, lassembleur est le programme qui permet de raliser lassemblage. 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 utiliseront 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). La premire colonne est rserve pour les tiquettes (repres) Vous disposez galement de la possibilit dinsrer un ou plusieurs espace(s) ou tabulation(s) de chaque ct de la virgule. 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 :
Ma_ligne MOVF STATUS,W ; Ceci est une tiquette ; charge le registre status dans le registre de travail

22

La seconde colonne du tableau donne un bref descriptif de linstruction. La troisime colonne donne le nombre de cycles ncessaires pour excuter 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. Rassurez-vous, ces techniques appartiennent maintenant au moyen-ge de linformatique. Tout au plus pouvez-vous mettre en corrlation les valeurs prsentes ici avec les valeurs du tableau 9-1 titre ducatif. Sinon, oubliez cette colonne. 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 propres aux ports dentres/sortie (I/O). Nous y reviendront au moment de la mise en uvre des PORTS. La note 2 indique quune modification dun timer remet zro son prdiviseur. Nous y reviendront 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. 4.4 Les indicateurs dtat Ces indicateurs sont indispensables pour la programmation. Il est donc absolument ncessaire davoir compris leur fonctionnement (du moins pour Z et C).

23

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. 4.4.1 Lindicateur dtat Z Cest lindicateur Zro, il fonctionne de la manire suivante : Si le rsultat dune opration POUR LEQUEL IL EST AFFECTE, donne un rsultat gal 0, le flag Zro passe 1. Donc, ne vous mlangez pas les pinceaux . Dire si Z = 1 correspond dire si rsultat = 0 . Le tableau 9-2, colonne 5 vous indique les instructions qui modifient Z. 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. 4.4.2 Lindicateur dtat C Cest lindicateur pour Carry (report). Si le rsultat dune opration entrane un dbordement, le bit C sera positionn. Il sagit en fait du 9me bit de lopration. Petit exemple : Si vous ajoutez B11111110 (254) + B00000011 (3) Vous obtenez B100000001, (257) donc 9 bits. 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). Les autres bits du registre dtat seront vu plus loin dans ce petit ouvrage.

24

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. 5.1 Prparation lutilisation La premire chose faire est daller chercher MPLAB 5.50 ou la version actuelle sur le site Microchip : http://www.microchip.com. Suivez les liens tools -> MPLAB IDE . Dcompactez le fichier et procdez son installation. 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. Si par contre, vous avez choisi de crer un rpertoire de travail, copiez-y galement les fichiers P16F84.INC et P16F84a.INC contenus dans le rpertoire dinstallation de MPLAB. Attention, vitez les caractres accentus et autres caractres spciaux pour votre rpertoire ou sous-rpertoire. Sans a, MPLAB vous affichera parfaitement les fichiers, mais vous serez dans limpossibilit de les modifier (le clavier nagira pas). Cest un bug de la version 5.20, que vous ne rencontrerez peut-tre pas dans les versions futures. Evitez donc un rpertoire leons et prfrez-lui lessons . 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.

25

5.2 Cration de notre premier projet Voil, maintenant, allez dans le menu dmarrer et lancez MPLAB. Aprs quelques secondes, vous vous trouvez devant un cran vide avec menus et barre doutils. Allez dans le menu project et slectionnez new project . MPLAB travaille en effet avec la notion de projets. Slectionnez le disque dur et le rpertoire dans lequel se trouvent vos data (par exemple DATAPIC), et entrez Essai1 dans la case File name . Une fentre intitule Edit project souvre alors. Cest dans cette fentre que vous allez dfinir les fichiers utiliss dans votre projet et les modalits de fonctionnement. Dans la premire case, se trouve le nom du fichier .hex que MPLAB gnrera pour vous. Par dfaut, cest le nom de votre projet avec lextension .hex. Pour nous y retrouver, nous le laisserons tel quel. Ce sera donc Essai1.hex Dans la seconde case Include path se trouve le chemin des fichiers de dfinition (fichiers include). Comme nous avons copi les fichiers en question (avec lextension .inc) dans notre rpertoire de travail, inutile dindiquer quoi que ce soit. Ne pas non plus remplir les chemins des librairies (Library) et des fichiers de liens (Link). Nous nen aurons pas besoin pour le moment. De plus, rappelez-vous que si les fichiers sont dans votre rpertoire de travail, vous nindiquez rien. Dans le cas contraire, il vous suffit dindiquer le chemin pour y accder (par dfaut c:\temp\program files\MPLAB). Vous trouvez ensuite une case intitule development mode . Ceci vous permet de choisir avec quel PIC vous allez travailler. Cliquez change , et une fentre souvre dans laquelle vous pouvez choisir le PIC pour chaque catgorie de matriel (programmateur, simulateur etc.). Laissez la case none coche et choisissez le processeur 16F84 dans le menu droulant. Une fois fait, cliquez OK, puis cliquez de nouveau OK sur la fentre derreur qui vous indique que vous navez pas encore de fichier .hex pour ce projet. Laissez la case suivante slectionne sur Microchip , puisque nous allons utiliser les outils Microchip.

26

Vient ensuite une case dans laquelle se trouvent les nuds (NODE) utiliss dans votre projet, cest dire les fichiers utiliss. Cliquez sur le seul nud prsent actuellement, qui est le nud du fichier .hex Essai1 [.hex] . La case Node properties (proprits du nud) devient alors active. Cest grce cette option que vous allez dcider la manire dont va tre construit votre fichier .hex. Cliquez dessus. Apparat alors une fentre qui contient les diffrents paramtres qui seront utiliss. Vous apprendrez par la suite personnaliser le project suivant vos gots. Sachez que vous pouvez dcider quel langage utiliser (nous utiliserons MPASM qui est lassembleur par dfaut, et choisir les diffrents niveaux dalerte. Nous y reviendrons si ncessaire. La case Default radix est dune extrme importance. Rappelez-vous les systmes de numrotations. Cette case indique de quelle manire lassembleur doit interprter un nombre lorsquil ny a pas de prfixe.

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 DEC . Attention, MPLAB semble ignorer cette consigne dans certains cas particuliers. Je vous conseille donc de TOUJOURS prciser un prfixe pour vos nombres dans votre programme. De plus, a vite les erreurs en cas de partage de fichier .asm . Dans la case Command line ou ligne de commande, vous voyez la syntaxe que vous devriez excuter si vous lanciez lassemblage par MPASM sans passer par MPLAB. Ne vous en proccupez pas et cliquez OK pour fermer cette fentre. Nous allons maintenant dire MPLAB que nous voulons utiliser le fichier Essai1.asm pour crer notre programme. Cliquons donc sur Add node (ajouter un nud). Choisissez votre fichier essai1.asm dans lexplorateur qui souvre, puis OK. Vous constaterez que si vous cliquez sur ce nud, seule la case Delete Node (effacer) est active, car il ny a rien diter sur ce nud. Cliquez sur OK dans le haut de la fentre, votre projet est cr.

27

Mais, allez-vous me dire, il ny a toujours rien lcran ! En effet, mais MPLAB assemblera les fichiers contenus dans les nuds, PAS les fichiers affichs lcran. Vous pouvez donc 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. Pour visualiser votre fichier essai1.asm , ouvrez-le donc laide du menu File>open . Et voici votre fichier de dpart ouvert. Mettez-le la taille approprie en lui faisant occuper la moiti gauche de lcran.

Nous allons maintenant examiner ce fichier dun peu plus prs.

28

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 guidez au travers du fichier. Najoutez donc pas de lignes pour linstant, pour garder la correspondance correcte avec ce texte. Si vous narrivez pas effectuer des modifications dans vote fichier, et que votre clavier semble inactif, cest que vous avez utilis un caractre tendu dans le nom de votre fichier. Rappelez-vous que MPLAB est allergique certains caractres, comme le . 6.1 Les commentaires De la ligne 1 la ligne 31 vous voyez un grand cadre. Si vous remarquez attentivement le premier caractre de chaque ligne, vous verrez le symbole ; . Tout ce qui suit tant considr comme zone de commentaire, vous pouvez y mettre tout ce que vous voudrez. 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 joints avec cette leon le fichier essai1.asm , qui reprend le fichier tel quil sera la fin de cette leon. 6.2 Les directives A la ligne 34, nous trouvons une DIRECTIVE destine MPASM pour 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. Au contraire, les INSTRUCTIONS seront traduites en OPCODE et charges dans le PIC. Il est donc impratif de bien faire la distinction. 6.3 les fichiers include La ligne 35 signale lassembleur que les ASSIGNATIONS sont dans le fichier P16F84.inc. Que contient ce fichier ? Et bien tout simplement la valeur de toutes les CONSTANTES que nous allons utiliser.

29

Pour voir ce quil contient, allez dans le menu file ->Open , choisissez all files dans le cadre infrieur, et ouvrez p16F84.inc. Une fois dpasse la zone de commentaires, vous verrez des lignes du style :
FSR EQU H'0004'

Cette ligne signifie tout simplement que FSR est EGAL 0x0004. 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. H0004 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. 6.4 La directive _CONFIG 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 programmateur attentif qui a utilis cette directive, vous naurez nul besoin de dfinir ces paramtres au moment de la programmation. Le logiciel du programmateur ira chercher ces valeurs dans le fichier luimme. Malheureusement, on trouve nombre de personnes qui pensent que cette directive, commentaires, et autres facilits sont rserver aux dbutants et ne les utilisent pas. Grossire erreur. 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) : On remplacera donc simplement la ligne :
__CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC _CP_ON & _WDT_ON & _PWRTE_ON & _HS_OSC

par
__CONFIG

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

6.5 Les assignations A la ligne 57 et 62, vous trouverez des ASSIGNATIONS personnelles qui fonctionnent selon le mme principe que dans le fichier .inc . A quoi cela sert-il ? Et bien faciliter la MAINTENANCE de votre programme. Il est en effet plus simple de retenir dans votre programme la valeur MASQUE que de manipuler la valeur 0x5B. Les assignations se comportent comme une simple substitution. Au moment de lassemblage, chaque fois que lassembleur va trouver une assignation, il la remplacera automatiquement par sa valeur. 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 :
mavaleur EQU0x05

6.6 Les dfinitions Descendons encore un peu. Nous dcouvrons, lignes 72 74 des exemples de DEFINE. Sachez que les define fonctionnent comme des ASSIGNATIONS. A ceci prs que nous rserverons les assignations pour les valeurs, et les dfinitions pour remplacer un texte plus complexe. 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 :
#DEFINE monbit PORTA,1

Lutilisation de cette macro seffectue tout simplement en utilisant son nom dans le programme. Par exemple :
bsf monbit ; mettre monbit 1

Sera traduit par MPLAB comme :


bsfPORTA,1 ; mettre monbit 1

31

6.7 Les macros Plus bas, lignes 82 85, nous trouvons une MACRO.
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 raccourci 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). 6.8 La zone des variables 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
CBLOCK 0x00C ; dbut de la zone variables

Ensuite, vous pouvez utiliser 68 emplacements mmoire, qui rpondront la syntaxe suivante : nom de la variable suivi du signe : suivi de la taille utilise. Par exemple :
w_temp :1 ; Zone de 1 byte montableau : 8 ; zone de 8 bytes

32

Ensuite, vous devrez prciser la fin de la zone en cours laide de la directive :


ENDC ; Fin de la zone

6.9 Les tiquettes 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. Lassembleur les remplacera par ladresse du programme lendroit o elles sont positionnes. Ceci vous vite de devoir calculer les emplacements programme. Nous en verrons plus loin le principe. 6.10 La directive ORG 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 ligne103 comment tout ceci fonctionne :
org 0x000 goto init ; Adresse de dpart aprs reset ; Adresse 0: initialiser

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

33

7. Ralisation dun programme


7.1 Cration de notre premier 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.
goto start ; Adresse 0: dmarrer

Descendez ensuite en ligne 225, vous trouverez l notre tiquette start, cest donc l que notre programme va sauter. Effacez ensuite la ligne
clrwdt ; effacer watch dog

Rassurez-vous, nous verrons tout ceci par la suite. Il reste donc une instruction que nous avons dj vue, linstruction goto .
goto start ; boucler

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 (rappelezvous, 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 mavariable ; effacer mavariable

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 :
34

boucle 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. Pour terminer, remplacez
goto start

par
goto boucle

Le programme doit toujours se terminer par la DIRECTIVE END Vous devriez donc vous retrouver avec ceci :
start clrf boucle incf goto END mavariable ; effacer mavariable

mavariable,f ; incrmenter mavariable boucle ; boucler ; directive fin de programme

7.2 Lassemblage dun 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 avec la fentre suivante :
Building ESSAI1.HEX... Compiling ESSAI1.ASM: Command line: "C:\PROGRA~1\MPLAB\MPASMWIN.EXE /e+ /l+ /x- /c+ /rdec /p16F84 /q D:\DOCUME~1\LESSONS\DATAPIC\ESSAI1.ASM" Message[302] D:\DOCUME~1\LESSONS\DATAPIC\ESSAI1.ASM 198 : Register in operand not in bank 0. Ensure that bank bits are correct. Message[302] D:\DOCUME~1\LESSONS\DATAPIC\ESSAI1.ASM 214 : Register in operand not in bank 0. Ensure that bank bits are correct. Error[113] D:\DOCUME~1\LESSONS\DATAPIC\ESSAI1.ASM 226 : Symbol not previously defined (mavariable) Error[113] D:\DOCUME~1\LESSONS\DATAPIC\ESSAI1.ASM 228 : Symbol not previously defined (mavariable) MPLAB is unable to find output file "ESSAI1.HEX". Build failed.

35

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. Nous expliquerons cela plus tard. 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 plus tard. 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
mavariable : 1 ; je dclare ma variable

Vous vous retrouvez donc avec ceci :


CBLOCK 0x00C w_temp :1 status_temp : 1 mavariable : 1 ENDC ; ; ; ; ; dbut de la zone variables Zone de 1 byte zone de 1 byte je dclare ma variable Fin de la zone

Relanons lassemblage en pressant sur F10. Cette fois, tout sest bien pass, lindicateur est rest vert, et, aprs les warnings, nous obtenons la phrase : Build completed successfully : construction acheve avec succs. 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 ? A ce stade, fermez la fentre des messages, et sauvez votre projet par le menu files>save all . Quittez MPLAB et rpondez YES la demande de sauvegarde du projet. Allez voir maintenant dans votre rpertoire de travail, et vous devriez y trouver 7 fichiers gnrs par votre application du type essai1.xxx Remarquez que MPLAB cre des copies de sauvegarde de vos fichiers chaque assemblage. 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.

36

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 : Crer et modifier un projet Assembler votre programme Le faire tourner sur simulateur pour le debugger

8.1 Lancement et paramtrage du simulateur Commencez donc par lancer MPLAB. Ce dernier connat le nom de votre dernier projet (essai1.prj) et vous demande si vous dsirez louvrir. Rpondez yes . 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>. Si vous lancez <F10> et que votre fichier source na pas t modifi depuis le dernier assemblage (on peut aussi utiliser le terme impropre de compilation), vous aurez le message explicite Target is current (le fichier de destination est celui dj cr). Lintrt dun simulateur est de visualiser le fonctionnement du programme, nous allons donc signaler MPLAB ce que nous dsirons observer. Slectionnons dabord la mise en service du simulateur de MPLAB. Allez dans le menu options->development mode . Vous connaissez dj la fentre qui apparat maintenant. Remarquez que seul lditeur est actif.

Slectionnez la case MPLAB-SIM pour activer le simulateur. Vous recevez alors dans la fentre un message davertissement qui vous signale que les transmissions srie ne sont pas simules et que tous les composants ne sont pas repris dans le simulateur.

37

Rassurez-vous. Il y a moyen de simuler quand mme les liaisons srie (en agissant sur quelques registres) pour les Pics qui le grent (16F876) et tous les PICs courants sont dans le simulateur (qui du reste est rgulirement mis jour). Cliquez sur <OK>

Vous obtenez alors un nouveau message qui vous prvient que les informations que vous avez pu entrer dans certains emplacements de votre projet seront perdues. Cliquez galement sur <OK>

A partir de maintenant, le simulateur est activ. Vous pouvez le vrifier en constatant que tous les sous-menus du menu Windows ne sont plus en gris. Nous allons donc faire apparatre lcran les informations surveiller. Slectionnez Windows->Special function registers . Une nouvelle fentre souvre lcran. Rangez-la dans la partie droite de votre cran, afin de ne pas cacher lditeur. 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 Windows->watch windows->new watch windows . Une nouvelle fentre apparat. Dans lemplacement prvu, entrez le nom de votre variable mavariable ou slectionnez la en la choisissant dans la grande fentre.

38

Cliquez ensuite sur properties pour indiquer au simulateur le format daffichage de votre variable. Indiquez, mais cela doit dj tre fait, 8 bits / format hexadcimal.

Pressez ensuite sur <OK>. La variable est maintenant valide. Fermez la fentre Add watch symbol avec le bouton <Close> et rangez la fentre watch_1 sous la fentre special function registers . A cette tape, vous devriez vous retrouver avec lcran suivant :

8.2 Explication des registres fondamentaux 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.

39

8.2.1 Les registres PCL et PCLATH 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) 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 En cas de modification du PCL directement par lutilisateur, comme pour un registre ordinaire, PCL est charg dans PC et complts par les 5 bits du registre PCLATH. Comme le 16F84 ne traite que 1K de mmoire programme, les bits b2, b3 et b4 de PCLATH seront inutiliss ici.

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

40

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. 8.2.3 Le registre STATUS 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. Ce bit est en fait le 9me bit dune opration. Par exemple, si une addition de 2 octets donne une valeur >255 (0xFF), ce bit sera positionn. 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. b2 : Z Zro Ce bit est positionn 1 si le rsultat de la dernire opration vaut 0. Rappelez-vous cependant que ces flags ne sont positionns que pour les instructions qui le prcisent (Status bit affected). Indique quel vnement a entran le dernier arrt du PIC b3 : PD Power down (instruction sleep ou dpassement du temps du watchdog). Nous y reviendrons plus tard. En ralit, vous verrez que PD est surmont dune petite barre qui signifie : actif ltat bas. Donc que 0 = bit valid. Comme je narrive pas avec ce traitement de textes crire ces petites barres, jcrirai les inversions en italique 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). B7 : IRP Indirect RP Permet de dcider quelle banque on adresse dans le cas de ladressage indirect (que nous verrons plus tard). b0 : C Carry (report)

41

8.3 Lancement de la simulation Et voil, vous connaissez maintenant 4 des registres. Nous allons pouvoir commencer simuler notre programme. Slectionner lditeur, par exemple, en cliquant une fois nimporte o dans notre fichier essai1.asm . Pressez <F6>, La ligne
goto start ; Adresse 0: initialiser

Est maintenant slectionne. Vous avez en fait provoqu un Reset de votre programme. Rappelez-vous que cela provoque le dmarrage ladresse 0x00. Vrifions donc : Au dessus de la ligne slectionne, vous trouvez la directive ORG 0x00 qui prcise que la ligne suivante est ladresse 0x00 : premier bon signe. Ensuite, examinons PCL et PCLATH, tous deux 0 : Donc, la prochaine instruction excute sera celle situe ladresse 0x00. Cest tout bon.

Examinons la ligne en question. Elle nous dit que la prochaine instruction, aprs son excution, sera celle situe ladresse start . A ce stade, rappelez-vous que les commandes du simulateur ne sont actives que si la fentre de lditeur est active. Si vous cliquez hors de cette fentre dans les manipulations, noubliez pas de cliquer de nouveau lintrieur avant de lancer une commande. Pressez maintenant <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

Rappelez-vous qu ce stade, linstruction nest pas encore excute. Le PCL vaut maintenant : PCL 33 51 00110011, soit 0x33, ou 51 dcimal, ou encore B00110011

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 : 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. Et oui, une simulation, a reste une simulation. La ligne pointe alors est :
42

incf

mavariable,f ; incrmenter mavariable

Le PCL pointe alors sur : PCL

34

52 00110100

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_1 . Vous voyez votre variable mavariable . Sa valeur est 0x00 (ou H00), et son adresse est 0x0E. Pourquoi ? Examinons la zone de dclaration des variables :
CBLOCK 0x00C w_temp :1 status_temp : 1 mavariable : 1 ; ; ; ; dbut de la zone variables Zone de 1 byte zone de 1 byte je dclare ma variable

La zone commence en 0x0C. La variable w_temp se trouve donc cette adresse et comprend un octet. Status_temp est donc en 0x0D, et mavariable en 0X0E. Cest tout simple. Pressons encore <F7>. La variable mavariable vaut maintenant 0x01 , car lopration dincrmentation a t excute. Vous lavez dj compris, lexcution suivante va vous renvoyer la ligne qui suit ltiquette boucle . Amusez-vous presser plusieurs fois la touche <F7> pour observer lvolution de votre variable. 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. Allez dans le menu Windows et slectionnez modify . Une fentre souvre. Slectionnez lemplacement mmoire modifier (mavariable). Cela peut tre aussi un registre spcial, ou une case programme, etc. Slectionnez radix hexa pour hexadcimal, Data pour memory area pour emplacement RAM et inscrivez FF dans la zone Data/Opcode. Remarquez quavec end adress , vous pouvez galement remplir des tableaux. Pressez write . et rangez cette fentre en dessous des 2 fentres de droite.

Examinez votre variable dans la fentre watch_1 . Elle est maintenant passe 0xFF. Slectionnez lditeur et pressez <F7> jusqu ce que la ligne suivante soit excute :
incf mavariable,f ; incrmenter mavariable

La ligne suivante est maintenant slectionne :


goto boucle ; boucler

Examinons ce qui sest pass :


43

La variable mavariable est passe 0. Logique, car 0xFF + 1 = 0x100. Or, 0x100 ncessite 9 bits (256). On obtiens donc 00 (et on reporte le bit 8). Examinons maintenant le registre STATUS : que constate-t-on. ? Les bits 2, 3 et 4 sont 1, les autres sont 0. Les bit 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. 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 Debug->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. La mme procdure avec <Ctrl><F9> 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
goto boucle ; boucler

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 ou des points darrt conditionnels (trace ou trigger). Vous pouvez galement demander votre programme de dmarrer jusquau point spcifi (run to here). Les diffrents paramtres et rglages se trouvent dans le menu debug . Avec le bouton de droite, donc, choisissez break point . Vous constaterez que votre ligne passe en rouge. 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. Allez dans le menu Debug et slectionnez clear all points . Rpondez OK la question. Le break point est maintenant supprim. La ligne est repasse en noir. Notez que vous pouviez supprimer ce break point en choisissant une seconde fois loption break point avec le bouton de droite (fonctionnement de type toggle ). Un dernier petit essai. Allez dans le menu debug , slectionnez clear all point pour tre sr quil ne reste pas de points darrt dans votre programme Dans le mme menu, choisissez alors trace settings . Une fentre souvre.
44

La premire case vous donne le nom de votre point darrt de type trace Laissez le nom par dfaut. Dans la seconde case, choisissez ladresse de la zone tracer . Indiquez ici votre tiquette boucle . Cliquez sur <Add>. Vous obtenez ceci :

Cliquez ensuite sur la ligne de la grande fentre pour la slectionner. Le menu complmentaire adress is qualifier en gris est alors actif. Slectionnez cette option, puis entrez 50 dans le compteur de passage pass count . Pressez ensuite le bouton <Set>.

Terminez en fermant la fentre avec <Close>. Vous venez de crer un compteur de passages avec arrt automatique. Pressez <F6> puis <F9>. Le programme va alors tourner jusqu ce quil ait excut 50 fois la ligne qui suit ltiquette boucle . Examinez alors votre variable. Elle vaut maintenant 0x32, cest dire 50. Enlevez tous les points darrts (debug->clear all points.). Quittez MPLAB en rpondant Yes la demande de sauvegarde. Vous connaissez maintenant les principales commandes du simulateur (nous en verrons dautres en temps utile).
45

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. 9.1 Linstruction GOTO (aller ) Cette instruction effectue ce quon appelle un saut inconditionnel, encore appel rupture de squence synchrone inconditionnel. Rappelez-vous que linstruction goto contient les 11 bits de lemplacement de destination. Les 2 bits restants sont chargs depuis le registre PCLATH. Rappelez-vous en effet la manire dont est construit le PC dans le cas des sauts. On ne peut sauter qu lintrieur dune mme PAGE de 211, soit 2048 Kmots. 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 ce moment dans la seconde partie. Voici donc en rsum le fonctionnement du goto : Ladresse de saut sur 11 bits est charge dans le PC. Les 2 bits manquants sont chargs depuis PCLATH (b3 et b4), pas pour le 16F84. Le rsultat donne ladresse sur 13 bits (10 bits pour le 16F84) La suite du programme seffectue la nouvelle adresse du PC.

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

46

Exemple Start goto plusloin ; le programme saute linstruction qui suit ltiquette plusloin xxxxxxxx plusloin xxxxxxxx ; instruction excute aprs le saut : le programme se poursuit ici Remarquez que vous pouvez sauter en avant ou en arrire. goto ncessite 2 cycles dhorloge, comme pour tous les sauts 9.2 Linstruction INCF (INCrement File) Cette instruction provoque lincrmentation de lemplacement spcifi (encore appel File). 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. Sauf spcification contraire, d vaut toujours, au choix : - f (la lettre f) : dans ce cas le rsultat est stock dans lemplacement mmoire. - W (la lettre w) : dans ce cas, le rsultat est laiss dans le registre de travail, et le contenu de lemplacement mmoire nest pas modifi. 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. Bit du registre STATUS affect Le seul bit affect par cette opration est le bit Z. 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 (d) avant lexcution valait 0xFF. Exemples incf mavariable , f incf mavariable , w ; le contenu de ma variable est augment de 1 ; le rsultat est stock dans mavariable. ; Le contenu de mavariable est charg dans w et ; augment de 1. W contient donc le contenu de ; mavariable + 1. mavariable nest pas modifie
47

9.3 Linstruction DECF (DECRement File) Decrmente lemplacement spcifi. Le fonctionnement est strictement identique linstruction prcdente. Syntaxe
decf f , d ; (f) 1 -> (d)

Bit du registre STATUS affect Le seul bit affect par cette opration est le bit Z. Si avant linstruction, (d) vaut 1, Z vaudra 1 aprs lexcution (1-1 = 0) Exemples
decf decf mavariable , f mavariable , w ; dcrmente mavariable, rsultat dans mavariable ; prends (mavariable) 1 et place le rsultat dans w

9.4 Linstruction MOVLW (MOVe Literal to W) Cette instruction charge la valeur spcifie (valeur littrale, ou encore valeur immdiate), dans le registre de travail W. Syntaxe
movlw k ; k reprsente une valeur de 0x00 0xFF.

Bit du registre STATUS affect Aucun ( donc mme si vous chargez la valeur 0.) Exemple
movlw 0x25 ; charge 0x25 dans le registre w

9.5 Linstruction MOVF (MOVe File) Charge le contenu de lemplacement spcifi dans la destination Syntaxe
movf f , d ; (f) -> (d)

Bit du registre STATUS affect Une fois de plus, seul le bit Z est affect (si f vaut 0, Z vaut 1). Exemple 1
48

Pour cette instruction, je vais me montrer beaucoup plus explicite. Vous allez comprendre pourquoi
movf mavariable,w ; charge le contenu de mavariable dans w.

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. Si nous excutons linstruction suivante :
movlw mavariable

Lassembleur va traduire en remplaant mavariable par sa VALEUR. Attention, la valeur, ce nest pas le contenu. Lassembleur va donc raliser la substitution suivante :
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). Si nous excutons par contre linstruction suivante :
movf mavariable , w

Lassembleur va traduire galement en remplaant mavariable par sa valeur. Nous obtenons donc :
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.

49

9.6 Linstruction Movwf (MOVe W to File) Permet de sauvegarder le contenu du registre de travail W dans un emplacement mmoire. Syntaxe
movwf f ; (W) -> (f)

Bit du registre STATUS affect Aucun Exemple


movlw 0x50 movwf mavariable ; charge 0x50 dans W : ma variable contient maintenant 0x50.

9.7 Linstruction ADDLW (ADD Literal and W) Cette opration permet dajouter une valeur littrale (adressage immdiat) au contenu du registre de travail W. Syntaxe
addlw k ; (W) + k -> (W)

Bits du registre STATUS affects Z Si le rsultat de lopration vaut 0, Z vaudra 1 C Si le rsultat de lopration est suprieur 0xFF (255) , C vaudra 1 DCSi le rsultat de lopration entrane en report du bit 3 vers le bit 4, DC vaudra 1 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
movlw 253 addlw 4 addlw 255 ; charger 253 en dcimal dans W ; Ajouter 4.W contient 1, Z vaut 0, C vaut 1(dborde) ; ajouter 255 W vaut 0, C vaut 1, Z vaut 1

50

9.8 Linstruction ADDWF (ADD W and F) 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
addwf f , d ; (w) + (f) -> (d)

Bits du registre STATUS affects C, DC, et Z Exemple movlw 12 ; charger 12 dans W movwf mavariable ; mavariable vaut maintenant 12 movlw 25 ; charger 25 dans W addwf mavariable,f ; rsultat : (W) + (mavariable), donc 25+12
; rsultat = 37 sauv dans mavariable (,f).

9.9 Linstruction SUBLW (SUBtract W from Literal) Attention, ici il y a un pige. Linstruction aurait du sappeler SUBWL. En effet, on soustrait W de la valeur littrale, et pas linverse. Syntaxe
sublw k ; k (W) -> (W)

Bits du registre STATUS affects 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). Si le rsultat est positif, donc, pas de dbordement : C =1.S il y a dbordement, C devient 0. Ceci est logique, et sexplique en faisant une soustraction manuelle. Le bit C reprsente le 9me 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. La formule de la soustraction est donc : k prcd dun neuvime bit 1 contenu de W = rsultat sur 8 bits dans W avec 9me bit dans C.

51

Exemple 1
movlw 0x01 sublw 0x02 ; ; ; ; charger 0x01 dans W soustraire W de 2 rsultat : 2 (W) = 2-1 = 1 Z = 0, C = 1, donc rsultat positif

Effectuons cette opration manuellement : C b7 b6 b5 b4 b3 b2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 = 1 0 0 0 0 0 0

b1 1 01 0

b0 010 1 1

Dec 2 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 emprunter 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
movlw sublw 0x02 0x02 ; charger 0x02 dans W ; soustraire 2 (w) = 2 2 = 0 ; Z = 1 , C = 1 : rsultat nul

C 1 0 1

b7 0 0 0

b6 0 0 0

b5 0 0 0

b4 0 0 0

b3 0 0 0

b2 0 0 0

b1 1 1 0

b0 0 0 0

Dec 2 2 0

On procde toujours de la mme manire. Exemple 3


movlw sublw 0x03 0x02 ; charger 0x03 dans W ; soustraire 2 (W) = 2 3 = -1 ; Z = 0, C = 0, rsultat ngatif

C 1 01 0

b7 010 01 1

b6 010 01 1

b5 010 01 1

b4 010 01 1

b3 010 01 1

b2 010 01 1

b1 110 11 1

b0 010 1 1

Dec 2 3 -1

Procdons de la mme manire, et nous obtenons B11111111, avec le bit C 0. Et l, me dites-vous, B11111111, cest FF, pas 1. Et bien, rappelez-vous ceci : Vous DEVEZ lire le bit C pour interprter le rsultat de votre soustraction. Comme ce dernier vaut 0, vous tes AVERTIS que le rsultat de lopration est ngatif. Or, comment savoir la valeur absolue dun nombre ngatif ? En prenant son complment 2. Rappelez-vous :
52

Complment 1 de B11111111 = B00000000 (on inverse tous les bits) Complment 2 = complment 1 + 1, donc B00000001. Donc, le complment 2 de 0xFF vaut 0x01. C.Q.F.D. 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. 9.10 Linstruction SUBWF (SUBtract W from F) Nous restons dans les soustractions, mais, cette fois, au lieu dun adressage immdiat, nous avons un ADRESSAGE DIRECT. Syntaxe
subwf f , d ; (f) (W) -> (d)

Bits du registre STATUS affects C , DC , Z Exemple


movlw movwf movlw subwf movwf 0x20 mavariable 0x1F mavariable,w ; ; ; ; ; ; autrevariable ; charger 0x20 dans w mettre w dans (mavariable) (0x20) charger 0x1F dans w (mavariable) - (w) -> (w) 0x20 0x1F = 0x01 rsultat dans w, C=1, Z=0 sauver 0x01 dans une autre variable

9.11 Linstruction ANDLW (AND Literal with W) Cette instruction effectue une opration AND BIT A BIT entre le contenu de W et la valeur littrale qui suit. Syntaxe
andlw k ; avec k = octet : (w) & k -> (w)

53

Bit du registre STATUS affect Z Exemple


movlw andlw B11001101 ; charger w B11110000 ; effectuer un and (&)

b7 1 And 1 = 1

b6 1 1 1

b5 0 1 0

b4 0 1 0

b3 1 0 0

b2 1 0 0

b1 0 0 0

b0 1 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. 9.12 Linstruction ANDWF (AND W with F) Maintenant, vous devriez avoir bien compris. De nouveau la mme opration, mais en ADRESSAGE DIRECT. Je vais donc acclrer les explications. Syntaxe
andwf f , d ; (f) AND (w) -> (d)

Bit du registre STATUS affect Z Exemple


movlw movwf movlw andwf 0xC8 mavariable 0xF0 mavariable,f ; ; ; ; charger 0XC8 dans w sauver dans mavariable charger le masque (mavariable) = 0xC0 (on a limin le quartet faible)

9.13 Linstruction IORLW (Inclusive OR Literal with W) 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.

54

Syntaxe
iorlw k ; (w) OR k -> (w)

Bit du registre STATUS affect Z Exemple


movlw iorlw 0xC3 0x0F ; charger 0xC3 dans W ; FORCER les bits 0 3 ; rsultat ; (w) = 0xCF

b7 1 OR 0 = 1

b6 1 0 1

b5 0 0 0

b4 0 0 0

b3 0 1 1

b2 0 1 1

b1 1 1 1

b0 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). 9.14 Linstruction IORWF (Inclusive OR W with File) Effectue un OR entre (w) et lemplacement spcifi. Cest donc une instruction en ADRESSAGE DIRECT. Je ne donnerai pas dexemple, vous devriez avoir compris. Syntaxe
iorwf f , d ; (w) OR (f) -> (d)

Bit du registre STATUS affect Z 9.15 Linstruction XORLW (eXclusive OR Literal with W) Par opposition au ou inclusif, voici maintenant le OU EXCLUSIF. Sa table de vrit est la mme que le ou inclusif, except que lorsque les 2 bits sont 1, le rsultat est 0. 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.
55

Syntaxe
xorlw k ; (w) xor k -> (w)

Bit du registre STATUS affect Z Exemple


movlw xorlw B11000101 B00001111 ; ; ; ; charger W xor avec la valeur rsultat : B 11001010 les 4 bits de poids faible ont t inverss

xor =

b7 1 0 1

b6 1 0 1

B5 0 0 0

B4 0 0 0

b3 0 1 1

b2 1 1 0

b1 0 1 1

b0 1 1 0

Remarquez que tous les bits de loctet initial ont t inverss par chaque bit de la seconde oprande qui taient 1. 9.16 Linstruction XORWF (eXclusive OR W with F) Cest exactement la mme opration que XORLW, mais en ADRESSAGE DIRECT. Syntaxe
xorwf f , d ; (w) xor (f) -> (d)

Bit du registre STATUS affect Z 9.17 Linstruction BSF (Bit Set F) Cest une instruction qui permet tout simplement de forcer directement un bit dun emplacement mmoire 1 Syntaxe
bsff , b ; le bit n b est positionn dans la case mmoire (f) ; b est videmment compris entre 0 et 7

Bit du registre STATUS affect Aucun


56

Exemples
bsfSTATUS , C bsfmavariable , 2 ; positionne le bit C 1 dans le registre STATUS ; positionne bit 2 de (mavariable) 1

9.18 Linstruction BCF (Bit Clear F) Cest une instruction qui permet tout simplement de forcer directement un bit dun emplacement mmoire 0 Syntaxe
bcff , b ; le bit n b est mis 0 dans la case mmoire (f) ; b est videmment compris entre 0 et 7

Bit du registre STATUS affect Aucun Exemples


bcfSTATUS , C ; positionne le bit C 0 dans le registre STATUS bcfmavariable , 2 ; positionne b2 de (mavariable) 0

9.19 Linstruction RLF ( Rotate Left through Carry) Rotation vers la gauche en utilisant le carry. Les oprations de dcalage sont des oprations trs souvent utilises. Les PICs ont la particularit de ne possder que des oprations de ROTATION. Vous allez voir quavec ces oprations, on peut trs facilement raliser des dcalages. Lopration de rotation effectue lopration suivante : Le bit de carry C est mmoris. Ensuite chaque bit de loctet est dplac vers la gauche. Lancien bit 7 sort de loctet par la gauche, et devient le nouveau carry. Le nouveau bit 0 devient lancien carry. Il sagit donc dune rotation sur 9 bits. Syntaxe
rlff , d ; (f) rotation gauche avec carry-> (d)

Bit du registre STATUS affect C Exemple1 Un petit exemple vaut mieux quun long discours.
57

bsf movlw movwf rlf

STATUS,C B00010111 mavariable mavariable,f

; ; ; ;

positionne le carry 1 charge la valeur dans w initialise mavariable rotation vers la gauche

f rlf

C 1 0

b7 0 0

b6 0 0

b5 0 1

b4 1 0

b3 0 1

b2 1 1

b1 1 1

b0 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
bcf movlw movwf rlf STATUS,C b00010111 mavariable mavariable,f ; ; ; ; positionne le carry 0 charge la valeur dans w initialise mavariable rotation vers la gauche

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). Prenons B00010111 , soit 23 en dcimal. Dcalons-le, nous obtenons B00101110, soit 46. Nous avons donc effectu une multiplication par 2. Retenez ceci, cela vous sera trs utile par la suite. 9.20 Linstruction RRF ( Rotate Right through Carry) Rotation vers la droite en utilisant le carry Lopration de rotation vers la droite effectue lopration suivante : Le bit de carry C est mmoris. Ensuite chaque bit de loctet est dplac vers la droite. Lancien bit 0 sort de loctet par la droite, et devient le nouveau carry. Lancien Carry devient le nouveau bit7. Il sagit donc galement dune rotation sur 9 bits. Syntaxe
rrf f , d ; (f) rotation droite avec carry-> (d)

Bit du registre STATUS affect C

58

Exemple1
bsf movlw movwf rrf STATUS,C ; B00010111 ; mavariable ; mavariable,f ; positionne le carry 1 charge la valeur dans w initialise mavariable rotation vers la droite

f rrf

b7 0 1

b6 0 0

b5 0 0

B4 1 0

b3 0 1

b2 1 0

b1 1 1

b0 1 1

C 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
bcf movlw movwf rrf STATUS,C b00010111 mavariable mavariable,f ; ; ; ; positionne le carry 0 charge la valeur dans w initialise mavariable rotation vers la droite

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. 9.21 Linstruction BTFSC (Bit Test F, Skip if Clear) 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 . En effet, il ny aura saut que si la condition est remplie. 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
btfsc f, b sinon ; on teste le bit b de la mmoire (f). ; si ce bit vaut 0, on saute linstruction suivante,

; on excute linstruction suivante. Instruction excute si faux; si le bit vaut 0, ne sera pas excute (skip) Poursuite du programme ; le programme continue ici

59

Bit du registre STATUS affect Aucun Exemple1 Voici un exemple dans lequel on doit excuter une seule instruction supplmentaire si le bit vaut 1.
btfsc STATUS,C bsfmavariable,2 xxxx ; tester si le bit C du registre STATUS vaut 0 ; non (C=1), alors bit 2 de mavariable mis 1 ; la suite du programme est ici dans les 2 cas

Exemple 2 Que faire si les traitements diffrent de plus dune instruction ? Et bien, on combine les sauts conditionnels avec les saut inconditionnels (par exemple goto).
movlw subwf btfsc goto xxxx 0x12 mavariable,f STATUS,C positif ; ; ; ; ; charger 12 dans le registre de travail on soustrait 0x12 de mavariable on teste si le rsultat est ngatif (C=0) non, alors au saute au traitement des positifs on poursuit ici si le rsultat est ngatif

Ces procdures sont les mmes pour tous les sauts inconditionnels, je ne les dtaillerai donc pas avec autant dexplications. 9.22 Linstruction BTFSS (Bit Test F, Skip if Set) Traduit littralement, cela donne : Teste le bit de lemplacement mmoire et saute sil vaut 1. Toutes les remarques de linstruction BTFSC restent valables. Syntaxe
btfsc f, b xxxx xxxx ; ; ; ; ; on si on si Le teste le bit b de la mmoire (f). ce bit vaut 1, on saute linstruction suivante, sinon excute linstruction suivante. le bit vaut 1, ne sera pas excute (skip) programme continue ici

Bit du registre STATUS affect Aucun Exemple


btfss STATUS,C bsfmavariable,2 xxxx ; tester si le bit C du registre STATUS vaut 1 ; non (C=0), alors bit 2 de mavariable mis 1 ; la suite du programme est ici dans les 2 cas

60

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
decfsz f, d ; (f) 1 -> (d). Saut si (d) = 0

Bit du registre STATUS affect Aucun Exemple1


; ; ; boucle ; addwf mavariable , f ; decfsz compteur , f ; goto boucle ; movf mavariable , w ; movlw 3 movwf compteur movlw 0x5 charger 3 dans w initialiser compteur charger 5 dans w tiquette ajouter 5 ma variable dcrmenter compteur et tester sa valeur si compteur pas 0, on boucle on charge la valeur obtenue dans w

Comment crit-on ce type de programme ? Et bien tout simplement de la manire suivante : on initialise les compteur de boucles. on place une tiquette de dbut de boucle on crit les instructions qui doivent sexcuter plusieurs fois linstruction decfsz permet de dterminer la fin des boucles linstruction goto permet de localiser le dbut de la boucle.

ATTENTION - Si vous aviez mis


decfsz compteur , w ; dcrmenter compteur et tester sa valeur

la boucle naurait jamais de fin, car la variable compteur ne serait jamais modifie. - Si vous placez 0 dans le compteur de boucles, la boucle sera excute 256 fois. Si vous ne dsirez pas que la boucle soit excute dans ce cas, vous devez ajouter un test AVANT lexcution de la premire boucle, comme dans lexemple suivant :

61

Exemple 2
; ; ; boucle ; addwf mavariable , f ; decfsz compteur , f ; goto boucle ; suite ; movf mavariable , w ; movf compteur,f btfsc STATUS , Z goto suite permet de positionner Z sauter si Z = 0, donc si compteur >0 compteur = 0, ne pas traiter la boucle tiquette de dbut de boucle ajouter 5 ma variable dcrmenter compteur et tester sa valeur si compteur pas 0, on boucle on saute directement ici si compteur = 0 on charge la valeur obtenue dans w

9.24 Linstruction INCFSZ (INCrement F, Skip if Zero) 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
incfsz f , d ; (f) + 1 -> (d) : saut si (d) = 0

Bit du registre STATUS affect Aucun 9.25 Linstruction SWAPF (SWAP nibbles in F) 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
swapf f , d ; inversion des b0/b3 de (f) avec b4/b7 -> (d)

Bit du registre STATUS affect Aucun : cette particularit nous sera trs utile lorsque nous verrons les interruptions. Exemple
movlw 0xC5 ; charger 0xC5 dans w movwf mavariable ; placer dans mavariable swapf mavariable , f ; (mavariable) = 0x5C

9.26 Linstruction CALL (CALL subroutine) Cette opration effectue un saut inconditionnel vers un sous-programme. Voyons ce quest un sous-programme. Et bien, il sagit tout simplement dune partie de programme qui peut tre appel depuis plusieurs endroits du programme dit principal .

62

Le point de dpart est mmoris automatiquement, de sorte quaprs lexcution du sous-programme, le programme continue depuis lendroit o il tait arriv. Cela parat un peu ardu, mais cest extrmement simple. Voyez les exemples dans la description de linstruction RETURN. Syntaxe
call etiquette : appel de la sous-routine ladresse etiquette.

Mcanisme Lors de lexcution de linstruction, ladresse de linstruction suivante est sauvegarde sur le sommet dune pile (exactement comme une pile dassiettes). Lorsque la sous-routine est termine, ladresse sauvegarde est retire de la pile et place dans le PC. Le programme poursuit alors depuis lendroit do il tait parti. Notez que si le sous-programme (ou sous-routine) appelle lui-mme un autre sous programme, ladresse sera galement sauve au dessus de la pile. 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 sousprogramme, mais dans le nombre dimbrications (sous-programme qui en appelle un autre qui en appelle un autre) etc. Bit du registre STATUS affect Aucun 9.27 Linstruction RETURN (RETURN from subroutine) 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). Rappelezvous que pour chaque instruction call rencontre, votre programme devra rencontrer une instruction return . Syntaxe
return ; fin de sous-routine. Le PC est recharg depuis la pile, le ; programme poursuit ladresse qui suit la ligne call.

Bit du registre STATUS affect Aucun

63

Exemples Comme ceci est un concept trs important, je vais dtailler un peu plus. 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 :
movlw 0xCA movwf compteur decfsz compteur,f goto boucle xxx ; valeur du compteur ; initialiser compteur de boucles ; dcrmenter compteur, sauter si 0 ; boucler si pas 0 ; suite du programme

boucle

Imaginons maintenant que cette petite temporisation soit appele rgulirement par notre programme principal. Ecrivons quoi ressemble le programme principal :
xxx xxx xxx xxx tempo xxx xxx xxx tempo xxx xxx tempo xxx ; ; ; ; ; ; ; ; ; ; ; ; ; instruction quelconque instruction quelconque instruction quelconque instruction quelconque ici, on a besoin dune tempo instruction quelconque instruction quelconque instruction quelconque ici aussi instruction quelconque instruction quelconque et encore ici instruction quelconque

La premire chose qui vient lesprit, est deffectuer un copier/coller de notre temporisation. On obtient donc un programme comme ceci :
xxx xxx xxx xxx movlw 0xCA movwf compteur ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; instruction quelconque instruction quelconque instruction quelconque instruction quelconque valeur du compteur initialiser compteur de boucles dcrmenter compteur, sauter si 0 boucler si pas 0 instruction quelconque instruction quelconque instruction quelconque valeur du compteur initialiser compteur de boucles dcrmenter compteur, sauter si 0 boucler si pas 0 instruction quelconque instruction quelconque valeur du compteur initialiser compteur de boucles

boucle

decfsz compteur,f goto boucle xxx xxx xxx movlw 0xCA movwf compteur boucle2 decfsz compteur,f goto boucle2 xxx xxx movlw 0xCA movwf compteur boucle3 decfsz compteur,f goto boucle3

; dcrmenter compteur, sauter si 0 ; boucler si pas 0 64

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 :
tempo boucle movlw 0xCA movwf compteur decfs compteur,f goto boucle return ; tiquette de dbut de la sous-routine ; valeur du compteur ; initialiser compteur de boucles ; dcrmenter compteur, sauter si 0 ; boucler si pas 0 ; fin de la 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 :
xxx xxx xxx call xxx xxx xxx call xxx xxx call xxx ; ; ; tempo ; ; ; ; tempo ; ; ; tempo ; ; instruction quelconque instruction quelconque instruction quelconque appel du sous programme instruction quelconque, le programme continue ici instruction quelconque instruction quelconque appel du sous programme instruction quelconque, le programme continue ici instruction quelconque appel du sous programme instruction quelconque, le programme continue ici

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). Exemple, notre sous-programme devient :
tempo movwf compteur boucle decfsz compteur,f goto boucle return ; tiquette de dbut de la sous-routine ; initialiser compteur de boucles ; dcrmenter compteur, sauter si 0 ; boucler si pas 0 ; fin de la sous-routine.

Quant notre programme principal :

65

xxx xxx xxx xxx movlw call xxx xxx xxx movlw call xxx xxx movlw call xxx

0x25 tempo

0x50 tempo 0x10 tempo

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

instruction quelconque instruction quelconque instruction quelconque instruction quelconque charger w avec 0x25 appel du sous programme instruction quelconque, instruction quelconque instruction quelconque charger w avec 0x50 appel du sous programme instruction quelconque, instruction quelconque charger w avec 0x10 appel du sous programme instruction quelconque,

tempo dune dure de 0x25 le programme continue ici

tempo dune dure de 0x50 le programme continue ici tempo dune dure de 0x10 le programme continue ici

Voil, maintenant vous savez ce quest un sous-programme. Enfantin, nest-ce pas ? 9.28 Linstruction RETLW (RETurn with Literal in W) 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
retlw k ; (w) = k puis return

Bit du registre STATUS affect Aucun Exemple test ; tiquette de dbut de notre sous-programme btfss mavariable,0 ; teste le bit 0 de mavariable retlw 0 ; si vaut 0, fin de sous-programme avec (w)=0 retlw 1 ; sinon, on sort avec (w) = 1

Le programme qui a appel la sous-routine connat donc le rsultat de lopration en lisant le registre w .

66

9.29 Linstruction RETFIE (RETurn From IntErrupt) 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. Syntaxe
retfie ; retour dinterruption

Bit du registre STATUS affect Aucun 9.30 Linstruction CLRF (CLeaR F) Cette instruction efface lemplacement mmoire spcifi Syntaxe
clrf f ; (f) = 0

Bit du registre STATUS affect Z : Vaut donc toujours 1 aprs cette opration. Exemple
Clrf mavariable ; (mavariable) = 0

9.31 Linstruction CLRW (CLeaR W) Cette instruction efface w 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. Bit du registre STATUS affect Z : Vaut donc toujours 1 aprs cette opration.

67

9.32 Linstruction CLRWDT (CLeaR WatchDog) Remet 0 le chien de garde (watchdog) de votre programme. Nous aborderons la mise en uvre du watchdog ultrieurement. Sachez cependant que cest un mcanisme trs pratique qui permet de provoquer un reset automatique de votre PIC en cas de plantage du programme (parasite par exemple). 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
clrwdt ; remet le timer du watchdog 0

Bit du registre STATUS affect Aucun 9.33 Linstruction COMF (COMplement F) Effectue le complment 1 de lemplacement mmoire spcifi. Donc, inverse tous les bits de loctet dsign Syntaxe
comf f , d ; NOT (f) -> (d)

Bit du registre STATUS affect Z Exemple


movlw B11001010 movwf mavariable comf mavariable,w ; ; ; ; charge valeur dans W initialise mavariable charge linverse de mavariable dans W (W) = B00110101

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.

68

9.34 Linstruction SLEEP (Mise en sommeil) Place le PIC en mode de sommeil. Il ne se rveillera que sous certaines conditions que nous verrons plus tard. Syntaxe
Sleep ; arrt du PIC

Bit du registre STATUS affect Aucun 9. 35 Linstruction NOP (No Operation) Comme vous devez tre fatigus, 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
nop ; tout simplement

Ceci termine lanalyse des 35 instructions utilises normalement dans les PICs midrange. Ceci peut vous paratre ardu, mais en pratiquant quelque peu, vous connatrez trs vite toutes ces instructions par cur. Pensez pour vous consolez que certains processeurs CISC disposent de plusieurs centaines dinstructions. 9.36 Les instructions obsoltes 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. Il sagit de linstruction OPTION, qui place le contenu du registre W dans le registre OPTION_REG, et de linstruction TRIS, qui place le contenu de W dans le registre TRISA ou TRISB suivant quon utilise TRIS PORTA ou TRIS PORTB. 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 utilise.
69

10. Les modes dadressage


Les instructions utilisent toutes une manire particulire daccder aux informations quelles manipulent. Ces mthodes sont appeles modes dadressage . Je vais simplement donner un petit exemple concret de ce quest chaque mode dadressage. Supposons que vous vouliez mettre de largent dans votre poche : 10.1 Ladressage littral ou immdiat Avec l ADRESSAGE IMMEDIAT ou ADRESSAGE LITTERAL, vous pouvez dire : je mets 100F en poche. La valeur fait IMMEDIATement partie de la phrase. Jai donn LITTERALlement la valeur concerne. Pas besoin dun autre renseignement. Exemple
movlw 0x55 ; charger la valeur 0x55 dans W

10.2 Ladressage direct 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
movf 0x10 , W ; charger le contenu de lemplacement 0x10 dans W

10.3 Ladressage indirect Avec l ADRESSAGE INDIRECT , vous pouvez dire : Le prpos du guichet numro 3 va me donner le numro du coffre qui contient la somme que je vais mettre en poche. Ici, vous obtenez le numro du coffre INDIRECTement par le prpos au guichet. 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. Cette adressage fait appel 2 registres, dont un est particulier, car il nexiste pas vraiment. Examinons-les donc :
70

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. Dans lexemple schmatique prcdent, le prpos au guichet, cest le registre FSR. Ladressage indirect est un peu particulier sur les PICS, puisque cest toujours la mme adresse que se trouvera ladresse de destination. En somme, on peut dire quil ny a quun seul prpos (FSR) dans notre banque. Comment cela se passe-t-il ? Premirement, nous devons crire ladresse pointe dans le registre FSR. Ensuite, nous accdons cette adresse pointe par le registre INDF. 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
movlw 0x50 movwf mavariable movlw mavariable movwf FSR movf INDF,w ; ; ; ; ; ; ; ; chargeons une valeur quelconque et plaons-la dans la variable mavariable on charge lADRESSE de mavariable, par exemple, dans les leons prcdentes, ctait 0x0e. (W) = 0x0E on place ladresse de destination dans FSR. on dira que FSR POINTE sur mavariable charger le CONTENU de INDF dans W.

LE CONTENU DE INDF EST TRADUIT PAR LE PIC COMME ETANT LE CONTENU DE LEMPLACEMENT MEMOIRE POINTE PAR FSR (W) = 0X50

71

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

Cest de ladressage immdiat ou littral ; donc on charge la VALEUR de mavariable, ce qui correspond en ralit son ADRESSE. Donc 0x0E est plac dans (W). Ceci se reconnat au l de linstruction movlw
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). movf INDF , w

Maintenant, cest de ladressage INDIRECT. Ce mode dadressage se reconnat immdiatement par lutilisation du registre INDF. Le PIC va voir dans le registre FSR, et lit ladresse contenue, dans ce cas 0X0E. Elle va ensuite dans lemplacement vis, et lit le CONTENU. Donc, dans (W) on aura le contenu de 0x0E, soit 0x50. 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 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 nul 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. 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.

72

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. 11.1 Le matriel ncessaire 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) :
-

1 PIC 16F84 ou 16F84A en botier PDIP et de frquence quelconque 2 supports tulipe 18 pins / cartement entre les ranges : 0.3 1 Quartz de 4MHz 2 condensateurs de 27pF 1 Led rouge 1 Rsistance de 330 ohms. 1 bouton-poussoir normalement ouvert (N.O.) 1 peu de fil rigide pour les connexions sur la platine dessais 1 alimentation stabilise

Si vous ne disposez pas dune alimentation de 5V, vous pouvez, soit utiliser une pile plate de 4.5V, soit raliser une petite alimentation dont le schma est donn page suivante. Il vous faudra dans ce dernier cas : -

1 Bloc dalimentation secteur de 9 15V, pas critique. 1 Condensateur de 100F/35V. 1 Condensateur de 0.1 F 1 diode 1N4007, ou autre diode permettant un courant de 1A (pas critique) 1 Rgulateur de type 7805.

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. 11.2 Montage de la platine dessais Insrez le pic dans un des supports tulipe. Insrez le support restant dans la platine dessais, et procdez aux connexions suivant le schma ci-joint. Vrifiez tout avant de connecter lalimentation. Si vous navez pas dalimentation stabilise, utilisez une pile, ou connectez les composants suivant le schma suivant.

73

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 que les tensions sont correctes au niveau des broches dalimentation du PIC. Vous tes maintenant prt commencer les exprimentations. 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. Schma de connexion du PIC

Schma de la petite alimentation stabilise

11.3 Cration du projet 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. Editez le nud, noubliez pas de cocher Default radix : Dec . Ajoutez ensuite le nud Led_cli.asm . Vous tes prts commencer. Noubliez pas bien sr douvrir votre fichier Led_cli.asm ( file->open ).De nouveau, ce fichier est disponible en annexe.

74

11.4 Edition du fichier source Compltez le cadre den-tte suivant votre dsir. Je vous indique ci-dessous un exemple. Prenez lhabitude de toujours documenter vos programmes. Ce nest pas un luxe, cest impratif pour une maintenance efficace dans le temps.
;************************************************************************** ; 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 * ; * ;**************************************************************************

11.5 Choix de la configuration Plus bas dans le fichier, vous trouverez ceci :
__CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC

; '__CONFIG' prcise les paramtres encods dans le processeur au moment de ; la programmation du processeur. Les dfinitions sont dans le fichier include. ; Voici les valeurs et leurs dfinitions : ;_CP_ON ;_CP_OFF ;_PWRTE_ON ;_PWRTE_OFF ;_WDT_ON ;_WDT_OFF ;_LP_OSC ;_XT_OSC ;_HS_OSC ;_RC_OSC Code protection ON : impossible de relire Code protection OFF Timer reset sur power on en service Timer reset hors-service Watch-dog en service Watch-dog hors service Oscillateur quartz basse consommation Oscillateur quartz moyenne vitesse ou externe Oscillateur quartz grande vitesse Oscillateur rseau RC

Jai inclus les commentaires dans le fichier de faon ce quil soit plus rapidement modifiables 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.
75

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 protge. 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. Il est important de ne pas utiliser _RC_OSC si on utilise un quartz. Ce paramtre est rserv un fonctionnement par rseau R/C tel que dessin figure 8-7 page 41. LE FAIT DUTILISER LE PARAMETRE RC AVEC UNE HORLOGE EXTERNE PEUT ENTRAINER LA DESTRUCTION DU PIC. 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 :
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC

11.6 Le registre OPTION 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 : 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.
76

Notez que cette option valide les rsistance 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. Comme ce dernier mode ncessite un circuit de gnration de pulses externe, nous utiliserons pour le timer0 lhorloge interne, donc b5 = 0 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. 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).

77

b2, b1,b0 : PS2,PS1,PS0 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. 11.7 Edition du programme 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 * ;********************************************************************* OPTIONVAL EQUH'0008 ; Valeur registre option ; Rsistance pull-up ON ; Pas de prscaler

Descendons encore jusqu la zone des dfinitions. Nous allons donner un nom notre bouton-poussoir et notre LED. 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.

78

Nous voyons sur le schma que la LED est connecte sur le bit 2 du port A. Le boutonpoussoir est connect sur le bit 2 du port B. Nous effaons donc les dfinition 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 soie 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 quand mme les utiliser titre dexemple. Effacez la macro donne titre dexemple et entrons celles-ci.
;********************************************************************* ; MACRO * ;********************************************************************* LEDON macro bsfLED endm LEDOFF macro bcfLED 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

Au moment de la compilation, notre assembleur remplacera LEDON par :


bsf LED

Il remplacera galement LED par PORTA,2. Ce qui fait quen ralit nous obtiendrons :
bsf PORTA , 2

79

Nous avons donc obtenu une facilit dcriture et de maintenance. Gardez lesprit que les macros sont des simples substitution 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

A lORG 0x00, laissons lappel vers la routine dinitialisation. Tout programme comporte en effet une tape dinitialisation des variables et des registres. Prenez lhabitude de sparer cette initialisation du reste du programme. Comme nous nutiliserons pas les interruptions, supprimez tout ce qui suit jusqu la routine dinitialisation, vous obtenez :
********************************************************************** ; DEMARRAGE SUR RESET * ;********************************************************************* org goto 0x000 init ; Adresse de dpart aprs reset ; Adresse 0: initialiser

;********************************************************************* ; INITIALISATIONS * ;********************************************************************* suite du programme

A ce stade, avant de poursuivre, nous allons tudier les registres dont nous allons nous servir, et tout dabord : 11.8 Le registre PORTA 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 banque0. 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.

80

Par exemple :
bsf PORTA , 1 ; envoyer niveau 1 sur RA1

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 entres, 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 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. Quand 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 limitez 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.

81

11.8.1 Fonctionnement particulier des PORTS Les PORTS fonctionnent toujours sur le principe lecture->modification->criture. Par exemple, si vous crivez bsf PORTA,1, le PIC procde de la manire suivante : 1) La totalit du PORTA est lu (mme les bits en sortie) 2) Le bit 1 est mis 1 3) La totalit du PORTA est rcrit. 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. Si vous effectuez lopration suivante :
bsf PORTA , 1 ; mettre RA1 1

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, 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. Pour les non-lectroniciens, ne paniquez pas, car, de toute faon, vous ne raliserez sans doute jamais une interface qui pose ce type de problme. Je tenais cependant tre exhaustif. 11.9 Le registre TRISA Ce registre est situ la mme adresse que PORTA, mais dans la banque 1. Son adresse complte sur 8 bits est donc 0x85. Ce registre est dun fonctionnement trs simple et est li au fonctionnement du PORTA. Chaque bit positionn 1 configure la pin correspondante en entre. Chaque bit 0 configure la pin en sortie. 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).
82

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). Ensuite, nous pourrons envoyer un niveau 1 sur PORTA, correspondant 5V sur la pin RA2. La squence correcte sera donc :
bsf STATUS , RP0 bcf TRISA , 2 bcf STATUS , RP0 bsf PORTA , 2 . . . bcfPORTA , 2 ; ; ; ; on passe en banque 1 bit 2 de TRISA 0 = sortie pour RA2 on repasse en banque 0 on envoie 5V sur RA2 : la LED sallume

; 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 nauront donc plus quune seule instruction utiliser. On commence entrer dans le concret . 11.10 Les registres PORTB et TRISB 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. Voyons maintenant les particularits du PORTB. Nous en avons dj vu une, puisque les entres du PORTB peuvent tre connectes une rsistance de rappel au +5V de manire interne. La slection seffectuant par le bit 7 du registre OPTION. Le schma interne visible figures 5-3 et 5-4 page 23 du datasheet vous montre que les bits b0 et b4/b7 peuvent tre utiliss comme source dinterruption, le bit 0 peut de plus tre utilis de manire autonome pour gnrer un autre type dinterruption. Nous verrons le fonctionnement des interruptions dans un autre chapitre. Sachez cependant dj que les schmas que vous concevrez vous-mme dans le futur devront tenir compte des particularits des PORTs. 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.

83

11.11 Exemple dapplication 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)
bsf bcf bcf bcf boucle btfss bsf btfsc bcf goto STATUS , RP0 OPTION_REG, RBPU TRISA , 2 STATUS , RP0 PORTB , PORTA , PORTB , PORTA , boucle 2 2 2 2 ; ; ; ; ; ; ; ; ; ; ; ; on passe en banque 1 rsistance de rappel en service bit 2 de TRISA 0 = sortie pour RA2 inutile de configurer TRISB, car il est en entre par dfaut au reset du PIC on repasse en banque 0 tiquette de dbut de la boucle principale tester RB2, sauter si vaut 1 RB2 vaut 0, donc on allume la LED tester RB2, sauter si vaut 0 RB2 vaut 1, donc LED teinte et on recommence

11.12 La routine dinitialisation Examinons les instructions contenues partir de ltiquette init Les 2 premires lignes ,
clrf clrf PORTA PORTB ; Sorties portA 0 ; sorties portB 0

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. La ligne suivante permet de se connecter sur la banque1. Jusqu nouvel ordre, les instructions suivantes utilisent des registres situs banque1. Ensuite nous trouvons la ligne :
clrf EEADR ; permet de diminuer la consommation

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. Ensuite, nous trouvons :
movlw OPTIONVAL movwf OPTION_REG ; charger masque ; initialiser registre option

84

Rappelez-vous que OPTIONVAL est une constante. Sa valeur a t dfinie prcdemment par nos soins en 0x08. Cette valeur sera envoye ici dans le registre OPTION (OPTION_REG). Souvenez-vous que OPTION_REG est le nom dclar dans MPLAB pour le registre OPTION. 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 ; movwf FSR ; init1 clrf INDF ; incf FSR,f ; btfss FSR,6 ; goto init1 ; btfss FSR,4 ; goto init1 ; xxxxx ;

initialisation pointeur pointeur d'adressage indirect effacer ram pointe par FSR pointer sur suivant tester si fin zone atteinte (>=0x40) non, boucler tester si fin zone atteinte (>=0x50) non, boucler ici se trouve la suite du programme

Voil donc un exemple concret de lutilisation de ladressage indirect. 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 banque0) 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.

85

Effacez ensuite les lignes suivante :


bcf bcf movlw movwf TRISA,0 STATUS,RP0 INTERMASK INTCON ; ; ; ; Bit PORTA.0 en sortie (exemple) Slectionner banque 0 masque interruption charger interrupt control

car elles ne nous intressent pas pour notre programme. Voyons maintenant ce que nous devons ajouter : 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

Autrement dit par


bcf 0x05 , 2

Or, RP0 est toujours positionn 1au 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. Donc, lopration a donc plac RA2 en sortie. En changeant donc simplement le DEFINE LED au dbut du programme, vous pouvez donc changer toutes les rfrences RA2 dans tout le programme, mme pour TRISA. Placez un petit commentaire den-tte, et vous obtenez :
; initialisations spcifiques ; --------------------------bcfLED ; LED en sortie (banque1)

Repassez ensuite en banque0 avant de quitter lintialisation. Cest une bonne pratique, car beaucoup derreurs sont provoques par des erreurs de banque, ajoutez donc :
bcfSTATUS , RP0 ; Repasser en banque 0

Terminez avec la ligne


goto start 86

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?). 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 bsf STATUS , RP0 ; slectionner banque 1 clrf EEADR ; permet de diminuer la consommation movlw OPTIONVAL ; charger masque movwf OPTION_REG ; initialiser registre option ; Effacer RAM ; -----------movlw 0x0c movwf FSR init1 clrf INDF incf FSR,f btfss FSR,6 goto init1 btfss FSR,4 goto init1

; initialisation pointeur ; pointeur d'adressage indirect ; ; ; ; ; ; effacer ram pointer sur suivant tester si fin zone atteinte (>=0x40) non, boucler tester si fin zone atteinte (>=0x50) non, boucler

; initialisations spcifiques ; --------------------------bcf LED ; LED en sortie (banque1) bcf STATUS , RP0 ; repasser banque 0 goto start ; sauter au programme principal

Descendons maintenant dans le programme principal, et supprimons la ligne :


clrwdt ; effacer watchdog

11.13 Les rsultats de la compilation Lancez la compilation par la touche <F10>. Dans la fentre de rsultat de compilation, vous devez trouver une ligne du type Message[302] D:\DOCUME~1\LESSONS\DATAPIC\LED_CLI.ASM 101 : Register in operand not in bank 0. Ensure that bank bits are correct.

87

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 banque0. MPASM vous demande de vrifier que votre bits RP0 est positionn correctement. Allez dans l diteur sur la ligne dont vous avez le numro. Vous tombez sur la ligne :
movwf OPTION_REG ; initialiser registre option

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 . 11.14 Le programme principal 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 call bcf call goto LED tempo LED tempo start ; ; ; ; ; allumer la LED appeler la tempo de 0.5s teindre LED appeler la tempo de 0.5s boucler

On aurait pu crire galement (en utilisant nos macros)


start LEDON call tempo LEDOFF call tempo goto start ; ; ; ; ; allumer la LED appeler la tempo de 0.5s teindre LED appeler la tempo de 0.5s boucler

Choisissez la mthode que vous prfrez. Limportant, cest davoir compris les deux mthodes.

88

11.15 La sous-routine de temporisation 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. 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. Chaque cycle dinstruction dure donc 1 millionime de seconde, ou encore une microseconde (s). Voil donc lunit pour travailler avec notre PIC. 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

89

Ralisons maintenant notre boucle.


tempo clrf cmpt1 boucle1 decfsz cmpt1 goto boucle1 return ; effacer compteur1 ; dcrmenter compteur1 ; si pas 0, boucler ; retour de la sous-routine

Lanons la compilation (F10) : Nous obtenons dans la fentre des rsultats une ligne supplmentaire de la forme : Message[305] D:\DOCUME~1\LESSONS\DATAPIC\LED_CLI.ASM 134 : Using default destination of 1 (file). 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. Positionnezvous dans lditeur sur la ligne incrimine (ligne 134 pour moi). Vous tes sur la ligne :
decfsz cmpt1 ; dcrmenter compteur1

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
decfsz cmpt1 , f ; dcrmenter compteur1

Maintenant, nous allons calculer la dure de cette tempo.


tempo clrf cmpt1 boucle1 decfsz cmpt1 , f goto boucle1 return ; 1 cycle ; ; ; ; 1 cycle si on ne saute pas, 2 si on saute. Donc, on ne sautera pas 255 fois et on sautera 1 fois 2 cycles multipli par 255 passages 2 cycles.

Le temps total est donc de : 2 cycles pour lappel de la sous-routine (call tempo) 1 cycle pour le reset de la variable 257 cycles pour les 256 dcrmentations 510 cycles pour les 255 goto 2 cycles pour le return. Soit un total de 772 cycles. On est loin des 500.000 cycles ncessaire. Pour la suite des calculs, nous allons ngliger les 2 cycles du call et les 2 cycles du return (compars aux 500.000 cycles ncessaires).

90

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 :
cmpt1 : 1 cmpt2 : 1 ; compteur de boucles 1 ; compteur de boucles 2

Ecrivons donc les 2 boucles imbriques :


tempo clrf boucle2 clrf boucle1 decfsz goto decfsz goto return cmpt2 cmpt1 cmpt1 , f boucle1 cmpt2 , f boucle2 ; effacer compteur2 ; effacer compteur1 ; ; ; ; ; dcrmenter compteur1 si pas 0, boucler si 0, dcrmenter compteur 2 si cmpt2 pas 0, recommencer boucle1 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 Quelle est la temporisation obtenue ? Calculons approximativement : 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 simple, ceci est expliqu dans un but didactique : il importe simplement davoir compris).
91

;********************************************************************* ; DECLARATIONS DE VARIABLES * ;********************************************************************* CBLOCK 0x00C ; dbut de la zone variables cmpt1 : 1 cmpt2 : 1 cmpt3 : 1 ENDC ; compteur de boucles 1 ; compteur de boucles 2 ; compteur de boucles 3 ; Fin de la zone

Voici le code final :


;********************************************************************* ; 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 ; si cmpt3 pas 0, recommencer boucle2 goto boucle3 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 Envoyez- le dans votre PIC laide de votre programmateur. Placez le PIC sur la carte HORS TENSION, envoyez lalimentation et regardez bien : VOTRE LED CLIGNOTE A LA FREQUENCE DE 1HZ. Flicitations, voici votre premier programme embarqu. La porte est ouverte des tonnes de nouvelles applications. 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.
92

12. Les interruptions


Voil un chapitre qui fera certainement peur beaucoup de futurs programmeurs. Pourtant, le mcanisme des interruptions est trs ais comprendre, et galement mettre en uvre, pour autant que lon travaille de manire propre et structure. 12.1 Quest-ce quune interruption ? Imaginez une conversation normale : Chaque interlocuteur prend la parole quand vient son tour de parler. Survient alors un vnement extrieur dont le traitement est urgent. Par exemple, un piano tombe du 3me tage de limmeuble au pied duquel vous discutez. Vous imaginez bien que votre interlocuteur ne va pas attendre la fin de votre phrase pour vous signaler le danger. Il va donc vous INTERROMPRE durant le cours normal de votre conversation., afin de pouvoir TRAITER IMMEDIATEMENT lEVENEMENT extrieur.

Les interlocuteurs reprendront leur conversation o elle en tait arrive, sitt le danger cart (sils ont vit le piano, bien sr). Et bien, pour les programmes, cest exactement le mme principe : Votre programme se droule normalement. Survient un vnement spcifique. Le programme principal est interrompu (donc, subit une INTERRUPTION), et va traiter lvnement, avant de reprendre le programme principal lendroit o il avait t interrompu.

Linterruption est donc une RUPTURE DE SEQUENCE ASYNCHRONE, cest dire non synchronise avec le droulement normal du programme. Vous voyez ici lopposition avec les ruptures de squences synchrones, provoques par le programme lui-mme (goto, call, btfss). 12.2 Mcanisme gnral dune interruption 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 : Le programme se droule normalement Lvnement survient Le programme achve linstruction en cours de traitement Le programme saute ladresse de traitement de linterruption Le programme traite linterruption Le programme saute linstruction qui suit la dernire excute dans le programme principal.
93

Il va bien sr de soi que nimporte quel vnement ne peut pas dclencher une interruption. Il faut que 2 conditions principales soient remplies : Lvnement en question doit figurer dans la liste des vnements susceptibles de provoquer une interruption pour le processeur sur lequel on travaille Lutilisateur doit avoir autoriser linterruption, cest dire doit avoir signal que lvnement en question devait gnrer une interruption.

Organigramme gnral de lexcution dune interruption. 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. 12.3 Mcanisme dinterruption sur les PICs 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. Les PICs en se connectant cette adresse, ne sauvent rien automatiquement, hormis le contenu du PC, qui servira connatre ladresse du retour de linterruption. Cest donc lutilisateur de se charger des sauvegardes. Le contenu du PC est sauv sur la pile interne (8 niveaux). Donc, si vous utilisez des interruption, vous ne disposez plus que de 7 niveaux dimbrication pour vos sousprogrammes. Moins si vous utilisez des sous-programmes dans vos interruption. Le temps de raction dune interruption est calcul de la manire suivante :

Le cycle courant de linstruction est termin. Le flag dinterruption est lu au dbut du cycle suivant.

94

Celui-ci est achev, puis le processeur sarrte un cycle pour charger ladresse 0x04 dans PC. Le processeur se connecte alors ladresse 0x04 o il lui faudra un cycle supplmentaire pour charger linstruction excuter. Le temps mort total sera donc compris entre 3 et 4 cycles. 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). Les interruptions sont remises en service automatiquement lors du retour de linterruption. Linstruction RETFIE agit donc exactement comme linstruction RETURN, mais elle repositionne en mme temps le bit GIE.

Les interruptions sur les PICs

12.4 Les sources dinterruptions du 16F84 Le 16F84 est trs pauvre ce niveau, puisquil ne dispose que de 4 sources dinterruptions possibles (contre 13 pour le 16F876 par exemple). Les vnements susceptibles de dclencher une interruption sont les suivants : 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.
95

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.

12.5 Les dispositifs mis en uvre 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. Imaginons un htel. Le groom de service reprsente notre programme. Lhtel comporte 4 chambres, et chaque chambre est quipe dun bouton-poussoir. Chaque bouton-poussoir servant appeler le groom, est reli une lampe laccueil de lhtel. Chaque lampe a la possibilit de faire rsonner une sonnette si linterrupteur gnral de la sonnette est positionn, et si linterrupteur particulier reliant chaque lampe la sonnette est mis. Voil donc le schma obtenu (attention, cest un schma symbolique, pas lectrique, les lignes reprsentent la circulation de linformation, pas un courant lectrique) :

96

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. Soit via la lampe, soit via la sonnette. 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. Les interrupteurs de validation nagissent pas sur les lampes. 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.

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. 12.6 Le registre INTCON (INTerrupt CONtrol) Ce registre se situe ladresse 0x0B, dans les 2 banques. Il est donc toujours accessible. Il est dtaill figure 4-5 page 16. 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).

97

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 RB port change Interrupt Enable bit : Valide les interruptions si on a changement de niveau sur une des entres RB4 RB7. 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 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 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.

98

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.

12.7 Sauvegarde et restauration de lenvironnement Si vous regardez de nouveau lorganigramme de la routine dinterruption, vous constatez que vous devez procder la sauvegarde et la restauration de lenvironnement de votre programme. En quoi cela consiste-t-il ? 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 : Supposons votre programme principal interrompu entre les 2 instructions suivantes :
movf mavariable , w ; charger mavariable et positionner Z btfss STATUS , Z ; tester bit Z et sauter si vaut 1

Il est plus que probable que votre routine dinterruption va utiliser au moins une instructions 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 prt certain que le registre w va tre modifi galement, donc il vous faudra veiller le sauvegarder galement.

99

12.7.1 Les registres sauvegarder Pour commencer, le plus simple : le PC est sauvegard automatiquement, le programme revient donc la bonne adresse tout seul. Par contre, STATUS est, comme nous venons de voir, restaurer par la routine dinterruption. W sera galement modifi par la routine dinterruption. Sil y a dautres registres sauvegarder, ce sera en fonction du fonctionnement de votre programme. Les seuls registres sauver obligatoirement sont donc STATUS et W. Si, dans la routine dinterruption et dans le programme principal, nous utilisons ladressage indirect, nous devrons galement restaurer FSR. 12.7.2 La mthode de sauvegarde En voil une bte question, allez-vous vous dire. En effet, avec un simple :
movf STATUS , w movwf emplacement_de_sauvegarde ; charge STATUS dans W ; sauvegarde STATUS

Les registres semblent sauvegards. Et bien, analysons en dtail ce qui ce passe dans ce cas. Si on analyse le fonctionnement de movf, nous constatons que le bit Z est affect par cette opration. Donc, dans W nous navons plus STATUS tel quil tait, mais dj un status modifi. Nous ne pouvons donc pas utiliser cette procdure. Mais alors, comment faire ? 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 . Effectuons donc la sauvegarde de la manire suivante :
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 :
swapf status_temp,w movwf STATUS ; swap ancien status, rsultat dans w ; restaurer status

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 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)
100

Pour sauver W, pas de problme, linstruction suivante :


movwf w_temp ; sauver registre W

Sauve W sans modifier STATUS. Par contre, pour restaurer W, nous devons charger w_temp SANS MODIFIER STATUS, il nous faut donc de nouveau utiliser swap. Seulement, nous avions sauv w non swapp . Pour le restaurer, nous ne devons pas le swapper , ce qui peut aussi se traduire par le swapper 2 fois. Nous pouvons donc crire
swapf swapf w_temp,f w_temp,w ; Swapper w_temp sans modifier Z ;Swapper une deuxime fois w_temp, rsultat dans ; w, STATUS non affect

La premire instruction swappe lancienne valeur de w et place le rsultat dans lemplacement de sauvegarde. La seconde instruction swappe une seconde fois cette valeur, et place le rsultat dans W. Nous avons donc recharg W sans modifier STATUS. Voici donc la structure de base dune routine dinterruption :
;********************************************************************** ; 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 ; switch vers diffrentes interrupts ; ---------------------------------; ici, on teste ventuellement de quelle interruption il sagit ; traitement des interruptions ; ----------------------------; ici, on peut traiter interruption puis effacer son flag

;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 retfi ; 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).
101

Comme je suis partisan de la programmation structure, la routine de switch branche en ralit sur des sous-programmes spars. Rien nempche en effet dutiliser des sousprogrammes dans une routine dinterruption. 12.7.3 Particularit de linstruction RETFIE A ce niveau de lexpos, une remarque pertinente serait la suivante : Pourquoi existe-t-il une instruction RETFIE, alors quon pourrait utiliser RETURN ? Et bien, vous ne pouvez pas interrompre une interruption par une autre. Si ctait le cas, les sauvegardes des registres W et STATUS seraient cras 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. Vous allez alors me dire : et si je fais ceci ?
bsf INTCON , GIE return ; remettre GIE 1 ; et sortir de la routine dinterruption

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. 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. 12.8 Utilisation dune routine dinterruption Effectuez une copie de votre fichier m16f84.asm. Renommez-la en myinter.asm . Crez un nouveau projet MPLAB avec le nom myinter.pjt suivant le processus habituel. 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). Ceci vous montre cependant que llectronique et la programmation avec les microcontrleurs sont trs dpendants. Quand vous construisez un circuit, vous devez dj penser la manire dont vous allez raliser la programmation. A linverse, si vous disposez
102

dun circuit dj existant, des contraintes vous sont dj imposes au niveau de la programmation. Il est par exemple impossible de traiter notre bouton-poussoir par interruption sil est cbl sur lentre RB2. Comme dhabitude, remplissez le cadre den-tte, et supprimez les lignes inutilises dans les variables, macro, et DEFINE. Attention, ne supprimez pas les variables w_temp et status_temp.. #include <p16F84.inc> ; Dfinitions des constantes

Voici len-tte tel que vous pourriez le complter :


;********************************************************************** ; Ce programme est un programme didactique destin monter * ; le fonctionnement des interruptions * ; * ;********************************************************************** ; * ; 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. Croyezmoi 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. Modifiez la config pour supprimer le fonctionnement du watch-dog :
__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC

Calculons la future valeur envoyer dans le registre OPTION b7 0, car on a besoin de la rsistance de rappel au +5V pour le bouton-poussoir. b6 0, car on veut une interruption quand presse le bouton, donc quand le niveau passe de 1 0 (flanc descendant) b5/b0 0, aucune importance dans cette application.

Donc, nous placerons notre assignation B00000000, donc :


103

;********************************************************************* ; ASSIGNATIONS * ;********************************************************************* OPTIONVAL EQUH'0000' ; Valeur registre option ; Rsistance pull-up ON ; Interrupt flanc descendant RB0

Pour le registre INTCON, nous devrons avoir : b7 1 b6 0 b5 0 b4 1 b3 0 b2/b0 0 : pour valider les interruptions : pas dinterruption EE : pas dinterruption tmr0 : interruption RB0 en service : Pas dinterruption RB : effacer les flags

Cela donne : B10010000, soit 0x90 Assignons une constante pour cette valeur ;
INTERMASK EQUH'0090' ; Masque d'interruption ; Interruptions sur RB0

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 :
104

;********************************************************************* ; DECLARATIONS DE VARIABLES * ;********************************************************************* CBLOCK 0x00C ; dbut de la zone variables w_temp :1 status_temp : 1 cmpt1 : 1 cmpt2 : 1 cmpt3 : 1 ENDC ; ; ; ; ; Sauvegarde de W dans interruption Sauvegarde de STATUS dans interrupt compteur de boucles 1 dans tempo compteur de boucles 2 dans tempo compteur de boucles 3 dans tempo

; Fin de la zone

12.9 Analyse de la routine dinterruption Nous avons dj vu la premire partie, qui est la sauvegarde des registres utiliss
;********************************************************************** ; 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 :
; switch vers diffrentes interrupts ; inverser ordre pour modifier priorits ;---------------------------------------btfsc btfss goto call goto INTCON,T0IE ; tester si interrupt timer autorise INTCON,T0IF ; oui, tester si interrupt timer en cours intsw1 ; non test suivant inttimer ; oui, traiter interrupt timer restorereg ; et fin d'interruption ; SUPPRIMER CETTE LIGNE POUR ; TRAITER PLUSIEURS INTERRUPT ; EN 1 SEULE FOIS

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.

105

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 vaut0, 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. La dernire ligne permet de sauter la fin de la routine dinterruption, donc de restaurer les registres et de sortir. Donc, dans le cas o on aurait deux sources dinterruptions simultanes, une seule serait traite la fois. Si par contre on supprime cette ligne, linterruption suivante sera traite ds celle en cours termine. Jai donc tudi cette ossature pour vous laisser toutes les variantes possibles, et directement utilisables. Remarques Si on nutilise jamais linterruption tmr0, on peut supprimer cette partie de code Si linterruption tmr0 tait en service tout au long du programme, on pourrait supprimer le test de T0IE (car il serait tout le temps 1)

- En cas de 2 interruptions simultanes de 2 vnements distincts, la premire interruption traite sera celle teste en premier. Lordre des tests modifie donc la priorit des interruptions. 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 btfss goto call bcf goto INTCON , INTE INTCON , INTF intsw2 intrb0 INTCON,INTF restorereg ; ; ; ; ; ; tester si interrupt RB0 autorise oui, tester si interrupt RB0 en cours non sauter au test suivant oui, traiter interrupt RB0 effacer flag interupt RB0 et fin d'interruption

intsw2 btfsc btfss goto call bcf goto intsw3

; SUPPRIMER CETTE LIGNE POUR ; TRAITER PLUSIEURS INTERRUPT ; EN 1 SEULE FOIS INTCON,RBIE INTCON,RBIF intsw3 intrb4 INTCON,RBIF restorereg ; ; ; ; ; ; tester si interrupt RB4/7 autorise oui, tester si interrupt RB4/7 en cours non sauter oui, traiter interrupt RB4/7 effacer flag interupt RB4/7 et fin d'interrupt

; ici, la place pour linterruption eeprom

106

Enfin, nous trouvons la partie servant la restauration des registres sauvegards. Nous avons dj vu cette procdure :
;restaurer registres ;------------------; ; ; ; ; ; ; swap ancien status, rsultat dans w restaurer status Inversion L et H de l'ancien W sans modifier Z R-inversion de L et H dans W W restaur sans modifier status return from interrupt

restorereg swapf status_temp , w movwf STATUS swapf w_temp , f swapf w_temp , w retfie

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

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). Voyons maintenant la suite du programme. Nous allons trouver les 3 routines de traitement des interruptions appeles lorigine par notre routine dinterruption. Comme nous avons supprim 2 de ces appels, inutile de conserver les sous-routines correspondantes. La seule dont nous aurons besoin sera donc :

107

;********************************************************************** ; INTERRUPTION RB0/INT * ;********************************************************************** intrb0 return ; fin d'interruption RB0/INT ; peut tre remplac par ; retlw pour retour code d'erreur

Elle ne contient que le retour de sous-routine correspondant lappel du call intrb0. Attention, ce niveau vous nutiliserez pas RETFIE, car vous ne sortez pas de linterruption, vous sortez dune sous-routine appele par la routine dinterruption. Si vous utilisiez RETFIE ce moment, vous remettriez les interruptions en service avant den sortir, donc plantage de votre programme. 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 goto restorereg ; et fin d'interruption

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 Poursuivons : nous trouvons la routine dinitialisation que nous avons dj explique la leon prcdente. Nous nous contenterons de remplacer les changements de banque par les macros que nous avons crites , et configurer RA2 en sortie pour la LED. Nous obtenons :
;********************************************************************* ; INITIALISATIONS * ;********************************************************************* init clrf clrf BANK1 clrf movlw movwf PORTA PORTB EEADR OPTIONVAL OPTION_REG ; ; ; ; ; ; Sorties portA 0 sorties portB 0 passer banque1 permet de diminuer la consommation charger masque 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 108

btfss FSR , 4 goto init1

; tester si fin zone atteinte (>=0x50) ; non, boucler

; configurer PORTS ; --------------bcfLED ; RA2 en sortie (TRISA) BANK0 movlw INTERMASK movwf INTCON goto start ; ; ; ; passer banque0 masque interruption charger interrupt control sauter programme principal

Il ne nous reste plus qu supprimer la ligne


clrwdt ; effacer watch dog

du programme principal, puisque nous avons dsactiv le watchdog. 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 banque0, et de toujours sassurer que vous tes en banque0 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) :
Building MYINTER.HEX... Compiling MYINTER.ASM: Command line: "C:\PROGRA~1\MPLAB\MPASMWIN.EXE /e+ /l+ /x- /c+ /rdec /p16F84 /q D:\DOCUME~1\LESSONS\DATAPIC\MYINTER.ASM" 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 successfully.

Je ne reviendrai pas ici sur les warnings. 12.12 Construction du programme principal 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. Je rappelle que ceci est un programme didactique. Nous raliserons ce tlrupteur de manire un peu plus lgante dans la leon sur le timer0.

109

Puisque nous dsirons utiliser les interruptions, linversion de lallumage de la LED se fera dans la routine dinterruption du bouton-poussoir. Dans un premier temps, nous pourrions penser que le programme principal na rien faire. Remarque trs importante En aucun cas vous ne pouvez laisser un programme se balader hors de la zone de votre programme. Si le programme na plus rien du tout faire, vous devez alors le boucler sur luimme. Car le programme ne sarrte pas (sauf passage en mode sleep que nous verrons plus tard). Notre programme principal pourrait donc tre de la forme : start goto start ; boucler

Mais, pour faciliter la visualisation de ce qui se passe sous lmulateur, je vous demanderai dajouter quelques NOP inutiles. Voil donc notre programme principal :
;********************************************************************* ; PROGRAMME PRINCIPAL * ;********************************************************************* start nop ; instruction inutile nop ; instruction inutile nop ; instruction inutile nop ; instruction inutile nop ; instruction inutile goto start ; boucler END ; directive fin de programme

12.13 Construction de la routine dinterruption 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 110

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. Ordinogramme 1 (version thoriquement fonctionnelle)

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. 12.14 Passage au simulateur dune routine dinterruption Petit rappel, il faut commencer par slectionner la mise en service du simulateur : Allez dans le menu project et slectionnez edit project . Dans la fentre qui souvre, slectionnez change ct du development mode . et cliquez sur la case MPLABSIM 16F84 . Rpondez oui toutes les questions qui pourraient vous tre poses. Dans le menu windows , slectionnons maintenant laffichage des registre spciaux (special function registers). Plaons cette fentre sur le ct. 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. Une fois arriv dans le programme principal, le programme boucle indfiniment. En effet, un vnement extrieur (bouton-poussoir) est ncessaire pour provoquer le passage dans la routine dinterruption. Je vais maintenant vous expliquer comment simuler un vnement extrieur. Allez dans le menu debug , choisissez Simulator stimulus ->Asynchronous stimulus . Une petite fentre souvre avec 12 vnements configurables. Cette fentre se place toujours en avant-plan. Rangez-la gauche de votre diteur, sans cacher les registres spciaux. Prenez garde pour linstant de ne pas cliquer sur un bouton tant que je ne vous le signalerai pas.

111

Placez-vous sur le bouton <Stim 1 (P) > et cliquez avec le bouton de droite. Vous avez un menu droulant qui apparat. Slectionnez assign pin . Choisissez ensuite la pin que vous voulez stimuler. Dans notre cas, RB0. Votre bouton est maintenant transform en <RB0 (P)>. Si vous regardez encore avec le bouton de droite, 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 est maintenant < RB0 (L) >. Crez un second bouton ct du premier en slectionnant RB0 et High. Vous disposez maintenant de 2 boutons. Le premier place RB0 au niveau 1 (donc simulation du bouton-poussoir relch), lautre le place sur 0, donc bouton-poussoir press. Notez, mais ne le faite pas maintenant, que si vous pressez deux fois sur un bouton avec le bouton de gauche, vous obtenez le message suivant :

Ceci signifie que vous ne pouvez videmment excuter quune stimulation par cycle. Vous tes donc oblig aprs chaque pression sur un bouton de stimulation, de revenir sur la fentre de lditeur et davancer dune instruction avec <F7> avant de pouvoir exercer un nouveau stimuli.

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, le schma quivalent est donn ci-dessus. 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.

112

Pressons donc le bouton <RB0 (H)> 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. Nous allons maintenant simuler la pression du bouton-poussoir : Pressez le bouton <RB0 (L)> pour envoyer 0 sur RB0. Revenez dans lditeur et pressez une seule fois sur <F7>. Linstruction qui suit lvnement est alors linstruction situe ladresse 0x04, car le passage de 1 0 sur RB0 a provoqu notre interruption. Avancez lentement par pressions de <F7> dans la routine dinterruption. Examinez leffet des diffrentes instructions vues. Une fois la ligne :

xorwf PORTA , f ; inverser RA2

excute, vous constatez que la LED sest allume (RA2 est pass 1 sur le registre PORTA). Avancez lentement jusqu ce que la ligne :
retfie ; return from interrupt

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>. Que se passe-t-il ? Au lieu de revenir au programme principal, nous recommenons une nouvelle interruption. 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. 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). 12.15 Premire correction : reset du flag Il nous faut donc ajouter la ligne suivante dans notre sous-routine intrb0
bcfINTCON , INTF ; effacer flag INT/RB0

Nous obtenons donc :

113

movlw B'00000100' BANK0

xorwf PORTA , f bcf INTCON , INTF return

; ; ; ; ; ; ; ; ;

bit positionn = bit invers 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 inverser RA2 effacer flag INT/RB0 fin d'interruption RB0/INT

Recompilons notre programme avec <F10>, puis <F6>, et enfin, recommencez toute la procdure que nous venons de voir. Vrifiez que la routine dinterruption se termine maintenant en rendant la main au programme principal. La LED 1 est maintenant allume (RA2 = 1). Pressez <RB0(H)> pour simuler le relchement du bouton-poussoir. Pressez quelques fois <F7> et pressez <RB0 (L)> pour simuler une seconde pression de bouton-poussoir. Suivez la routine dinterruption et constatez que cette fois la LED steint. On obtient donc au simulateur le fonctionnement suivant : - Une pression sur le B.P. (bouton-poussoir) allume la LED - Une autre pression teint la LED - Et ainsi de suite. Nous avons donc obtenu le rsultat souhait. 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-til ? 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 ? Elle 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. Le PIC est donc plus rapide que notre B.P. Noubliez donc jamais que les PICs ne travaillent pas une chelle de temps humaine. Vous devez en tenir compte.

114

12.17 Le problme de lanti-rebond Comment remdier ce problme ? Et bien, tout simplement en attendant un temps suprieur au temps de rebondissement avant dautoriser une nouvelle interruption sur RB0. Nous allons utiliser nos connaissances actuelles pour rsoudre ce problme. Il devient utile de dessiner un ordinogramme de ce que nous voulons faire :

Explications 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 principale 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 moment spcifiques.

115

12.18 Finalisation du programme Tout dabord, il nous faut une routine de temporisation. Ouvrez le fichier Led_cli.asm et effectuez un copier/coller de la routine de temporisation.
;********************************************************************* ; 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 :
;********************************************************************* ; 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.

116

;********************************************************************* ; DECLARATIONS DE VARIABLES * ;********************************************************************* CBLOCK 0x00C w_temp :1 status_temp : 1 cmpt1 : 1 cmpt2 : 1 flags : 1 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; dbut de la zone variables Sauvegarde de W dans interruption Sauvegarde de STATUS dans interrupt compteur de boucles 1 dans tempo compteur de boucles 2 dans tempo un octet pour 8 flags rservons b0 pour le flag tempo b1 : libre b2 : libre b3 : libre b4 : libre b5 : libre b6 : libre b7 : libre Fin de la zone

ENDC #DEFINE tempoF , 0

; Dfinition du flag tempo

Modifions notre programme principal en suivant notre ordinogramme. Nous obtenons :


;********************************************************************* ; 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 ; boucler goto start END ; directive fin de programme

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 117

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. Une fois la routine dinterruption termine, les interruptions sont invalides. Linterrupteur rebondi sans causer dappel dinterruption. MAIS SON FLAG EST POSITIONNE cause des rebonds. Souvenez-vous que les bits Enable nagissent pas sur les flags. Donc, ds que le programme principal remet linterruption en service, une interruption est gnre directement, INTF ayant t positionn avant. 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 le reset du flag INTF avant de remettre les interruptions INT en service. bcf INTCON , INTF ; effacer flag INT

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. A titre de bonus, voici le schma dun tlrupteur oprationnel fonctionnant avec votre programme.

118

Remarque sur notre 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. 12.19 Remarques importantes 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. En consquence, VOUS NE POUVEZ PAS UTILISER de calcul de temps en utilisant le calcul du nombre dinstructions dans toute partie de code dans lequel une interruption risque de survenir. Notre sous-routine de temporisation de Led-cli , par exemple, donnerai un dlai qui risquerait dtre allong. Dans ce programme, cependant, les interruptions ne sont plus en service au moment de lexcution de cette temporisation. Voyez lordinogramme. 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. 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. VOUS NE POUVEZ DONC JAMAIS ETRE CERTAIN PAR SIMULATION QUE VOTRE PROGRAMME EST COMPLETEMENT DEBUGGE. 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.

119

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 Au terme de ce chapitre, vous pouvez apprhender les mcanismes dinterruption et leur mise en uvre. Nous utiliserons encore cette possibilit dans la leon sur le timer. Jespre avoir dmystifi 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. Lutilisation des interruptions impose de ce fait la parfaite comprhension des mcanismes mis en place, et vous oblige envisager toutes les possibilits au niveau de la survenance dun vnement extrieur. Ceci est surtout vrai pour les programmes avec plusieurs sources dinterruptions. Je vous conseille donc fortement, lors de la ralisation de programme complexe, de commencer par crire une algorithme gnral, soit en franais, soit en utilisant des ordinogrammes.

120

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. 13.1 Les diffrents modes de fonctionnement 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. T0CS = 1 : Fonctionnement en mode compteur T0CS = 0 : Fonctionnement en mode timer 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. T0SE = 0 : comptage si lentre RA4/TOKI passe de 0 1 T0SE = 1 : comptage si lentre RA4/TOKI passe de 1 0 13.2 Le registre tmr0 Ce registre, qui se localise ladresse 0x01 en banque0, contient tout simplement la valeur actuelle du timer0. Vous pouvez crire ou lire tmr0. Si par exemple vous avez configur tmr0 en compteur, la lecture du registre tmr0 vous donnera le nombre dvnements survenus sur la pin RA4/TOKI. 13.3 Les mthodes dutilisation du timer0 Comment utiliser le timer0, et quelles sont les possibilits offertes ce niveau, voil de quoi nous allons parler ici.

121

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 :
Clrf tmr0 Xxx movf tmr0 , w movwf mavariable ; ; ; ; dbut du comptage ici un certain nombre dinstructions charger valeur de comptage sauver pour traitement ultrieur

13.3.2 Le mode de scrutation du flag 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 :
clrf bcf loop btfss goto xxx tmr0 INTCON , T0IF INTCON , T0IF loop ; dbut du comptage ; effacement du flag ; tester si compteur a dbord ; non, attendre dbordement ; poursuivre : 256 vnements couls

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 movwf bcf loop btfss goto xxx 256-100 tmr0 INTCON,T0IF INTCON,T0IF loop ; charger 256 100 ; initialiser tmr0 ; effacement du flag ; tester si compteur a dbord ; non, attendre dbordement ; oui, poursuivre : 100 vnements couls

122

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. 13.3.4 Les mthodes combines 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 : 1) 2) 3) 4) A la premire impulsion sur RB0, on lance le timer 0 en mode interruptions. A chaque interruption de tmr0, on incrmente une variable A la seconde interruption de RB0, on lit tmr0 et on arrte les interruptions Le temps total sera donc (256*variable)+tmr0

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 interruptions. Nous aurons donc une interruption toutes les 256s, soit peut prs toutes 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 . Quest-ce donc ? Et bien, tout simplement un diviseur dvnements situ AVANT lentre de comptage du timer0. Nous pourrons donc dcider davoir incrmentation de tmr0 tous les 2 vnements par exemple, ou encore tous les 64 vnements. Regardez 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, quand lui, dtermine si le prdiviseur est affect au timer0 ou au watchdog. Voici un tableau exprimant toutes les possibilits de ces bits :

123

PSA PS2 PS1 PS0 /tmr0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 2 4 8 16 32 64 128 256 1 1 1 1 1 1 1 1

/WD Temps tmr0 1 1 1 1 1 1 1 1 1 2 4 8 16 32 64 128 512 s 1024 s 2048 s 4096 s 8192 s 16384 s 32768 s 65536 s 256 s 256 s 256 s 256 s 256 s 256 s 256 s 256 s

Temps typique Watchdog (minimal) 18 ms (7ms) 18 ms (7ms) 18 ms (7ms) 18 ms (7ms) 18 ms (7ms) 18 ms (7ms) 18 ms (7ms) 18 ms (7ms) 18 ms (7ms) 36 ms (14 ms) 72 ms (28 ms) 144 ms (56 ms) 288 ms (112 ms) 576 ms (224 ms) 1,152 Sec (448 ms) 2,304 Sec (996 ms)

PSA PS0 sont les bits de configuration du prdiviseur /tmr0 indique la valeur du prdiviseur rsultante sur le timer0 /WD indique la valeur du prdiviseur rsultante sur le Watchdog temps tmr0 indique le temps max entre 2 interruptions tmr0 avec quartz de 4MHz Temps watchdog indique le temps typique disponible entre 2 reset watchdog (indpendant du quartz utilis). La valeur entre parenthses indique le temps minimal, qui est celui utiliser pour faire face toutes les circonstances.

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.

- Il nexiste pas de prdiviseur = 1 pour le timer0. Si vous ne voulez pas utiliser le prdiviseur, vous devez donc imprativement le slectionner sur le watchdog avec une valeur de 1 (ligne verte du tableau). 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.

124

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 Faites un copier/coller de votre nouveau fichier m16f84.asm et renommez cette copie Led_tmr.asm . Relancez MPLAB et crez un nouveau projet intitul Led_tmr.pjt . Ajoutez-y votre nud Led_tmr.asm . Crez votre en-tte (je continue dinsister)
;********************************************************************** ; * ; 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 * ;**********************************************************************

Dfinissez ensuite les _CONFIG en plaant le watch-dog hors service. Calculons ensuite le nombre de dbordement de tmr0 ncessaires. Nous avons besoin dune temporisation de 500 ms, soit 500.000s. 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.

125

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 :
OPTIONVAL EQU H'0087' ; Valeur registre option ; Rsistance pull-up OFF ; Prscaler timer 256

Ensuite nous devons dterminer la valeur placer dans le registre INTCON pour obtenir les interruptions sur le timer0. Ce sera B10100000, soit 0xA0
INTERMASK EQU H'00A0' ; Interruptions sur tmr0

Ensuite, nos dfinitions :


;********************************************************************* ; DEFINE * ;********************************************************************* #DEFINE LED PORTA,2 ; LED

Ne touchons pas notre routine dinterruption principale, car nous avons suffisamment de place pour conserver nos tests. 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.
cmpt : 1 ; compteur de passage

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 intialiser 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. Nous obtenons donc :

126

;********************************************************************* ; INITIALISATIONS * ;********************************************************************* init clrf PORTA ; Sorties portA 0 clrf PORTB ; sorties portB 0 BANK1 ; passer banque1 clrf EEADR ; permet de diminuer la consommation movlw OPTIONVAL ; charger masque movwf OPTION_REG ; initialiser registre option ; Effacer RAM ; -----------movlw 0x0c movwf FSR init1 clrf INDF incf FSR,f btfss FSR,6 goto init1 btfss FSR,4 goto init1

; initialisation pointeur ; pointeur d'adressage indirect ; ; ; ; ; ; effacer ram pointer sur suivant tester si fin zone atteinte (>=0x40) non, boucler tester si fin zone atteinte (>=0x50) non, boucler

; initialiser ports ; ----------------bcf LED ; passer LED en sortie BANK0 ; passer banque0 movlw INTERMASK movwf INTCON ; masque interruption ; charger interrupt control

; initialisations variables ; ------------------------movlw 7 ; charger 7 movwf cmpt ; initialiser compteur de passages goto start ; sauter programme principal

13.5.3 La routine dinterruption Ralisons donc maintenant notre routine dinterruption : Tout dabord, on dcrmente notre compteur de passage, sil nest pas nul, on na rien faire cette fois.
decfsz return cmpt , f ; dcrmenter compteur de passages ; pas 0, on ne fait rien

Ensuite, si le rsultat est nul , nous devons inverser la LED et recharger 7 dans le compteur de passages. Voici le rsultat final :

127

;********************************************************************** ; 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

Il ne nous reste plus qu effacer la ligne


clrwdt ; effacer watch dog

du programme principal, puisque le watchdog nest pas en service. Compilez votre programme. Nous allons maintenant le passer au simulateur. Noubliez pas de mettre le simulateur en service, et ouvrez la fentre des registres spciaux. Avancez ensuite votre programme en pas pas jusqu ce quil arrive dans le programme principal. Remarques Le dernier registre en dans la fentre des registres spciaux T0pre est en rouge car cest 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.

13.6 Modification des registres dans le simulateur Comme nous nallons pas passer des heures simuler ce programme, nous allons modifier les registres en cours de simulation. Allez dans le menu Windows et slectionnez Modify La fentre ci-dessous souvre.

128

Cette fentre vous permet de modifier un registre (ou un emplacement mmoire ) en y inscrivant la valeur de votre choix. Nous allons nous servir de cette possibilit. Premirement, supprimons le prdiviseur. Pour ce faire, nous allons crire B10001000, soit 0x88. Choisissez donc OPTION_REG comme adresse, 88 comme data et Hex comme radix. Pressez <Write> et vrifiez que votre registre option est bien pass 0x88.

Maintenant, chaque pression de <F7> incrmente tmr0 (pas de prdiviseur) Ouvrez ensuite une fentre de visualisation des variables, avec window->watch->new watch window . Choisissez dafficher la variable cmpt . Cliquez <Add>.

Continuez de presser <F7> et constatez que le dbordement de tmr0 provoque une interruption et que cette interruption provoque la dcrmentation de cmpt. Pour ne pas attendre trop longtemps, servez-vous de la fentre modify pour positionner cmpt 1. Ensuite, poursuivez la simulation. Vous constaterez que la prochaine interruption provoque la modification de RA2. 13.7 Mise en place sur la platine dessais 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. En ralit, vous aurez un allumage toutes les (256*256*7*2) = 917504S. En 1 minute, on devrait obtenir : 60.000.000/917504 = 65,3 allumages. La thorie rejoint la pratique. Le fichier est fourni sous la dnomination led_tmr1.asm .

129

13.8 Premire amlioration de la prcision Nous allons chercher amliorer la prcision de notre programme. Nous pouvons commencer par modifier notre prdiviseur. Essayons plusieurs valeurs successives : /1 : donne 500000/256 = 1953,125 passages. Pas pratique /2 : donne 500000/512 = 976,5625 passages. Pas plus pratique /4 : donne 500000/1024 = 488,28125 passages . Idem /8 : donne 500000/2048 = 244,140625 passages. Dans ce cas, un seul compteur est galement ncessaire, car le nombre de passages est infrieur 256. Quelle va tre la prcision obtenue ? Et bien, nous initialiserons cmpt 244, avec prdiviseur 8. Dans ce cas, la dure obtenue sera de : 256*8*244 = 499712 s, donc 499712*2 = 999424s par allumage. 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
TIMEBASE EQUD244 ; base de temps = 244 dcimal

Si vous avez un problme, le fichier fonctionnel de cet exercice est disponible sous la dnomination Led_tmr.asm . Avantages obtenus : Une plus grande prcision 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.

13.9 Seconde amlioration de la prcision 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 : On dtecte 1953 passages laide de plusieurs compteurs Lors du 1953me passage, on en est 1953*256 = 499968 s, il nous manque donc : 500.000 - 499.968 = 32s. On ajoute donc 256-32 = 224 tmr0, de la faon suivante :
130

movlw 224 addwf tmr0 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. 13.10 La bonne mthode - Adaptation de lhorloge 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. Il suffit donc de recalculer lenvers : Que doit durer une instruction ? 1000000/(256*256*7*2) = 1,089913504s. 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.

131

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. 13.12 Exemple dutilisation de 2 interruptions 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.

132

Nous aurons donc une interruption pour RB0, et une autre pour tmr0. Vous voyez cidessous lordinogramme qui va nous servir. Effectuez une copie de votre fichier m16f84.asm et renommez-le telerupt.asm . Crez un nouveau projet telerupt.pjt . Editez votre fichier comme prcdemment : coupure du watchdog, positionnement de la LED en sortie, mise en service initiale des interruptions RB0/INT. Crez votre routine dinterruption timer0 toutes les 260ms, soit prdiviseur 256, et 4 passages . Essayez de raliser vous-mme ce programme. Chargez-le dans votre PIC et lancez-le. Notez que lordinogramme ne contient pas le compteur de passages dans tmr0. Je vous laisse le soin de rflchir. 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. 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.

133

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. 14.1 Taille et localisation de la mmoire eeprom 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. Notez dj que si ces emplacements ne sont pas accessibles directement par le programme, par contre ils le sont au moment de la programmation. Vous pourrez donc initialiser votre zone eeprom au moment de programmer votre composant. 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 ? De mme, ladresse 0x2006 contient lidentification du composant. Cest ainsi quun programmateur volu peut faire la distinction entre un 16F84 et un 16F84A, car leur identification constructeur diffre. Le 16F84 dispose de 64 emplacements eeprom disponibles pour votre libre usage. Nous allons voir comment les utiliser. 14.2 Prparation du programme Commencez par effectuer un copier/coller de votre fichier Led_tmr1.asm et renommez cette copie en eep_test.asm . Construisez votre nouveau projet dans MPLAB avec le mme nom et ajoutez-y ce nud. Editez la zone den-tte du programme

134

;********************************************************************** ; * ; 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.
reload : 1 ; valeur recharger dans 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 : On initialise un emplacement eeprom eereload avec la valeur 0x07 lors de la programmation Au dmarrage, on lit leeprom eereload et on place son contenu dans reload Le contenu de reload est utilis pour recharger le cmpt une fois celui-ci arriv 0.

Avantage de la procdure : si on modifie la valeur de la base de temps dans leeprom, cette modification ne sera pas perdue au moment de la remise sous tension de leeprom. Je vous donne lordinogramme de ce que nous allons raliser dans un premier temps.

135

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 return BANK0 movlw xorwf movf movwf return cmpt , f b'00000100' PORTA , f reload , w cmpt ; ; ; ; ; ; ; ; dcrmenter compteur de passages pas 0, on ne fait rien par prcaution slectionner bit inverser inverser LED charger valeur contenue dans reload dans compteur de passages fin d'interruption timer

14.3 Initialisation de la zone eeprom Nous voyons sur notre ordinogramme que nous lisons notre eeprom afin de placer le contenu dans notre variable. Mais nous devons bien quand 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 ?

136

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
#DEFINE eereload 0x00 ; adresse eeprom de eereload

ou encore
eereload EQU 0x00

Dans notre ordinogramme nous allons avoir besoin de lire leeprom. 4 registres sont utiliss pour accder leeprom. Nous allons maintenant les examiner. 14.4 Le registre EEDATA 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 banque0.

137

14.5 Le registre EEADR Dans ce registre, situ ladresse 0x09 banque0, 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. 14.6 Le registre EECON1 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 WRite ENable. Autorisation de dmarrage du cycle dcriture 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 Remarque : Dans le cas o le cycle dcriture serait interrompu suite au dpassement du watchdog ou un reset, vous pouvez lire le bit WRERR qui vous le signalera. Les registres EEDATA et EEADR demeurent inchangs et vous pouvez relancer le cycle dcriture. Ceci ne fonctionne videmment pas pour une coupure de tension. Dans ce cas, je vous expliquerai ma mthode personnelle de vrification la fin de ce chapitre.

138

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. 14.8 Accs en lecture dans la mmoire eeprom 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 banque0 pour appeler cette macro, et elle vous retourne la valeur lue dans le registre W.
READEE movlw movwf bsf bsf bcf movf endm macro adeeprom adeeprom EEADR STATUS , RP0 EECON1 , RD STATUS , RP0 EEDATA , w ; ; ; ; ; ; ; ; macro avec 1 paramtre (argument) charger adresse eeprom (argument reu) adresse lire dans registre EEADR passer en banque1 lancer la lecture EEPROM repasser en banque0 charger valeur lue dans W 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 :
READEE eereload ; lecture de ladresse eereload de leeprom

Lira leeprom ladresse eereload, cest dire ladresse 0x00. Cette macro, comme toutes les modifications principales, seront ajoutes votre fichier m16f84.asm. Je vous le fournis modifi sous la dnomination m16f84_n2.asm . A partir de la prochaine leon, il remplacera votre fichier m16F84.asm actuel. 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 :

139

; 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. 14.9 Laccs en criture la zone eeprom 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. La procdure suivre consiste dabord placer la donne dans le registre EEDATA et ladresse dans EEADR. Ensuite une squence spcifique (il ny a rien comprendre, cest impos par le constructeur) doit tre envoye au PIC. Remarques Microchip recommande que cette procdure spcifique ne soit pas interrompue par une interruption, donc nous couperons les interruptions durant cette phase. A la fin de la procdure dcriture, la donne nest pas encore enregistre dans leeprom. Elle le sera approximativement 10ms plus tard (ce qui reprsente tout de mme pas loin de 10.000 instructions). Vous ne pouvez donc pas crire une nouvelle valeur en eeprom, ou lire cette valeur avant davoir vrifi la fin de lcriture prcdente. 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.

140

WRITEE LOCAL movwf movlw movwf loop bcf btfsc goto bsf bcf bsf movlw movwf movlw movwf bsf bcf bsf bcf endm

addwrite macro loop EEDATA addwrite EEADR INTCON INTCON loop STATUS EECON1 EECON1 0x55 EECON2 0xAA EECON2 EECON1 EECON1 INTCON STATUS , GIE , GIE , RP0 , EEIF , WREN

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

la donne se trouve dans W tiquette locale placer data dans registre charger adresse d'criture placer dans registre interdire interruptions tester si GIE bien 0 non, recommencer passer en banque1 effacer flag de fin d'criture autoriser accs criture charger 0x55 envoyer commande charger 0xAA envoyer commande lancer cycle d'criture verrouiller prochaine criture rautoriser interruptions repasser en banque0

, , , ,

WR WREN GIE RP0

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. La procdure dcriture en eeprom est relativement longue et prend normment de temps. Pensez que pour remplir la zone complte de 64 octets, il faudra plus de 6/10me de seconde. 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.

141

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. cmpt2 : 1 ; compteur de passages 2

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. Un petit mot sur le bug des interdictions dinterruption sur le 16C84 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. Comme retfie remettait automatiquement le bit GIE 1, linterruption tait remise en service linsu du programmeur. 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. A partir du 16F84, les interruptions sont interdites ds linstruction excute, et donc avant lexcution de linstruction suivante . Le bug nexiste donc plus.

142

Voici le nouvel ordinogramme obtenu.

Et la routine dinterruption timer :


;********************************************************************** ; 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 ; recharger compteur de passages ; -----------------------------movf reload , w ; charger valeur contenue dans reload movwf cmpt ; dans compteur de passages ; incrmenter compteur de passages 2 ; ---------------------------------incf cmpt2 , f ; incrmenter compteur de passages2 return ; fin d'interruption timer

Nous allons crire dans leeprom depuis notre programme principal. Il y a deux raisons ne pas crire dans leeprom depuis notre routine dinterruption timer.
143

- 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. Voyons donc notre programme principal :
;********************************************************************* ; 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 ; Tester si criture prcdente eeprom termine ; -------------------------------------------------------; facultatif ici, car le temps coul ; est largement suffisant BANK1 ; passer banque1 wait btfsc EECON1 , WR ; tester si criture en cours goto wait ; oui, attendre BANK0 ; repasser en banque 0 ; crire contenu de reload en eeprom ; -------------------------------------------movf reload , w ; charger reload WRITEE eereload ; crire l'adresse 0x00 goto start ; boucler END ; directive fin de programme

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. Estimez la frquence de clignotement en cours, et coupez lalimentation du PIC. Attendez quelques secondes, et remettez le PIC sous tension. La LED clignote la frquence prcdente, car le paramtre a t sauvegard en EEPROM . Le fichier tel quil devrait tre la fin de cette leon est disponible sous la dnomination eep_test.asm

144

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. Voici une procdure qui permet den tre certain. 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. Puis nous crivons notre ou nos donne(s) dans leeprom Pour finir, nous rinscrivons notre en-tte dans leeprom. 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.

145

15. Le watchdog
Le watchdog, ou chien de garde est un mcanisme de protection de votre programme. Il sert surveiller si celui-ci sexcute toujours dans lespace et dans le temps que vous lui avez attribus. 15.1 Le principe de fonctionnement La mise en service ou larrt du watchdog se dcide au moment de la programmation de votre PIC, laide de la directive _CONFIG. Si _WDT_OFF est prcis, le watchdog ne sera pas en service. Si au contraire vous prcisez _WDT_ON , le watchdog sera actif. IL NEST DONC PAS POSSIBLE DE METTRE EN OU HORS SERVICE LE WATCHDOG DURANT LEXECUTION DE VOTRE PROGRAMME. Le fonctionnement du watchdog est li un timer interne spcifique, qui nest pas synchronis au programme, ni un vnement extrieur. La dure spcifique de dbordement de ce timer est approximativement de 18ms. Cette valeur est prendre avec prcaution, car elle varie en fonction de diffrents paramtres comme la tension dalimentation ou la temprature. 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. 15.2 Le prdiviseur et le watchdog 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.

146

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. 15.3 Les rles du watchdog 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. 15.4 Utilisation correcte du watchdog 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, celuici 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. 15.5 Ce quil ne faut pas faire Souvenez-vous quune interruption interrompt le programme et branche ladresse 0x04. Une fois linterruption termine, le programme est reconnect lendroit o il se trouvait, mme si cest hors de votre zone normale de programme.
147

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 : IL NE FAUT JAMAIS UTILISER LINSTRUCTION CLRWDT DANS UNE ROUTINE DINTERRUPTION. 15.6 Mesure du temps rel du watchdog 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 ? Nous allons tenter de rpondre cette question. Effectuez un copier/coller de votre fichier Led_cli.asm . Renommez ce fichier en wdt.asm et crez un nouveau projet. Dans un premier temps, ne touchez pas la _CONFIG Modifiez la valeur du registres OPTION
OPTIONVAL EQUB'10001111' ; Valeur registre option ; Rsistance pull-up OFF ; prscaler Wdt = 128

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
clrwdt ; effacer watchdog

Juste aprs ltiquette init pour tre bien sr de remettre le watchdog 0 (en ralit, inutile).
148

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

Compilez le programme, chargez-le dans votre PIC, et alimentez votre platine. Que se passe-t-il ? Et bien, aprs approximativement seconde, la LED sallume, et cest tout. Il ne se passe plus rien. Cest bien ce que nous avions prvu. Modifiez maintenant la ligne _CONFIG pour mettre le watchdog en service :
__CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC

Recompilez votre programme, et rechargez-le dans votre PIC. Alimentez votre montage. Que se passe-t-il ? Et bien maintenant la LED clignote. Vous constaterez probablement que le temps sparant deux extinctions (ou deux allumages) est approximativement 2secondes. 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. 15.7 Simulation du plantage dun programme Effectuez de nouveau une copie de votre fichier Led_cli.asm et renommez cette copie secur.asm . Crez un nouveau projet. Changez la ligne de configuration :

149

OPTIONVAL

EQU

H'000F'

; Valeur registre option ; Rsistance pull-up ON ; Prscaler wdt 128

et le DEFINE (vu que nous avons modifi notre platine)


#DEFINE BOUTON PORTB,0 ; bouton-poussoir

Modifiez ensuite votre programme principal :


start bsf call bcf call btfsc goto plante goto END LED tempo LED tempo BOUTON start plante ; ; ; ; ; ; ; ; ; ; allumer la LED appeler la tempo de 0.5s teindre LED (LEDOFF) appeler la tempo de 0.5s tester bouton-poussoir pas press, boucler le programme n'est pas sens arriver ici simulation de plantage directive fin de programme

De cette manire, une pression du bouton-poussoir envoie le programme dans une zone que nous avons cre et qui simule un plantage du programme sous forme dune boucle sans fin. Compilez le programme et chargez-le dans votre PIC. Alimentez le montage : la LED clignote. Maintenez un instant le bouton-poussoir enfonc, la LED sarrte de clignoter, le programme est dans une boucle sans fin qui simule dans notre cas le plantage suite, par exemple, un parasite qui a ject notre programme hors de sa zone de fonctionnement normal. 15.7.1 Correction avec utilisation du watchdog Modifions maintenant notre programme. Tout dabord, nous mettons le watchdog en service, comme vu prcdemment dans la _CONFIG. Nous allons ensuite nous arranger pour remettre notre watchdog 0 intervalles rguliers. Voici donc notre programme principal modifi :

150

start bsf LED clrwdt call tempo bcfLED clrwdt call tempo btfsc BOUTON goto start plante goto plante END

; ; ; ; ; ; ; ; ; ; ; ;

allumer la LED effacer watchdog appeler la tempo de 0.5s teindre LED (LEDOFF) effacer watchdog appeler la tempo de 0.5s tester bouton-poussoir pas press, boucler le programme n'est pas sens arriver ici simulation de plantage 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 sousroutine tempo . Recompilons notre programme, et rechargeons le PIC. Lanons lalimentation. La LED clignote toujours. Pressez le bouton quelques instants, la LED sarrte de clignoter un instant, puis recommence de nouveau. La watchdog a rcupr le plantage de votre programme. 15.8 Choix de la valeur du prdiviseur En gnral, il faut essayer de calculer le prdiviseur de faon ne pas devoir placer de commande clrwdt en de trop nombreux endroits. Il faut galement tenir compte du temps de raction obtenu en augmentant le prdiviseur. Si une rcupration de plantage en 2 secondes vous convient ou si votre programme ncessite une rcupration en 18ms max conditionnera la valeur du prdiviseur utiliser. Tout est donc histoire de compromis. 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.

151

15.9 Temps typique, minimal, et maximum Nous avons vu apparatre plusieurs notions de temps de watchdog. Il est important de bien effectuer la distinction entre les diffrentes valeurs. Je vais donc rcapituler ici : 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. ATTENTION : Le watchdog utilis en protection dans le cas dune programmation correcte et dune carte bien conue ne devrait jamais entrer en fonctionnement. Il nagira donc en gnral que dans de trs rares occasions (parasites violents, orage). Il ne doit pas servir masquer une erreur de conception de votre programme. Celui-ci doit pouvoir fonctionner sans le secours du watchdog. Je vous conseille donc de raliser vos programmes de la faon suivante : 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).

152

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. 16.1 Principe de fonctionnement 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 : Le watchdog est remis 0, exactement comme le ferait une instruction clrwdt . Le bit TO du registre STATUS est mis 1. Le bit PD du registre STATUS est mis 0. Loscillateur est mis larrt, le PIC nexcute plus aucune instruction.

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. Pour profiter au maximum de la chute de la consommation (montage sur piles par exemple), Microchip recommande de veiller ce que les pins dentres/sorties et llectronique connecte soient des niveaux 0 ou 1 tels quil ny ait aucun passage de courant qui rsulte du choix de ces niveaux. Ceci vous montre que les niveaux prsents sur les pins au moment de la mise en mode sleep restent dapplication. 16.2 La sortie du mode sleep 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.
153

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. Apparition dune interruption RB0/INT, RB ou EEPROM.

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. 16.3 Rveil avec GIE hors service. 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 . 16.4 Rveil avec GIE en service Dans le cas o votre bit GIE est positionn, un rveil suite une interruption entranera la squence suivante. Linstruction qui suit linstruction sleep est excute. Le programme se branche ensuite ladresse 0x04 comme une interruption ordinaire.

Notez que si vous ne voulez pas excuter linstruction qui suit linstruction sleep , il vous suffit de placer cet endroit une instruction nop . 16.5 Mise en sommeil impossible 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.

154

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. 16.6 Utilisation du mode sleep Nous allons raliser un petit exercice sur la mise en veille de notre PIC. Effectuez un copier/coller de votre nouveau fichier m16F84.asm et renommez-le en sleep.asm Crez un nouveau projet. Placez le prdiviseur sur le watchdog avec une valeur de 32. Ceci nous donne une valeur typique de dbordement de 18ms*32 = 576 ms.
OPTIONVAL EQU H'008D' ; Valeur registre option ; Prscaler wdt 32

Dfinissez votre LED sur la pin RA2


#DEFINE LED PORTA,2 ; LED de sortie

Placez ensuite votre LED en sortie dans la routine dinitialisation (attention, en banque1)
bcf LED ; LED en sortie

Ecrivons ensuite notre programme principal :


;********************************************************************* ; 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. 16.7 Cas typiques dutilisation Ce mode de fonctionnement est principalement utilis dans les applications dans lesquelles la consommation en nergie doit tre conomise (piles). On placera donc dans ce cas le PIC en mode Power Down ou sleep aussi souvent que possible.
155

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. 16.8 Conclusion Vous tes maintenant capable de placer un PIC en mode de sommeil afin dconomiser au maximum lnergie. Je ne doute pas que vous trouverez des tas dapplications pour ce mode trs pratique et trs simple grer.

156

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. Ceuxci tant parfaitement aptes comprendre une figure telle que la figure 3-1. Pour les autres, ceci napportera rien de plus lutilisation des PICs. Cette leon vous montrera du mme coup comment comprendre un datasheet. Comme les datasheet sont sans cesse mis jour chez Microchip, je joints la leon celui qui ma servi jusqu prsent pour faire ces cours, et qui sappelle 16F84.pdf 17.1 La structure interne 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. 17.2 La squence de dcodage 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. 17.3 Organisation de la mmoire 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.

157

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. 17.5 Llectronique des ports 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. 17.6 Le registre de configuration Le registre de configuration est situ ladresse 0x2007, hors de lespace dadressage normal du PIC. Il nest accessible quau moment de la programmation. Vous accdez ce registre laide de la directive _CONFIG , ou laide de la directive DA prcde de la directive ORG 0x2007 . A ce moment, la donne que vous indiquerez suite la directive DA prcisera le niveau des 14 bits utiles pour le 16F84 (5 bits pour le 16C84). 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). A titre dexemple, la ligne suivante : __CONFIG _CP_OFF & _WDT_ON & _PWRTE_ON & _HS_OSC Correspondra donc pour un 16F84 ceci : ORG 0x2007 DAB111111111111110 JE VOUS DECONSEILLE CE GENRE DE PRATIQUE, nous verrons plus bas pourquoi.

158

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 table 8-2 fait de mme pour les oscillateurs quartz. Notez que les bits cits sont intgrs dans les _HS_ OSC et autres configurations doscillateur. Cest ce qui explique que vous ne les ayez jamais rencontrs directement. 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. EVITEZ LES MODELES DE TYPE LS (74LS04), sous peine de dboires. 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. Reste le mode doscillateur avec rseau Rsistance Condensateur. Dans ce mode, loscillation est assure par deux composants passifs, sans ncessiter de quartz (pour raisons dconomie). 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. Par exemple, pour un quartz de 4MHz : T = 4 / 4000000 = 1 microseconde. Et rciproquement : F = 4 / T pour calculer la frquence qui correspond un temps de cycle calcul.

159

Donc, si je veux un temps de cycle de 1,5 s (microseconde), il me faudra une horloge cadence : F = 4 / (1,5*10-6) = 2,667 * 106 = 2,667 MHz (Mega Hertz) 17.7.1 La prcision de loscillateur 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. Commenons par le rseau RC. 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 : 86400 * 50 * 10-6 = 4,32 s. Voici dj un rsultat beaucoup plus acceptable. 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.

160

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. Evnement Mise sous tension MCLR la masse durant fonctionnement normal MCLR la masse durant mode sleep Reset par dpassement timer watchdog Sortie du mode sleep par dpassement watchdog Sortie du mode sleep par interrupt avec GIE = 0 Sortie du mode sleep par interrupt avec GIE = 1 Branchement (PC) 0x00 0x00 0x00 0x00 Suite programme (PC+1) PC + 1 PC + 1 puis 0x04 STATUS 00011xxx 000uuuuu 0001uuuu 00001uuu uuu00uuu uuu10uuu uuu10uuu

161

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). 17.9 La mise sous tension 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. Ce reset dclenche un timer interne et indpendant de la vitesse du PIC. Ce timer maintient le PIC larrt durant un temps typique de 72ms ds dtection de la condition de reset . Ce timer est appel PoWeR-up Timer ou PWRT. Il peut tre mis en ou hors service via le bit de configuration PWRTE. Je vous conseille de le mettre toujours en service, sauf si le temps de dmarrage sous tension tait critique pour votre application. 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 (par 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.

162

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. 17.10 Caractristiques lectriques 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. 17.11 Portabilit des programmes 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 imprativement utiliser les directives prvues (_CONFIG) au dtriment des accs directs style (ORG 0x2007). En effet, ces emplacements et leur contenu sont susceptibles de modifications dun modle lautre. 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.

163

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. 17.12 Les mises jour des composants A lappendice E, vous trouverez un tableau donnant les diffrences entre le 16C84 et le 16F84. Nous allons y jeter un il. 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. Viennent ensuite un avertissement sur quelques caractristiques lectriques du PIC. Cet avertissement vous renvoie aux diffrents tableaux des caractristiques lectriques. Directement aprs, encore une correction au niveau du fonctionnement du PORTA, lorsque le PIC tait utilis avec une frquence infrieure 500 KHz. Puis Microchip a ajout un trigger de Schmitt au niveau de lentre RB0 lorsquelle est utilise en interruption. Pour les non-lectroniciens, sachez simplement que cela limite le risque de fausse interruption suite un niveau incertain sur la pin. 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.

164

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 btfsc INTCON , GIE goto loop ; Arrter les interruptions ; Tester si une interruption na pas remis GIE 1 ; si, alors on recommence

Je vous en ai galement parl dans cet ouvrage. 17.13 Conclusion Vous voil maintenant en possession de la totalit des informations ncessaires pour dvelopper vos propres programmes en 16F84. Attention, il vous faudra cependant pratiquer avant de devenir un crack de la programmation. Vous vous direz souvent : cest pas possible, a devrait marcher, mon 16F84 est dfectueux . Dans 99% des cas, ce sera un bug de votre programme, que vous trouverez peut-tre aprs plusieurs jours de recherche. Ne vous dcouragez pas et relisez les documentations, mme si vous tes certains de les connatre par cur. 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. Je vous ai fourni le dictionnaire de rimes, vous dcrire les pomes

165

18. Astuces de programmation


Dans ce chapitre, nous allons examiner quelques mthodes simples pour se tirer de situations classiques. 18.1 Les comparaisons Quoi de plus simple que deffectuer une comparaison entre 2 nombres. Il suffit deffectuer une soustraction. Soit par exemple comparer mem1 avec mem2 : movf mem1 , w ; charger mem1 subwf mem2 , w ; soustraire mem2 mem1 Il vous suffit ensuite de tester les bits C et Z du registre STATUS pour connatre le rsultat : Si Z = 1 , les 2 emplacements mmoires contiennent la mme valeur Si Z = 0 et C = 1, le rsultat est positif, donc mem2 est suprieur mem1 Si Z = 0 et C = 0, le rsultat est ngatif, donc mem2 est infrieur mem1

Si vous dsirez simplement comparer lidentit entre 2 valeurs, sans modifier C, vous pouvez galement utiliser linstruction xor movf mem1 , w ; charger mem1 xorwf mem2 , w ; Si galit, tous les bits sont 0 et Z est 1 18.2 Soustraire une valeur de w 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.

166

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. X 0 1 0 1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 12 13 12 0 48 96 156

1 0

1 1 0

Quavons-nous effectu ? Et bien nous avons multipli 12 par chaque chiffre de 13 en commenant par la droite . Nous avons dcal dune range vers la gauche chaque rsultat intermdiaire avant sont addition finale. La particularit en binaire, cest quil ny a que 2 chiffres : 0 et 1. Donc on multiplie soit par 0 (ce qui revient ne rien faire) soit par 1 (ce qui revient simplement recopier le chiffre). Voici donc ce que nous obtenons en binaire : On multiplie 1100 par 1 . On obtient donc 1100 (D12) On multiplie 1100 par 0 et on dcale le rsultat vers la gauche. On obtient donc 0000 On multiplie 1100 par 1 et on dcale le rsultat vers la gauche. On obtient 1100 complt par 00, soit 110000, donc D 48 On multiplie 1100 par 1 et on dcale le rsultat vers la gauche. On obtient 1100 complt par 000, soit 1100000, donc D96. On additionne le tout et on obtient 10011100, soit D156.

Si on ralisait ce programme, il nous faudrait 4 variables supplmentaires pour stocker les rsultats intermdiaires. 8 dans le cas dune multiplication de 8 bits par 8 bits. On peut alors imaginer de se passer de ces rsultats intermdiaires en procdant laddition au fur et mesure du rsultat intermdiaire avec le rsultat final. On obtient alors lalgorithme suivant : On multiplie 1100 par 1. On place le rsultat dans rsultat final On multiplie 1100 par 0. On dcale une fois. On ajoute au rsultat final On multiplie 1100 par 1. On dcale 2 fois. On ajoute au rsultat final On multiplie 1100 par 1. On dcale 3 fois. On ajoute au rsultat final.

167

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 pseudocode 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 Bit suivant
168

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 :
clrf clrf movlw movwf movf movwf movf loop rrf btfsc addwf rrf rrf decfsz goto resulH resulL 0x08 cmpt multi , w multemp multan , w multemp , f STATUS , C resulH , f resulH , f resulL , f cmpt , f loop ; ; ; ; ; ; ; ; ; ; ; ; ; ; effacer rsultat poids fort idem poids faible pour 8 bits initialiser compteur de boucles charger multiplicateur sauver dans multemp multiplicande dans w dcaler multiplicateur vers la droite tester si bit sorti = 1 oui, ajouter au rsultat poids fort dcaler rsultat poids fort dcaler rsultat poids faible dcrmenter compteur de boucles pas fini, bit suivant

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. Rassurez-vous, cest avec lexprience que vous arriverez ce genre de rsultat. Ce petit programme est disponible sous la dnominations : multi.asm 18.4 Multiplication par une constante 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 :

169

Pour multiplier par 10, il faut : multiplier par 2 (donc dcaler loprande vers la gauche) multiplier encore par 2 (= multiplier par 4, donc dcaler encore une fois). Ajouter loprande originale (donc oprande + oprande*4 = oprande *5) Multiplier le rsultat par 2 (donc dcalage vers la gauche).

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. Ceci vous fera gagner un prcieux temps programme. 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 :
movf movwf bcf rlf rlf addwf rlf mem1 , w resul STATUS , C resul , f resul , f resul , f resul , f ; ; ; ; ; ; ; charger oprande sur 4 bits sauver dans rsultat effacer carry multiplier par 2 multiplier par 4 ajouter mem1, donc multiplier par 5 multiplier par 10

18.5 Adressage indirect pointant sur 2 zones diffrentes 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
movlw movwf movlw movwf loop movf movwf movlw addwf movf movwf movlw mem1 FSR 15 cmpt INDF , w tampon mem2-mem1 FSR , f tampon , w INDF (mem1-mem2)+1 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; on pointe sur la premire zone on initialise le pointeur sur la zone source 15 variables transfrer sauver dans compteur de boucles charger source on doit sauver dans un emplacement tampon cart dadresse entre les 2 emplacements pointer sur destination recharger valeur source sauver dans destination Ecart entre adresse de destination et adresse de la source suivante, do le +1 ajouter au pointeur dcrmenter compteur de boucles pas dernier emplacement, suivant

addwf FSR , f decfsz cmpt , f goto loop

170

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 :
CBLOCK 0x10 mem1 : 15 ENDC CBLOCK 0x30 mem2 : 15 ENDC ; on choisit une zone mmoire dans la RAM ; 15 emplacements pour la source ; on choisit une autre zone, mais pas au hasard ; 15 emplacements destination.

Ou encore, mais on ne voit pas bien lorganisation des zones utilises :


mem1 EQU 0x10 mem2 EQU 0x30

Maintenant, la source va de B00010000 B00011111 , et la destination de B00110000 B00111111 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. Nous pouvons donc modifier notre programme de la manire suivante :
movlw movwf movlw movwf loop movf bsf movwf bcf incf decfsz goto mem1 FSR 15 cmpt INDF , w FSR , 5 INDF FSR , 5 FSR , f cmpt , f loop ; ; ; ; ; ; ; ; ; ; ; on pointe sur la premire zone on initialise le pointeur sur la zone source 15 variables transfrer sauver dans compteur de boucles charger source on pointe sur destination sauver dans destination on pointe sur source pointer sur suivant dcrmenter compteur de boucles pas dernier emplacement, suivant

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. . 18.6 Les tableaux en mmoire programme 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. Le problme, cest que le 16F84, contrairement au 16F876, par exemple, ne dispose daucune mthode pour aller lire les donnes dans la mmoire programme. La seule mthode pour y avoir accs est dutiliser des instructions.
171

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 : On teste si le nombre pass en argument = 0. Si oui, on retourne 0 On teste si le nombre pass en argument = 1. Si oui, on retourne 1 On teste si le nombre pass en argument = 2. Si oui, on retourne 4 Et ainsi de suite

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 retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw retlw 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; carr carr carr carr carr carr carr carr carr carr carr carr carr carr carr carr de de de de de de de de de de de de de de de de 0 = 0 1 = 1 2 = 4 3 = 9 4 = 16 5 = 25 6 = 36 7 = 49 8 = 64 9 = 81 10 = 100 11 = 121 12 = 144 13 = 169 14 = 196 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

Donc, si on charge 4 dans w et quon effectue un appel call carre . Le programme se branche sur cette ligne, le PCL est incrment de 4 et le programme excute donc alors la ligne retlw 16 . Rappelez-vous, en effet, que le PC pointe toujours sur linstruction suivante, donc au moment de lexcution de addwf PCL , f , celui-ci pointait sur la ligne retlw 0 .

172

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 :

173

;********************************************************************* ; TABLEAU DES CARRES * ;********************************************************************* ;--------------------------------------------------------------------; Ne pas oublier de valider le radix dcimal par dfaut dans le nud ; principal du projet. 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 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

Compilez votre programme puis passez-le au simulateur. Vous constaterez. Que cela ne fonctionne pas. Pourquoi ? Et bien, en ralit, toute opration dont le PC est la destination fait intervenir PCLATH. Or nous avons laiss PCLATH 0. Ladresse de calcul nest donc pas la bonne. Avant le saut sous aurions du ajouter :

174

movlw 03 movwf PCLATH

Afin de permettre PCLATH de pointer sur la page 0x300 lors du calcul dincrmentation de PCL. Vous pouvez avantageusement remplacer la ligne org 0x300 par :
repere ORG (repere+31)& 0x3E0 ; adresse du tableau

Dans ce cas, pas besoin de modifier PCLATH car on reste en page 00 Le but de cette manipulation est dobtenir automatiquement la premire adresse disponible pour laquelle il ny aura pas de dbordement de notre PCL. Pour un tableau de 256 lments, utilisez ORG (repere+255) & 0x300. Faites des essais la main sur un bout de papier pour vous en convaincre. Par exemple, on calcule la fin du tableau (repere+255). Org pointe alors sur la bonne page. On limine ensuite les bits correspondants (255 = 8 bits) de la taille mmoire totale du programme (0x3FF). Reste donc & 0x300. Le fichier obtenu est disponible sous la dnomination tableau.asm 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. Nous aurions pu modifier le tableau en consquence, de faon que le premier lment du tableau pointe loffset 0 de la page de 8 bits .
org 0x2FF carre addwf PCL , f retlw 8 retlw 4 ; adresse du tableau (premire ligne retlw = 0x300) ; ajouter w PCL ; premier lment du tableau : adresse 0x300 ; second lment du tableau : adresse 0x301

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 org 0x300 retlw 8 retlw 4 ; ; ; ; ajouter w PCL (adresse = suite du programme principal) adresse effective du tableau(256 emplacements disponibles) premier lment du tableau : adresse 0x300 second lment du tableau : adresse 0x301

18.7 Les variables locales 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.
175

En fait, lutilisation de ce type de variable est trs simple et rduit considrablement le nombre de variables ncessaires dans un programme. Voici ma mthode personnelle dutilisation de ce type de variables. 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 premire sous-routine sappelle tempo , elle utilise 2 compteurs pour effectuer un comptage de temps. 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.

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. La variable rsultat de la sous-routine fonction devra tre conserv aprs excution de cette sous-routine, ce nest donc pas une variable locale. Nous dirons que cest une variable globale. Par contre, les 2 variables utilises pour les calculs intermdiaires ne seront plus daucune utilit. Ce sont des variables locales. 18.7.2 Construction sans variables locales Que serait notre zone de variables sans lutilisation des variables locales ? Et bien crons notre zone de variables :
CBLOCK 0X0C Cmpt1 : 1 Cmpt2 : 1 Resultat : 1 Interm1 : 1 Interm2 : 1 ENDC ; ; ; ; ; compteur compteur rsultat rsultat rsultat 1 pour routine tempo 2 pour routine tempo pour routine fonction intermdiaire1 pour fonction intermdiaire2 pour fonction

Nous voyons que nous aurons besoin de 5 variables. Utilisons maintenant les variables locales.

176

18.7.3 Construction avec 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 Local2 : 1 Resultat : 1 ENDC ; variable locale 1 ; variable locale 2 ; rsultat pour fonction

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.
#DEFINE #DEFINE #DEFINE #DEFINE cmpt1 Local1 cmpt2 Local2 interm1 Local1 interm2 Local2 ; ; ; ; compteur1 = variable locale1 compteur2 = variable locale2 rsultat intermdiaire1 = variable locale1 rsultat intermdiaire2 = variable locale2

Et voil, pas besoin du C pour utiliser les variables locales trs simplement. 18.8 Conclusion Vous voici en possession de quelques astuces de programmation. Le but tait de vous montrer les mthodes de raisonnement afin de vous permettre de dvelopper vos propres trucs et astuces.

177

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 dpourvue 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. 19.1 Spcificits utiles de la norme ISO 7816 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.

19.1.1 Les commandes ISO 7816 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.
178

La carte ne prend jamais linitiative de lchange dinformations. Elle ne fait que rpondre des commandes de la forme : CLASSE INSTRUCTION PARAMETRE1 PARAMETRE2 LONGUEUR Ou encore, sous forme abrge : C LASS INS P1 P2 LEN

Voici les significations de chacun des octets de la commande reue : CLASS : dtermine le groupe dinstructions concernes. Si le nombre dinstructions utilis nest pas lev, rien ninterdit de nutiliser quune seule classe. Cest ce que nous ferons dans cet exercice simplifi. INS : cest linstruction proprement dite, ou encore la commande. Cest cet octet qui dtermine lopration effectuer par la carte. P1 et P2 : sont 2 paramtres que la carte reoit avec la commande. Leur signification dpend de la commande envoye. Ils peuvent tre inutiliss mais doivent tout de mme tre prsents. 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). 19.1.2 Le protocole dchange dinformations Voici comment se droule un change standard dinformations entre le matre et la carte ISO 7816. 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). Le matre envoie la commande Class INS P1 P2 LEN La carte renvoie linstruction comme accus de rception INS Le matre envoie ventuellement les donnes complmentaires La carte envoie ventuellement la rponse La carte envoie le status et repasse en mode dattente de commande

179

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 envoie : 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 envoie : 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 envoie : D5 15 01 02 10 La carte rpond : 15 (accus de rception) Le matre envoie : 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. 19.2 Les liaisons srie asynchrones 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 : La vitesse de transmission en bauds Le format, cest dire le nombre de start-bits, de stop-bits, de bits de donnes et le type de parit

180

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 startbit. 19.2.2 Les bits de donne 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 donne, ce qui nous donne des valeurs admissibles de 0 0xFF pour chaque octet reu. 19.2.3 Le bit de parit Le bit de parit est une vrification du bon droulement du transfert. Lors de lmission, on comptabilise chaque bit de donne qui vaut 1. A la fin du comptage, on ajoute un bit 1 ou 0 de faon obtenir un nombre de bits total impair ou pair. On dira quon utilise une parit paire si le nombre de bits 1 dans les bits de donnes et le dans bit de parit est un nombre pair. De mme, une parit impaire donnera un nombre impair de bits 1. 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.

181

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. Le dbit maximum en octets par seconde est donc gal : Dbit maximum = 1 / (nbre de bits * dure dun bit), soit pour la norme ISO 7816 : 1 / 1250 * 10-6 = 800 octets par seconde. 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. 19.3 Acquisition des bits 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.

182

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. Une fois le bit de parit lu, nous avons 2 possibilits : 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. 19.4 Caractristique des cartes standard Sur les cartes du commerce, de type carte pour serrure code , les connexions utilises sont gnralement les suivantes : Nom pin MCLR VSS RB4 RB5 RB7 VDD CLKIN Pin 4 5 10 11 13 14 16 Signal RST GND SDA SCL DATA +5V CLK Rle du signal Type Commande de reset de la carte Entre Masse Alimentation data pour eeprom externe (24C16) Bi-directionnel horloge pour eeprom externe Sortie donnes mode srie half-duplex Bi-directionnel Alimentation +5V Alimentation Entre de lhorloge externe Oscillateur

19.5 Cration et initialisation du projet Suivant note mthode habituelle, copiez / collez votre fichier m16f84.asm et renommez la copie iso7816.asm . Crez votre projet dans MPLAB. Ensuite, crez votre en-tte de programme :
183

;*********************************************************************** ; 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.0 * ; 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 * ; * ;***********************************************************************

Dfinissons la configuration : Nous nallons pas utiliser le watch-dog pour cette application, et nous utiliserons une horloge externe. Nous aurons donc
LIST p=16F84 ; Dfinition de processeur #include <p16F84.inc> ; Dfinitions des constantes __CONFIG ; ; ; ; _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC Code protection OFF Timer reset sur power on en service Watch-dog hors service Oscillateur quartz grande vitesse

Calculons maintenant la valeur encoder dans notre registre OPTION : Nous devons utiliser, pour des raisons de compatibilit lectronique, la rsistance de rappel au +5V de la pin RB7. Nous aurons donc b7 du registre OPTION = 0. Ensuite, nous allons travailler avec le timer0. Comme lcart entre 2 bits est de 93 instructions, nous travaillerons sans prdiviseur, ce qui nous impose de rediriger le prdiviseur vers le watchdog. Dfinissons donc la valeur placer dans OPTION :
OPTIONVAL EQU 0x08 ; Valeur registre option ; Rsistance pull-up ON ; Prscaler timer 1

184

19.6 La base de temps Nous voyons dj que nous allons avoir besoin de 2 temporisations : une de 93 instructions et une de 93+46 instructions, correspondant 1 et 1,5 bits. Nous allons donc construire une sous-routine.
;********************************************************************* ; TEMPORISATION * ;********************************************************************* ;--------------------------------------------------------------------; temp_1bd: initialise tmr0 pour que la temporisation soit gale ; l'quivalent d'un bit et demi, soit 46+93 incrmentations ; de tmr0 le temps ncessaire pour arriver dans la routine ; temp_1b : Attend que l'cart entre la prcdente tempo et la tempo ; actuelle soit de 1 bit, soit 93 instructions ;--------------------------------------------------------------------temp_1bd movlw -40 ; prparer valeur tmr0 movwf TMR0 ; initialiser tmr0 call temp_suite ; et attendre 1/2 bit temp_1b movlw addwf -93 TMR0 , f ; cart entre 2 bits ; 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. Nous commenons par charger la dure correspondant 93 instructions avant le dbordement du timer, soit 0 93, ou encore plus simplement 93. Il ne faut cependant pas oublier quun certain nombre dinstructions ont dj t excutes depuis le dernier passage dans la routine timer, lors de la rception ou lmission du bit prcdent. 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 93 dans tmr0, mais bien AJOUTER 93 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.

185

Examinons maintenant le point dentre temp_1bd : Nous commenons par initialiser TMR0 avec 40, 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. 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. Ensuite nous appelons la sous-routine elle-mme de faon attendre la dure prvue, puis la sous-routine poursuit en excutant la temporisation de 93 cycles. Nous avons donc attendu en tout 93 + 40 cycles, soit la dure de 1,5 bit. De plus cette sous-routine nutilise aucune variable. 19.7 Rception dun octet 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. Notre sous-programme devra donc effectuer les oprations suivantes : Attendre le dbut du start-bit Attendre une dure de 93 + 46 instructions Pour chacun des 8 bits, lire le bit et le placer dans le caractre reu en bonne position Se positionner quelque part dans les stop-bits Voici donc notre sous-programme :

186

;********************************************************************* ; Rception d'un octet provenant du matre * ;********************************************************************* ;--------------------------------------------------------------------; Caractre lu dans W. La parit pas n'est pas vrifie ;--------------------------------------------------------------------Receive ; attendre dbut start-bit ; -----------------------btfsc SERIAL goto Receive ; Tester si start bit arriv ; non, attendre

; se positionner sur le milieu du 1er bit utile ; --------------------------------------------call temp_1bd ; attendre 1bit et demi

; rception du caractre ; ---------------------movlw 0x8 movwf cmptbts Recloop bcf STATUS , btfsc SERIAL bsf STATUS , rrf caract , call temp_1b decfsz cmptbts goto Recloop C ; pour 8 bits ; dans compteur de bits ; ; C ; f ; ; , f ; ; Carry = 0 tester si bit = 0 Carry = bit reu faire entrer le bit par la gauche attendre milieu caractre suivant dcrmenter compteur de bits pas dernier, suivant

; on pointe actuellement sur le centre du bit de parit ; reste donc attendre +- 1.5 bits pour tre dans le second stop-bit ; ------------------------------------------------------------------call temp_1bd movf caract , w return ; Attendre 1,5 bit ; charger caractre lu ; et retour

Ce sous-programme ne contient pas de difficults particulires. Remarquez que plutt que de positionner chaque bit reu directement la bonne position, on le fait entrer dans b7 en se servant dune instruction rrf . Le bit prcdent est de fait recul en b6 et ainsi de suite. Au final, le premier bit lu se retrouve donc en b0, le dernier restant en b7, ctait bien le but recherch. Concernant la dernire temporisation, nous pointons ce moment sur le centre du 9me bit, cest dire le bit de parit. Comme nous ne le traitons pas, inutile de le lire. Nous devons alors nous positionner sur un endroit o la ligne est repasse au niveau 1 , cest dire un des stop-bits, afin de pouvoir ventuellement commencer une attente dun nouveau caractre. Nous devons donc nous 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.
187

19.8 Lmission dun caractre 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. Il est important galement de se souvenir que nous travaillons en mode half-duplex, cest dire que la mme ligne sert pour les entres et les sorties. Comme chacun des interlocuteurs parle tour de rle, il faut laisser chacun le temps de repasser en lecture aprs lenvoi de son dernier message. Ceci sappelle temps de retournement . Il faut galement 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. Un bon compromis et la facilit dcriture du programme nous permet de choisir une attente de 1.5 bit avant de commencer mettre. Jai choisi cette valeur car cette temporisation permet dinitialiser le timer. Cette valeur nest cependant pas critique. Il faut simplement rpondre aprs que le matre soit plac en mode de rception, et avant quil ne considre que vote carte na pas rpondu. Notre programme va donc effectuer les oprations suivantes : Attendre temps choisi avant mission Passer en mission et envoyer le start-bit Envoyer les 8 bits en commenant par b0 Pour chaque bit 1 envoy, inverser la parit, pour obtenir une parit paire Envoyer la parit Envoyer les 2 stop-bits Repasser en rception Voici donc notre sous-programme :

188

;********************************************************************* ; 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 banque0 ; envoyer start-bit ; -------------------SERIAL ; envoyer 0 : start-bit parite ; effacer bit de parit ; pour 8 bits envoyer ; dans compteur de bits ; attente entre 2 bits

bcf clrf

movlw 8 movwf cmptbts call temp_1b

Send_loop rrf caract , f rrf caract , w andlw 0x80 xorwf parite , f xorwf PORTB , w xorwf PORTB , f call temp_1b decfsz cmptbts , f goto Send_loop

; envoyer 8 bits de data ; --------------------------; ; ; ; ; ; ; ; ; dcaler caractre, b0 dans carry carry dans b7 de w garder bit envoyer en position b7 positionner parit Garder 1 si changement sur SERIAL si oui, inverser RB7 attente entre 2 bits dcrmenter compteur de bits pas dernier, suivant

; envoyer parit ; -----------------movf parite , w ; xorwf PORTB , w ; xorwf PORTB , f ; call temp_1b ;

charger parit paire calcule Si serial diffrent de bit envoyer alors inverser RB7 attendre fin de parit

; envoyer 2 stop-bits ; ------------------BANK1 ; passer banque1 bsf SERIAL ; repasser en entre (et niveau haut) BANK0 ; passer banque0 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.

189

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 2 instructions :
xorwf xorwf PORTB , w PORTB , f ; Garder 1 si changement sur SERIAL ; si oui, inverser RB7

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 . Si nous appliquons W sur le PORTB en effectuant un xorwf , nous inverserons RB7 uniquement si b7 de W vaut 1, cest dire, en dautres mots : Nous inverserons RB7 uniquement si son niveau actuel est diffrent du niveau que nous devons envoyer. 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. 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 banque0

190

19.10 Envoi de lATR 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 ; 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 Lutilisation de la commande decfsz facilite lcriture des boucles, mais, comme le compteur de boucles est en mme temps loffset de la position en eeprom, lATR sera crit lenvers dans leeprom, cest dire du dernier vers le premier octet. A lendroit de lappel de la sous-routine Rd_eeprom , le compteur de boucles variera de 5 1. Or, notre adresse eeprom variera de 4 0. Donc, lopration decf permet de charger dans W la valeur du compteur de boucles 1. Le sous-routine Rd_eeprom nest rien dautre que notre macro de lecture de mmoire eeprom transforme en sous-programme. La voici :

191

;********************************************************************* ; Lecture d'un octet en eeprom interne * ;********************************************************************* ;--------------------------------------------------------------------; Lecture d'un octet de l'eeprom interne. L'adresse est passe dans w.octet lu est dans W ;--------------------------------------------------------------------Rd_eeprom 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 banque0 movf EEDATA , w ; charger valeur lue dans W return ; retour

Pensons galement inscrire notre ATR dans la zone eeprom :


;********************************************************************* ; DECLARATIONS DE LA ZONE EEPROM * ;********************************************************************* org 0x2100 ; adresse dbut zone eeprom ATR DE DE DE DE DE 0x07 0xAB 0xBB 0x01 0xB7 ; Rponse l'ATR ; B7 01 BB AB 07

19.11 Lenvoi du status 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. 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.

192

;=============================================================== ; 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

19.12 Rception de la classe Maintenant, notre carte passe en mode rception et attend sa premire commande. Notre programme, pour des raisons de facilit ne gre quune seule classe. Nous nous contentons donc de lire loctet, sans le vrifier ni le traiter. Il sagit en effet dun exercice didactique.
;================================================================= ; 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

19.13 Rception de INS, P1, P2, et LEN Examinons maintenant notre routine de rception de linstruction, des paramtres P1 et P2, ainsi que de la longueur de la chane.

193

;=============================================================== ; 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. 19.14 Contrle de linstruction reue 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. Cette instruction calcule la somme de P1 et P2, et renvoie le rsultat. Comme LEN contient la longueur de la chane de rponse, si LEN est suprieur 1, la rponse sera complte par des 0xFF. Toute autre instruction sera considre comme incorrecte. Voici notre test :
;============================================================== ; 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 ; traiter instruction incorrecte ; -----------------------------0x40 ; charger octet2 status envoyer status2 ; placer dans variable 0x60 ; charger octet 1 status Statxx ; envoyer status 194

movlw movwf movlw goto

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 . 19.15 Traitement dune instruction Nous en arrivons maintenant au traitement de notre instruction proprement dite. On va traiter cette instruction de la manire suivante : Comme dans toute instruction, on renvoie linstruction reue La carte renvoie la somme de P1 et de P2. La trame d'envoi est complt par des 0xFF pour atteindre une longueur totale de data identique Ser_Len Ensuite le status standard est envoy 80 00

;================================================================ ; 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 ; Tester longueur de la rponse ; ----------------------------------decf Ser_Len , f ; car dj rsultat envoy btfsc STATUS , Z ; tester si complet goto Statstd ; oui, envoyer status standard ; complter avec des 0xFF ; ------------------------------Insloop movlw 0xFF ; valeur envoyer call Send ; envoyer 0xFF decfsz Ser_Len , f ; dcrmenter compteur de boucles goto Insloop ; pas fini, suivant ; envoyer status standard ; ----------------------------goto Statstd ; envoyer status standard

19.16 Les variables Il nous reste maintenant dclarer les variables utilises. Jai dcid ici dutiliser des variables locales lorsque ctait possible :

195

;********************************************************************* ; DECLARATIONS DE VARIABLES * ;********************************************************************* CBLOCK 0x00C Ser_Ins : 1 Ser_P1 : 1 Ser_P2 : 1 Ser_Len : 1 local1 : 1 local2 : 1 local3 : 1 local4 : 1 temp_sauvw : 1 ENDC ; ; ; ; ; ; ; ; ; ; ; dbut de la zone variables instruction ISO7816 paramtre 1 ISO7816 paramtre 2 ISO7816 longueur data ISO7816 variable locale 1 variable locale 2 variable locale 3 variable locale 4 sauvegarde de W pour temp Fin de la zone

; routine ATR ; ----------#DEFINE cmpt1 local1

; compteur d'octets pour ATR

; sous-routine send et receive ; ---------------------------#DEFINE caract local2 ; caractre envoyer #DEFINE parite local3 ; bit de parit #DEFINE cmptbts local4 ; compteur de bits ; 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.

196

Annexe1 : Questions frquemment poses (F.A.Q.)


Je vais tenter de rpondre ici un maximum de questions que se posent les utilisateurs en gnral. A1.1 Je narrive pas diter mon fichier source Si vous avez suivi les exercices correctement, et, quune fois votre fichier .asm ouvert, votre clavier semble inactif, vous avez probablement plac votre fichier dans une rpertoire contenant un caractre tendu. Un cas classique est par exemple, lutilisation du nom leon pour le rpertoire. MPLAB est allergique par exemple au caractre . Remplacez leon par lesson , et tout rentrera dans lordre. A1.2 Je trouve que 8 sous-programmes, cest peu Attention, vous ne devez pas confondre le nombre de sous-programme et le nombre dimbrications de sous-programmes. Le nombre de sous-programme est illimit (dans la limite de la mmoire disponible). Une imbrication, cest quand un sous-programme appelle un autre sous-programme. Pour compter les niveaux dimbrications, suivez le chemin de votre programme dans lordre dexcution. Faites +1 pour chaque instruction call rencontre et (-1) pour chaque instruction return ou retlw . Si votre programme est correct, les 3 conditions suivantes doivent tre remplies : On ne doit jamais durant le comptage passer en ngatif On ne peut jamais dpasser 8 durant le comptage A la fin de lexcution du programme, on doit tre revenu 0

A1.3 Je nutilise que 8 imbrications, et pourtant mon programme plante. Vous ne devez pas oublier que les interruptions utilisent aussi la pile. Si vous utilisez les interruptions, vous navez droit qu 7 niveaux dimbrication. A1.4 Mon programme semble ne jamais sortir des interruptions Vous avez oubli deffacer le flag qui a provoqu linterruption.

197

A1.5 Je narrive pas ajouter un nud mon projet Vous avez oubli dditer les proprits du nud principal. Mme si vous ne dsirez rien changer, vous devez le faire. Les dernires versions de MPLAB mmorisent votre dernire action et peuvent ne pas rclamer ldition pralable. A1.6 Je narrive pas utiliser le simulateur, les options sont en gris Vous avez oubli de signaler MPLAB que vous utilisez le simulateur. Allez dans le menu project et slectionnez edit project . Dans la fentre qui souvre, slectionnez change ct du development mode . et cliquez sur la case MPLAB-SIM 16F84 . Rpondez oui toutes les questions. A1.7 Je reois un message derreur EOF avant instruction END Vrifiez si votre fichier comporte la directive END. 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. Dans ce cas, essayer un copier/coller de ce fichier dans un fichier vide cr avec un autre diteur. A1.8 Comment dsassembler un fichier .hex ? Je vais vous dcrire 2 mthodes pour dsassembler un fichier en format hexadcimal. La premire mthode utilise MPLAB : 1) 2) 3) 4) 5) 6) 7) Allez dans le menu File-> import -> import to memory Slectionnez le fichier .hex dsassembler Allez dans le menu File->export->export memory Dans la fentre output format , slectionnez disassembled code Dans le menu droulant list files of type , choisissez Disasm files (*.txt) Entrez un nom dans file name , et choisissez un emplacement de destination Cliquez sur <OK>. Vous obtenez un fichier texte qui contient le programme dsassembl.

La seconde mthode utilise IC-Prog, le clbre utilitaire de programmation des pics disponible partout : 1) Chargez le fichier .hex depuis le menu File->open file 2) Slectionnez view->assembler . Cest tout. A1.9 Utilisation des minuscules et des majuscules Par dfaut, MPLAB effectue la distinction entre minuscules et majuscules. Si cela vous pose problme, vous pouvez le modifier dans les proprits de votre projet.
198

Pour effectuer cette opration : Pressez <CTRL> + <F3> (ou menu project->edit project ) Dans la fentre project files , cliquez sur le premier nud ( [.HEX] ) Cliquez node properties Cochez OFF la ligne Case sensitivity

A1.10 Le choix dun programmateur Je ne veux pas entrer ici dans le concret, car je veux pas faire de publicit pour un ou lautre produit sur le march. Difficile galement de renseigner un logiciel, car je ne peux tre certain des droits de diffusion de tel ou tel logiciel. Je me limiterai donc un conseil : Utilisez un programmateur srie ou parallle, mais choisissez de prfrence un modle disposant de sa propre alimentation, de prfrence un modle tirant son alimentation du port srie. A1.11 Jai une erreur de stack Je reois galement pas mal de courrier de personnes qui me disent : Lorsque jexcute mon programme en pas--pas dans MPLAB, je reois un moment donn un message de type : Stack overflow ou Stack underflow . Que signifie ces messages ? 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).

199

B. Utilisation du prsent document


Le prsent ouvrage est destin faciliter la comprhension de la programmation des PICs en gnral, et du 16F84 en particulier. La seconde partie sur le 16F876 est en cours de ralisation. Communiquez lauteur (avec politesse) toute erreur constate afin que la mise jour puisse tre effectue dans lintrt de tous. Le prsent ouvrage peut tre utilis par tous, et copi dans son intgralit, condition de ne rien modifier. Dans le cas dune mise disposition du document sur un site Internet, lauteur demande simplement dtre averti de ladresse du site et des conditions de tlchargement. Dans ce cas, les fichiers joints devront tre prsents au mme emplacement. Dans le cas o le crateur du site ne dispose pas des fichiers, il peut joindre lauteur par mail. La distribution de cet ouvrage devra tre entirement gratuite, il ne pourra tre demand aucun frais inhrents limpression ou lenvoi des fichiers. 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 la (les) partie(s) suivante(s). Pour rpondre tous ceux qui souhaitent absolument contribuer financirement, vous pouvez verser si vous le voulez une petite somme une uvre humanitaire de ma part. Pour ma part le cours restera gratuit jusqu nouvel ordre. Certains continuent envoyer des messages sur ladresse bigonoff@hotmail.com . Prenez connaissance de la bonne adresse, pour de pas encombrer des adresses non concernes. Vous risquez de plus dattendre longtemps votre rponse. Sachez que je rponds toujours au courrier reu, mais notez que : 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 4 heures par semaine pour rpondre au courrier, si, en plus, je devais debugger, jy passerais la semaine. Vous

200

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. Je travaille sur la version 16F876, inutile de me demander si jai fini. Quand ce sera le cas, vous trouverez les fichiers aux adresses habituelles Je nai pas actuellement de site personnel. Donc, les sites sur lesquels vous tlchargez le cours ne dpendent pas de moi. En cas de problme de chargement, signalez le problme directement au webmaster concern. Renvoyez lascenseur en mettant disposition de tous les programmes intressants que vous allez raliser. Il suffit de les envoyer sur les sites o vous avez charg le cours. 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. A lheure o jcris ces lignes, le cours est disponible aux adresses suivantes, adresses qui vous donneront en plus des tas de renseignements, des liens, des exemples pratiques Nhsitez donc pas les parcourir tous. Dans lordre danciennet du cours : http://fribotte.free.fr/bdtech/ http://perso.wanadoo.fr/pat.deaubonne/DOWNLOAD/CoursBigOnOff/ http://www.aurelienr.com http://www.von-info.ch/hb9afo http://www.winstonpj.fr.fm http://www.courspic.fr.st http://perso.libertysurf.fr/p.may http://ejacquard.free.fr/dossier_lycee/Pic/cours_pic.htm http://perso.wanadoo.fr/yves.heilig/ElecRob/index.htm Merci tous ceux qui mont inform des erreurs dans les diffrentes versions Merci aux Fribottes pour la recherche dtaille des correctifs effectus pour la version 3. 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. Edition termine le 09/02/2001. Mise jour version 2 le 15/06/2001 (correction de quelques erreurs) Mise jour version 3 le 24/07/2001 (correction dtaille avec les Fribottes) Mise jour version 4 le 26/10/2001 (quelques petites erreurs retrouves) Mise jour version 5 le 27/02/2002 (encore quelques erreurs tenaces) Mise jour version 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 ) Dernire minute : Si vous voulez que dautres puissent profiter du cours comme vous en avez profit, jai des demandes pour la traduction de celui-ci dans dautres langues.
201

En allemand (en cours de traduction) En anglais En espagnol.

Si vous avez les comptences requises, et si vous dsirez vous rendre utile, vous pouvez, seul ou plusieurs raliser la traduction. Dans ce cas, faites-le moi savoir et je vous ferai parvenir une copie ditable du fichier original au format compatible Word. Ralisation : Bigonoff Email : bigocours@hotmail.com (Attention BIGOCOURS PAR BIGONOFF)

202

You might also like