Temporisations logicelle ou par TIMER en ASM - Ressources > Autres ressources - Articles et téléchargements
Temporisations logicelle ou par TIMER en ASM - Ressources > Autres ressources - Articles et téléchargements
Pseudo Pass se souvenir de moi     Créer un compte
ARTICLES et TELECHARGEMENTS ~ FORUMS ~ LIENS  
 
             
 
proposer
 
   
             
 
Catégories
 
   
             
 
Recherche
 
   
 
Articles-et-telechargements > Ressources > Autres ressources > Temporisations logicelle ou par TIMER en ASM

Temporisations logicelle ou par TIMER en ASM

Publié par david le 03/10/2005 (3957 lectures)
La création d'un temporisation n'est pas très compliquée, qu'elle soit logicielle ou par timer


Il est important de noter que certains versions de HC08 n'ont pas de timer ou certaines en possèdent plusieurs. Ce choix se fera suivant le mode d'utilisation de votre application. Elle imposera ou non la fonction TIMER.


En quelques mots, voici les différences majeures entre ces 2 types de temporisation :

- La temporisation logicielle permet de créer des tempos assez précise mais interdit tout autre action pendant l'exécution de cette temporisation. Par exemple, il est impossible de faire des actions aléatoires pendant son exécution. Mais il est possible de faire certains actions à condition d'avoir le même nombre de cycles d'horloge à chaque fois.


- La temporisation par TIMER permet de créer de tempo extrêmement précise et autorisant tout type d'action. Il est donc possible de faire ce que l'on veut. On choisira soit une interruption soit un bit de mise à 1 qui précisera si la tempo est fini.



Il faut pour cela connaître la fréquence du bus de votre micro. Certains fonctionnent à la même vitesse que la fréquence d'horloge, d'autre fréquence d'horloge divisé par 4 ou même par 2. Il faut donc regarder le mode de fonctionnement de votre micro dans les registres et suivant le datasheet du composant. A noter que certains possèdent une fréquence d'horloge interne, pré divisée aussi pour certaines versions.



1 - La temporisation logicielle.

Un fois que l'on connaît la fréquence du bus, il faut avoir sous les yeux le nombre de cycles d'horloge pour chaque instruction voir chapitre CPU Processor Unit et Instruction Set Summary).

;- TEMPORISATION DE 100MS ----------------------------------------------------------------
TEMa2_100ms:
pshx ; on met de coté X
pshh ; on met de coté H
clrx
clrh ; effacement de X et H
TEMa2_100ms_1
sta COPCTL ; effacement du chien de garde
aix #$1 ; incremente X
cphx #10234 ; compare X à 10234 decimal
bne TEMa2_100ms_1 ; si la comparaison n'est pas bonne, on revient à TEMa2_100ms_1
pulh ; on restaure H
pulx ; on restaure X
rts ; on sort du sous programme
;- FIN TEMPORISATION DE 100MS ------------------------------------------------------------


Pour l'exemple suivant, il a fallu faire ce calcul:
durée_tempo = t_pshx + t_pshh + t_clrx + t_clrh + 10238*(t_sta + t_aix + t_cphx + t_bne) + t_pulh + t_pulx + t_rts
soit durée_tempo = 2 + 2 + 1 + 1 + 10238*( 4 + 2 + 3 + 3) + 2 + 2 + 4 = 122870

t_sta dure 4 cycles car l'opérande n'est pas une valeur directe (comprise entre $00 et $FF)
t_cphx dure 3 cycles car l'opérande est une valeur immédiate

Cette tempo dure donc 122870 cycles d'horloge. Pour connaître sa temporisation en secondes, il faut la multiplier par la durée d'un cycle d'horloge. Pour l'utilisation d'un quartz à 4,9152Mhz et un bus à Fh/4, on obtient:

t_cycle = Fh/4 = 4/4915200 = 1/1228800 = 0,814µs

