Académique Documents
Professionnel Documents
Culture Documents
Bigonoff PDF
Bigonoff PDF
PAR BIGONOFF
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
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.
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
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.
-
B11111010
B11111011
12
B00000100
B00000101
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
15
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
19
6 bits pour linstruction : logique, car comme il y a 35 instructions, il faut 6 bits pour
pouvoir les coder toutes
1 bit de destination(d) pour indiquer si le rsultat obtenu doit tre conserv dans le
registre de travail de lunit de calcul (W pour Work) ou sauv dans loprande (F pour
File).
Aie, premier problme, 7 bits ne donnent pas accs la mmoire RAM totale, donc voici
ici lexplication de la division de la RAM en deux banques.
En effet, il faudra bien trouver une solution pour remplacer le bit manquant. Vous avez dit
un bit dun des registres ? BRAVO, je vois que vous avez tout compris. Il sagit en ralit
du bit RP0 du registre STATUS.
Ah, vous avez remarqu quil y a un RP1 ? Et oui, le 16F876 a 4 banques, ce bit sera
utilis pour certains autres PICs que nous verrons dans la seconde partie. Vous veillerez
laisser RP1 0 pour le 16F84, afin de pouvoir porter votre programme sans problme vers
un PIC suprieur.
20
4 bits pour linstruction (dans lespace rest libre par les instructions prcdentes)
Elle est suivie dune valeur IMMEDIATE code sur 8 bits (donc de 0 255).
21
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
22
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
25
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
28
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
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
monbit
PORTA,1
Lutilisation de cette macro seffectue tout simplement en utilisant son nom dans le
programme. Par exemple :
bsf
monbit
; mettre monbit 1
; mettre monbit 1
31
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
32
; Fin de la zone
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
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
; 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
mavariable
; effacer mavariable
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
;
;
;
;
;
36
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
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 :
39
Lors dun saut, par exemple, le contenu du PC est charg directement avec les 11 bits de
destination contenus dans linstruction en elle-mme. Les 2 bits manquants sont extraits
du registre PCLATH.. Les bits 3 et 4, qui doivent tre positionns par lutilisateur, sont
placs directement dans les bits 11 et 12 du PC afin de complter ladresse de destination.
Comme le 16F84 ne gre que 1K de mmoire programme, nous naurons pas besoin de ce
registre dans le cas des sauts. Rappelez-vous que le 16F84 ne gre que 10 des 13 bits du
PC
Remarquez que la limite du PC est de 13 bits, ce qui implique que les PICs de la famille
mid-range auront une capacit de mmoire programme de 8K mots maximum (soit 213).
Il est trs important de se rappeler que le PC pointe toujours sur linstruction suivante,
donc linstruction qui nest pas encore excute. Cest indispensable de bien comprendre ceci
pour analyser les programmes en cours de 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
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.
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
33
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
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
;
;
;
;
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
; boucler
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 :
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 :
-
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
f , d
mavariable , f
mavariable , w
0x25
f , d
Pour cette instruction, je vais me montrer beaucoup plus explicite. Vous allez comprendre
pourquoi
movf
mavariable,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
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
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
50
f , d
51
Exemple 1
movlw 0x01
sublw 0x02
;
;
;
;
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
C
1
0
1
0x02
0x02
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
C
1
01
0
0x03
0x02
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
0x20
mavariable
0x1F
mavariable,w
;
;
;
;
;
;
autrevariable ;
53
b7
1
And 1
=
1
B11001101 ; charger w
B11110000 ; effectuer un and (&)
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
0xC8
mavariable
0xF0
mavariable,f
;
;
;
;
54
Syntaxe
iorlw k
b7
1
OR 0
=
1
0xC3
0x0F
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
Syntaxe
xorlw k
xor
=
b7
1
0
1
B11000101
B00001111
;
;
;
;
b6
1
0
1
b3
0
1
1
B5
0
0
0
B4
0
0
0
charger W
xor avec la valeur
rsultat : B 11001010
les 4 bits de poids faible ont t inverss
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
Exemples
bsfSTATUS , C
bsfmavariable , 2
bsf
movlw
movwf
rlf
f
rlf
C
1
0
STATUS,C
B00010111
mavariable
mavariable,f
b7
0
0
b6
0
0
b5
0
1
;
;
;
;
positionne le carry 1
charge la valeur dans w
initialise mavariable
rotation vers la gauche
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
58
Exemple1
bsf
movlw
movwf
rrf
f
rrf
b7
0
1
STATUS,C
;
B00010111 ;
mavariable ;
mavariable,f ;
b6
0
0
b5
0
0
B4
1
0
positionne le carry 1
charge la valeur dans w
initialise mavariable
rotation vers la droite
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
59
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
;
;
;
;
;
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
60
;
;
;
boucle
;
addwf mavariable , f ;
decfsz compteur , f
;
goto boucle
;
movf mavariable , w ;
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
ATTENTION
- Si vous aviez mis
decfsz
compteur , w
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
movf compteur,f
btfsc STATUS , Z
goto suite
;
;
;
boucle
;
addwf mavariable , f ;
decfsz compteur , f
;
goto boucle
;
suite
;
movf mavariable , w ;
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
62
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
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 :
boucle
movlw 0xCA
movwf compteur
; valeur du compteur
; initialiser compteur de boucles
decfsz compteur,f
goto boucle
xxx
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
boucle
xxx
xxx
xxx
xxx
movlw 0xCA
movwf compteur
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
;
;
;
;
;
;
instruction quelconque
instruction quelconque
instruction quelconque
instruction quelconque
valeur du compteur
initialiser compteur de boucles
;
;
;
;
;
;
;
;
;
;
;
;
;
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
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
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,
66
; retour dinterruption
; (f) = 0
mavariable
; (mavariable) = 0
; (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
;
;
;
;
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
; arrt du PIC
; 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
0x55
INDF,w
;
;
;
;
;
;
;
;
71
mavariable
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
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
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 :
-
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
-
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
74
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
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
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
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
;*********************************************************************
;
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
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
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
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
;
;
;
;
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
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
boucle
bsf
bcf
bcf
STATUS , RP0
OPTION_REG, RBPU
TRISA , 2
STATUS , RP0
;
;
;
;
;
;
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
bcf
btfss
bsf
btfsc
bcf
goto
PORTB ,
PORTA ,
PORTB ,
PORTA ,
boucle
;
;
;
;
;
;
2
2
2
2
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
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
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
85
TRISA,0
STATUS,RP0
INTERMASK
INTCON
;
;
;
;
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
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
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
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
; effacer watchdog
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
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
;
;
;
;
;
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
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
89
; effacer compteur1
; dcrmenter compteur1
; si pas 0, boucler
; retour de la sous-routine
; 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
; 1 cycle
;
;
;
;
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
cmpt2
; effacer compteur2
cmpt1
; effacer compteur1
cmpt1 , f
boucle1
cmpt2 , f
boucle2
;
;
;
;
;
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
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
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 :
-
Il va bien sr de soi que nimporte quel vnement ne peut pas dclencher une
interruption. Il faut que 2 conditions principales soient remplies :
-
Tout dabord, ladresse de dbut de toute interruption est fixe. Il sagit toujours de
ladresse 0x04.
Toute interruption provoquera le saut du programme vers cette adresse. Toutes les
sources dinterruption arrivant cette adresse, si le programmeur utilise plusieurs
sources dinterruptions, il lui faudra dterminer lui-mme laquelle il est en train de
traiter.
Le contenu du PC est sauv sur la pile interne (8 niveaux). Donc, si vous utilisez des
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 :
94
Celui-ci est achev, puis le processeur sarrte un cycle pour charger ladresse 0x04
dans PC.
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).
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.
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.
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.
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
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
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
w_temp
; sauver registre W
w_temp,f
w_temp,w
;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
; 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
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
b6 0, car on veut une interruption quand presse le bouton, donc quand le niveau
passe de 1 0 (flanc descendant)
;*********************************************************************
;
ASSIGNATIONS
*
;*********************************************************************
OPTIONVAL
EQUH'0000'
b7 1
b6 0
b5 0
b4 1
b3 0
b2/b0 0
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
; Fin de la zone
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
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
-
intsw2
btfsc
btfss
goto
call
bcf
goto
intsw3
INTCON , INTE
INTCON , INTF
intsw2
intrb0
INTCON,INTF
restorereg
;
;
;
;
;
;
;
;
;
;
;
;
106
Enfin, nous trouvons la partie servant la restauration des registres sauvegards. Nous
avons dj vu cette procdure :
;restaurer registres
;-------------------
restorereg
swapf status_temp , w
movwf STATUS
swapf w_temp , f
swapf w_temp , w
retfie
;
;
;
;
;
;
;
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
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
; configurer PORTS
; --------------bcfLED
; RA2 en sortie (TRISA)
BANK0
movlw INTERMASK
movwf INTCON
goto start
;
;
;
;
passer banque0
masque interruption
charger interrupt control
sauter programme principal
109
; boucler
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 :
-
excute, vous constatez que la LED sest allume (RA2 est pass 1 sur le registre PORTA).
Avancez lentement jusqu ce que la ligne :
retfie
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
113
movlw B'00000100'
BANK0
xorwf PORTA , f
bcf
INTCON , INTF
return
;
;
;
;
;
;
;
;
;
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
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
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
#DEFINE
ENDC
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
tempoF , 0
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
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
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
;
;
;
;
dbut du comptage
ici un certain nombre dinstructions
charger valeur de comptage
sauver pour traitement ultrieur
tmr0
INTCON , T0IF
; dbut du comptage
; effacement du flag
INTCON , T0IF
loop
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
122
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
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
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
Remarques importantes :
-
Il ny a quun prdiviseur, qui peut tre affect au choix au timer du watchdog (que nous
verrons plus tard) ou au timer0. Il ne peut tre affect aux deux en mme temps.
La valeur contenue dans le prdiviseur nest pas accessible. Par exemple, si vous dcidez
dutiliser un prdiviseur de 64, et quil y a un moment donn 30 vnements dj
survenus, vous navez aucun moyen de le savoir. Le prdiviseur limite donc la prcision
en cas de lecture directe.
Lcriture dans le registre tmr0 efface le contenu du prdiviseur. Les vnements survenus
au niveau du prdiviseur sont donc perdus.
124
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'
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
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
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
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.
128
129
Si vous avez un problme, le fichier fonctionnel de cet exercice est disponible sous la
dnomination Led_tmr.asm .
-
Inconvnient : plus dinterruptions gnres, donc plus de temps perdu pour le programme
principal. Dans notre cas, cela na pas dimportance, le programme ne fait rien dautre,
mais ce ne sera pas toujours le cas.
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
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
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
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 :
-
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
;
;
;
;
;
;
;
;
136
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
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
138
macro adeeprom
adeeprom
EEADR
STATUS , RP0
EECON1 , RD
STATUS , RP0
EEDATA , w
;
;
;
;
;
;
;
;
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
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.
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
;
;
;
;
;
;
;
;
;
;
;
;
;
;
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
, GIE
, GIE
, RP0
, EEIF
, WREN
,
,
,
,
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.
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
; 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
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
Placez un en-tte dans le premier ou les premiers octets de votre eeprom. Par exemple,
nous placerons 0x55 dans loctet 0.
Lors de lcriture de nouvelles valeurs dans leeprom, nous commenons par effacer
notre en-tte.
Lors dun dmarrage du PIC, si len-tte est prsent, cela signifie que les donnes
eeprom sont valides. Dans le cas contraire, le cycle dcriture a t interrompu. A vous
alors de ragir en consquence, par exemple en rinscrivant dans leeprom les valeurs
par dfaut.
Pour augmenter la scurit du systme pour les donnes critiques, vous pouvez placer
plusieurs octets den-tte.
14.12 Conclusion
Voici encore une nouvelle tape franchie dans votre connaissance du 16F84. Vous pouvez
maintenant utiliser la zone eeprom de votre PIC pour y stocker vos donnes rmanentes.
Nhsitez pas exprimenter, mais noubliez pas de vrifier votre programme pour viter
les critures inutiles et trop frquentes dans votre eeprom.
Pas de panique cependant, si votre programme est correctement crit, vous ntes pas prt
datteindre les 1.000.000 de cycles dcritures garantis.
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
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
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
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'
; bouton-poussoir
LED
tempo
LED
tempo
BOUTON
start
;
;
;
;
;
;
allumer la LED
appeler la tempo de 0.5s
teindre LED (LEDOFF)
appeler la tempo de 0.5s
tester bouton-poussoir
pas press, boucler
plante
;
;
;
;
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
;
;
;
;
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
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
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
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.
-
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'
; LED de sortie
Placez ensuite votre LED en sortie dans la routine dinitialisation (attention, en banque1)
bcf
LED
; LED en sortie
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
157
158
159
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
161
Branchement (PC)
0x00
0x00
0x00
0x00
Suite programme (PC+1)
PC + 1
PC + 1 puis 0x04
STATUS
00011xxx
000uuuuu
0001uuuu
00001uuu
uuu00uuu
uuu10uuu
uuu10uuu
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 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
165
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
1
0
1
1
0
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
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
;
;
;
;
;
;
;
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
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
;
;
;
;
;
;
;
mem1
FSR
15
cmpt
;
;
;
;
INDF , w
tampon
mem2-mem1
FSR , f
tampon , w
INDF
(mem1-mem2)+1
;
;
;
;
;
;
;
;
;
;
;
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
mem1
FSR
15
cmpt
;
;
;
;
INDF , w
FSR , 5
INDF
FSR , 5
FSR , f
cmpt , f
loop
;
;
;
;
;
;
;
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 :
-
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
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
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
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
;
;
;
;
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.
;
;
;
;
;
compteur
compteur
rsultat
rsultat
rsultat
Nous voyons que nous aurons besoin de 5 variables. Utilisons maintenant les variables
locales.
176
; 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
;
;
;
;
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
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.
P1 P2 LEN
INS : cest linstruction proprement dite, ou encore la commande. Cest cet octet qui
dtermine lopration effectuer par la carte.
LEN : peut reprsenter 2 choses. Soit cest le nombre doctets qui suit la commande, dans
ce cas la carte sattendra recevoir LEN octets supplmentaires avant de traiter la
commande dans sa totalit. Soit ce sera la longueur de la chane de rponse que le matre
sattend recevoir en provenance de la carte. Cest linstruction qui permet dtablir le
rle de LEN.
Notez quil existe des modes tendus pour la norme ISO7816, qui permet la fois
denvoyer et de recevoir plusieurs octets en une seule opration. Ce mode est dfini comme
mode T=1. Dans notre cas, nous supposons que linformation ne circule que dans un sens
pour une instruction donne (Mode T=0).
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).
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 :
-
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
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
;***********************************************************************
;
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
*
;
*
;***********************************************************************
0x08
184
-93
TMR0 , f
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
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
temp_1bd
; rception du caractre
; ---------------------movlw 0x8
movwf cmptbts
Recloop
bcf
STATUS ,
btfsc SERIAL
bsf
STATUS ,
rrf
caract ,
call temp_1b
decfsz cmptbts
goto Recloop
; pour 8 bits
; dans compteur de bits
C
;
;
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
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
bcf
clrf
; envoyer start-bit
; -------------------SERIAL
; envoyer 0 : start-bit
parite
; effacer bit de parit
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 parit
; -----------------movf parite , w
;
xorwf PORTB , w
;
xorwf PORTB , f
;
call temp_1b
;
; 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
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
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
DE
DE
DE
DE
DE
0x07
0xAB
0xBB
0x01
0xB7
; Rponse l'ATR
; B7 01 BB AB 07
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
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
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 :
-
;================================================================
;
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
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
;
;
;
;
;
;
;
;
;
;
;
; routine ATR
; ----------#DEFINE cmpt1
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
197
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
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.
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
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