13.6 Modification des registres dans le simulateur |
Comme nous n’allons pas passer des heures à simuler
ce programme, nous allons modifier les registres en cours de
simulation. Allez dans le menu " Window "
et sélectionnez " Modify… " La fenêtre
ci-dessous s’ouvre :
Cette fenêtre vous permet de modifier un registre (ou
un emplacement mémoire ) en y inscrivant la valeur
de votre choix. Nous allons nous servir de cette possibilité.
Premièrement, supprimons le prédiviseur. Pour
ce faire, nous allons écrire B’10001000’, soit 0x88.
Choisissez donc OPTION_REG comme adresse, 88 comme data et Hex
comme radix. Pressez <Write> et vérifiez que votre
registre option est bien passé à 0x88.
Maintenant, chaque pression de <F7> incrémente
tmr0 (pas de prédiviseur)
Ouvrez maintenant une fenêtre de visualisation des variables,
avec " window->watch->new watch window ".
Choisissez d’afficher la variable " cmpt ".
Cliquez <Add>.
Continuez de presser <F7> et constatez que le débordement
de tmr0 provoque une interruption et que cette interruption
provoque la décrémentation de cmpt. Pour ne pas
attendre trop longtemps, servez-vous de la fenêtre " modify "
pour positionner cmpt à 1. Ensuite, poursuivez la simulation.
Vous constaterez que la prochaine interruption provoque la modification
de RA2.
13.7 Mise en place sur la platine d’essais |
Chargez le fichier .hex obtenu dans votre PIC et alimentez
votre platine d’essais. Comptez les allumages de la LED obtenus
en 1 minute. Vous devriez trouver aux alentours de 65/66 pulses
par minute. Ceci vous montre la précision obtenue.
En réalité, un allumage toutes les (256*256*7*2)
= 917504µS.
En 1 minute, 60.000.000/917504 = 65,3 allumages. La théorie
rejoint la pratique. Le fichier est disponible sous la dénomination
" led_tmr1.asm ". [ NDLR
: Fichiers exemples ici ]
13.8 Première amélioration de la précision |
Nous allons chercher à améliorer la précision
de notre programme. Nous pouvons commencer par modifier notre
prédiviseur. Essayons plusieurs valeurs successives :
/1 : donne 500000/256 = 1953,125 passages. Pas pratique
/2 : donne 500000/512 = 976,5625 passages. Pas plus pratique
/4 : donne 500000/1024 = 488,28125 passages . Idem
/8 : donne 500000/2048 = 244,140625 passages. Dans ce
cas, un seul compteur est également nécessaire,
car le nombre de passages est inférieur à 256.
Quelle va être la précision obtenue ? Et
bien, nous initialiserons cmpt à 244, avec prédiviseur
à 8. Dans ce cas, la durée obtenue sera de :
256*8*244 = 499712 µs, donc 499712*2 = 999424µs par allumage.
En une minute, nous aurons donc 60000000/999424 = 60,034 allumages.
Voici donc une précision nettement meilleure.
Vous pouvez maintenant modifier vous-même votre programme
selon ces indications. Vous voyez que vous devez modifier la
valeur 07 en 244 à 2 endroits. Ce n’est pas pratique.
Ajoutez donc une assignation, par exemple :
TIMEBASE |
EQU |
D’244' |
; base de temps = 244 décimal |
Si vous avez un problème, le fichier fonctionnel est
disponible sous " Led_tmr.asm ".[
NDLR : Fichiers exemples ici ]
- Avantages obtenus : Une plus grande précision
- Inconvénient : plus d’interruptions générées,
donc plus de temps perdu pour le programme principal. Dans
notre cas, cela n’a pas d’importance, le programme ne fait
rien d’autre, mais ce ne sera pas toujours le cas.
13.9 Seconde amélioration de la précision |
Vous pouvez encore améliorer la précision de
votre programme. En effet, vous pouvez ne pas utiliser de prédiviseur,
donc utiliser plusieurs compteurs pour 1953,125 passages. Au
1953ème passage, vous pourrez même générer
une dernière tempo en ajoutant une valeur au tmr0. Par
exemple :
- On détecte 1953 passages à l’aide de plusieurs
compteurs
- Lors du 1953ème passage, on en est à
1953*256 = 499968 µs, il nous manque donc : 500.000 -
499.968 = 32µs.
- On ajoute donc 256-32 = 224 à tmr0, de la manière
suivante :
Bien entendu, 32µs pour tout réaliser, c’est très
court, aussi nous devrons optimiser les routines d’interruption
au maximum. Suppression des tests et des sous-programmes etc.
Mais cela reste en général à la limite
du possible. Nous ne traiterons pas ce procédé
ici, car cela ne présente pas d’intérêt,
d’autant que les interruptions vont finir par occuper la majorité
du temps CPU.
13.10 La bonne méthode - Adaptation de l’horloge |
Supposons que vous voulez construire un chronomètre.
La précision est la donnée la plus importante
dans ce cas, et passe bien avant la vitesse. Nous allons donc
nous arranger pour que les démultiplicateurs tombent
sur des multiples entiers. Comment ? Et bien simplement
en changeant le temps d’une instruction, donc, en changeant
le quartz de la PIC.
Exemple :
Comme nous ne pouvons pas accélérer une PIC
au dessus de sa vitesse maximale (nous utilisons une PIC 4MHz),
nous pouvons seulement la ralentir. Nous partons donc d’une
base de temps trop rapide.
Par exemple : reprenons notre cas de départ :
prédiviseur à 256, compteur de passages à
7. Durée avec un quartz de 4MHz : 256*256*7 par
tempo, donc 256*256*7*2 par allumage, soit 917504 µs.
Or, nous désirons 1000000µs.
Il suffit donc de recalculer à l’envers :
Que doit durer une instruction ? 1000000/(256*256*7*2)
= 1,089913504µs.
Cela nous donne donc une fréquence d’instructions de
1/1,089913504µs = 0,917504 MHz.
Comme la fréquence des cycles internes est égale
à la fréquence du quartz/4, nous aurons donc besoin
d’un quartz de 0,917504 * 4 = 3,670016 MHz. (MHz car nous avons
divisé par des µs : or, diviser par un millionième
revient à multiplier par un million).
La seule contrainte est donc de savoir s’il existe des quartz
de cette fréquence disponibles dans le commerce. Dans
le cas contraire, vous recommencez vos calculs avec d’autres
valeurs de prédiviseurs et de compteur.
Si vous trouvez donc un quartz de fréquence appropriée,
vous obtenez une horloge de la précision de votre quartz.
Vous ajoutez un affichage, et voilà une horloge à
quartz.
13.11 La méthode de luxe : La double
horloge |
La méthode précédente présente
l’inconvénient de ralentir la PIC. Que faire si vous
voulez à la fois une vitesse maximale et une précision
également maximale ? Et bien, aucun problème.
Vous alimentez votre PIC avec votre quartz et vous créez
un autre oscillateur externe avec votre quartz spécial
timing. Vous appliquez le signal obtenu sur la pin RA4/TOKI
et vous configurez votre timer0 en mode compteur.
Donc, votre PIC tourne à vitesse maximale, et les interruptions
timer0 sont générées par une autre base
de temps, plus adaptée à la mesure de vos événements.
13.12 Exemple d’utilisation de 2 interruptions |
Dans ce petit exemple nous allons utiliser 2 sources d’interruption
différentes, afin de vous montrer un exemple concret
de ce type d’utilisation. Nous allons recréer notre programme
de télérupteur, mais en remplaçant la temporisation
par une interruption sur le timer0.
Remarquez que notre programme principal ne fait plus rien.
Vous pouvez donc utiliser d’autres possibilités sur cette
carte sans perturber le fonctionnement du télérupteur.
Nous aurons donc une interruption
pour RB0, et une autre pour tmr0. Vous voyez ci-dessous l’ordinogramme
qui va nous servir.
Effectuez une copie de votre fichier m16f84.asm et renommez-le
" telerupt.asm ". Créez un nouveau
projet " telerupt.pjt ". Editez votre fichier
comme précédemment : coupure du watchdog,
positionnement de la LED en sortie, mise en service initiale
des interruptions RB0/INT.
Créez votre routine d’interruption timer0 toutes les
260ms, soit prédiviseur à 256, et 4 passages .
Essayez de réaliser vous-même ce programme. Chargez-le
dans votre PIC et lancez-le. Notez que l’ordinogramme ne contient
pas le compteur de passages dans tmr0. Je vous laisse le soin
de réfléchir.
Une pression sur le B .P. allume la LED, une autre l’éteint.
Si cela ne fonctionne pas, cherchez l’erreur ou servez-vous
du simultateur. Je vous fourni le programme fonctionnel dans
le cas où vous seriez bloqués.
Remarque
Il est très important de bien comprendre qu’il faut
effacer tmr0 AVANT d’effacer le flag T0IF et de relancer les
interruptions tmr0. En effet, si vous faites le contraire, vous
risquez que tmr0 déborde entre le moment de l’effacement
du flag et le moment de l’effacement de tmr0. Dans ce cas le
flag serait remis immédiatement après l’avoir
effacé. Votre programme pourrait donc avoir des ratés
par intermittence.
Vous savez maintenant exploiter le timer0. Les méthodes
évoquées ici sont une base de travail pour des
applications plus sérieuses. Je vous conseille vraiment
d’effectuer toutes les manipulations évoquées.
Même les erreurs vous seront profitables.
|