On a donc une tempo de t = 0,814*122870 = 100 ms (si la valeur t_cycle n'est pas arrondi, on a une tempo de 99991,8µs)
L'erreur est donc de 0,008%

La formule pour trouver la valeur de X doit être :
X = (t_voulu - ( t_cycle * (t_pshx + t_pshh + t_clrx + t_clrh + t_pulh + t_pulx + t_rts)))/(t_cycle*(t_sta + t_aix + t_cphx + t_bne)

Le programme ci-dessus ne modifie aucun registre vu qu'ils sont sauvegardés par les fonctions PSH et restaurés par les fonctions PUL. Il peut donc s'adapter à tous vos programmes.


La formule simplifié est la suivante:
X = (t_voulu - ( 14 * t_cycle))/( 12* t_cycle)

A noter que l'instruction NOP permet d'ajuster votre tempo à la micro seconde près, vu que c'est une instruction d'un seul cycle et qui ne sert à rien, qu'à perdre du temps.

Il est à noter que certains tempo ne peuvent pas être réalisable car l'accumulateur H:X est au maximum Pour une fréquence de bus de 1,2288Mhz (quartz de 4,9152Mhz), on a une durée maximale de 640ms

On peut soit réduire la fréquence du bus, ce qui réduit aussi l'exécution de tout votre programme ou utiliser l'accumulateur A.

;- TEMPORISATION DE 1 S ------------------------------------------------------------------
TEMa2_1s:
psha
lda #10 ; 10 x 100ms = 1s (on met 10 car le test s'effectue apres la tempo et non pas avant sinon ca fait 11)
TEMa2_1s_1:
jsr TEMa2_100ms
deca
bne TEMa2_1s_1 ; quand c'est on sort sinon on continue
pula
rts
;- FIN TEMPORISATION DE 1 S --------------------------------------------------------------

Ici on ne compte pas le nombre de cycle de chaque instruction car ca ne sert à rien, vu que la tempo obtenu n'est pas à 1 µs près. Si l'on souhaite le faire, il faut donc l'inclure dans le calcul précédent. Mais il est plus intéressant d'utiliser le TIMER.

Avec cette astuce on peut arriver à des valeurs maximales de 163,840 secondes (avec H:X=65535 et A=256)

On peut aussi inclure des routines dans ces tempos mais elles doivent avoir le même cycle d'horloge, ce qui est assez contraignant.



2 - La temporisation par TIMER.

Celle-ci peut paraître très complexe mais ne l'est pas. Je dirais même qu'elle est encore plus simple que la précédente.

Je précise une fois de plus que certaines versions ne disposent pas de TIMER. On différencie la version 1 TIMER par la version 2 TIMER par des registres différents. Il est donc important de ne pas se tromper de registres lorsqu'il y a 2 TIMER. Il est impossible aussi d'utiliser un TIMER pour une version intégrant 1 seul TIMER sur une version 2 TIMER sans modifications.


Dans une version 1 TIMER, les registres s'appellent: T1MODH, T1MODL, T1SC.
Dans une version 2 TIMER, les registres s'appellent: TAMODH et TBMODH, TAMODL et TBMODL, TASC et TBSC

Ceux sont les seuls registres à utiliser pour faire une tempo. Il existe d'autres registres plus évolués qui permettent d'activer des sorties à 1 ou à 0 avec la fonction PWM du TIMER, cette option n'existe pas non plus dans toutes les versions équipées de TIMER.


Ici, on ne compte pas le nombre de cycles, c'est le micro qui les compte.

;- TIMER_1 S -----------------------------------------------------------------------------
TIMER_1s:
bclr 7,TASC ; clear overflow flag
mov #%00110110,TASC ; Stop & reset, overflow interrupt disable, prescaler=64
clr TASC0 ; Inhibit all capture/compare functions
clr TASC1
mov #$4B,TAMODH ; Modulo count = 19200 (4B00H)
mov #$00,TAMODL
bclr 4,TASC ; Un-reset TIMer
bclr 5,TASC ; start timer
rts
;- FIN TIMER_1 S -------------------------------------------------------------------------
Il faut bien évidement effacer toutes les flag (drapeaux) des registres. Ensuite on configure le prédiviseur du TIMER.
Ce prédiviseur permet de diviser par 1, 2, 4, 8, 16, 32 ou 64 la fréquence du bus. Ceci dans le but d'avoir une précision extrême de votre TEMPO.
On ne vas pas choisir une prédivision par 64 pour une tempo de quelques millisecondes.

On peut noter que l'on peux choisir une fréquence externe (suivant bien évidement les options du micro) sur une broche du port D (la plus part du temps, TACLK ou TBCLK). Cette fréquence ne peut pas être prédivisée.

La procédure décrite est pour un TIMER qui s'appelle TASC. La même méthode doit être appliquée aux timers mais en utilisant les bons registres.


Le registre TASC et le suivant :
- bit7 : bit en lecture du dépassement de la valeur prédéfinie dans TAMODH et TAMODL,
- bit6 : permet d'activer les interruptions logicielles (via le registre dans le vecteurs de reset Timer A Overflow Vector, où est inscrit l'adresse à pointer lorsque la tempo est terminée),
- bit5 : permet d'arrêter/réactiver le compteur du TIMER et non pas le comptage, il arrête le compteur TACNTL et TACNTH),
- bit4 : efface la prédivision et remet à 0 le compteur TACNTL et TACNTH,
- bit3 : non utilisé,
- bit2 à bit0 : choix du prédiviseur ou le cas échéant de la broche à utiliser.

Pour le programme ci-dessus: mov #%00110110,TASC
On choisis donc de ne pas activer les interruptions logicielles, de remettre le compteur à 0 et de prédivisé par 64.

Les registres TASC0 et TASC1 sert essentiellement pour les Input Captures (compteur en entrée), Output Capture (compteur en sortie) ou la fonction PWM. Ceci n'est donc pas nécessaire mais si vous les utilisez ailleurs, il faut les ré-initialiser au cas ou.

Les registres TAMODH et TAMODL vont nous servir à mettre la valeur maximale à détecter. C'est donc à partir de cette valeur que le flag OverFlow (dépassement) va être actif, suivant le choix du bit 7 ou bit 6 du registre TASC.
En cas de dépassement, si l'on choisit aucune interruption, il faut la détecter de manière logicielle, par scrutation, comme ceci :
brclr IRQ_CP,IRQ_CP_PORT,BOUCLE_DETECT1 ; on attend que le signal repasse à zéro avant de continuer à compter

Si l'on choisit de le faire par interruption, il faut donc créer un sous programme pour lui indiquer ce qu'il faut faire lorsque cette valeur est dépassée (l'adresse de ce sous programme sera indique dans le vecteur de reset à l'adresse Timer A Overflow Vector).

A partir d'ici, on n'a fait que configurer le TIMER, il n'est pas encore actif. On va donc le remettre à 0 par le bit 4 et l'activer par le bit 5. Il démarre donc ici.

La valeur $4B00 correspond à 19200 cycles d'horloge à une prédivision par 64 de la fréquence du bus soit la valeur :
T = (19200 * 64) / t_cycle
Pour l'utilisation d'un quartz à 4,9152Mhz et un bus à Fh/4, on obtient:
t_cycle = Fh/4 = 4/4915200 = 1/1228800 = 0,814µs
T = 19200*64*0,814µs=1,000243s

On a donc un timer beaucoup plus précis que le timer logiciel et qui peut atteindre jusqu'à 3,41s au maximum. Bien entendu, on peut imbriquer le timer avec un petit programme avec l'interruption logicielle comme ceci :
la valeur NB_TIMER sera en RAM et indiquera le nombre de cycle à faire (au maximum $FF, on attend donc au max 872,96s soit plus de 14 minutes).

;- TIMER_1 S -----------------------------------------------------------------------------
TIMER_1s:
cli ; clear overflow flag
mov #%01110110,TASC ; Stop & reset, overflow interrupt disable, prescaler=64
clr TASC0 ; Inhibit all capture/compare functions
clr TASC1
mov #$4B,TAMODH ; Modulo count = 19200 (4B00H)
mov #$00,TAMODL
bclr 4,TASC ; Un-reset TIMer
bclr 5,TASC ; start timer
rts
;- FIN TIMER_1 S -------------------------------------------------------------------------

INTERRUPTION_TIMER:
cli
lda NB_TIMER ; on charge la valeur defois que le timer doit etre executer
deca
sta NB_TIMER
beq SORTIE_INTERRUPTION_TIMER ; si c'est fini on sort, on arrete le timer et on sort sinon on revient toujours dans cette interrution
bclr 4,TASC ; Un-reset TIMer
bclr 5,TASC ; start timer
rti
SORTIE_INTERRUPTION_TIMER:
bset 5,TASC ; stop TIMer
rti


Article précédent Article suivant
Conversion HEXA/ASCII et ASCII/HEXA en C Article suivant
Les commentaires appartiennent à leurs auteurs. Nous ne sommes pas responsables de leur contenu.
Auteur Commentaire en débat
Powered by XOOPS© The XOOPS Project
Contacter les administrateurs

Temporisations logicelle ou par TIMER en ASM - Ressources > Autres ressources - Articles et téléchargements