Vous êtes sur la page 1sur 34

Les Timers

Les Timers 1

Principe de fonctionnement

Rôle : Réaliser une temporisation

Élément essentiel : Compteur qui s'incrémente à chaque front montant du signal qui lui est appliqué :

● Élément essentiel : Compteur qui s'incrémente à chaque front montant du signal qui lui est

Principe de fonctionnement

Lorsque le compteur dépasse la valeur maximale qu'il peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en anglais) se lève.

peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en

253

peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en
peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en

254

peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en
peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en

255

peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en
peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en

0

peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en
peut contenir (par exemple : 256 pour un compteur sur 8 bits), un drapeau (flag en

Principe de fonctionnement

Ce drapeau a pour but d'indiquer au programme que le compteur a débordé (c'est à dire qu'il a ”fini” de compter).

De la même manière que pour la boîte aux lettres, c'est au programme de rebaisser le drapeau pour recommencer un cycle de comptage (ça ne se fait pas tout seul !).

le drapeau pour recommencer un cycle de comptage (ça ne se fait pas tout seul !).

Ré-initialisation du drapeau

le drapeau pour recommencer un cycle de comptage (ça ne se fait pas tout seul !).
le drapeau pour recommencer un cycle de comptage (ça ne se fait pas tout seul !).

Méthodes de configuration

Un Timer doit pouvoir compter un temps défini par le programme (par exemple 1ms, 10ms, 50ms, etc).

Pour cela, 2 paramètres peuvent être modifiés :

La fréquence du signal appliqué au compteur

Le compteur s'incrémentera ainsi plus ou moins vite.

Le nombre d'impulsions à compter

Le drapeau se lève toujours lorsqu'il y a débordement, on peut donc faire partir le compteur d'une valeur non nulle pour réduire le temps de comptage.

Méthodes de configuration

Modification de la fréquence du signal appliqué au compteur : le pré-diviseur (prescaler en anglais)

Exemple : pour compter 4 fois moins vite

signal appliqué au compteur : le pré-diviseur (prescaler en anglais)  Exemple : pour compter 4

Méthodes de configuration

Modification du nombre d'impulsions à compter

Si le compteur démarre à 0, il mettra beaucoup de temps à atteindre sa valeur maximale.

Pour réduire le temps de comptage, on peut donc charger une valeur initiale non nulle dans le compteur.

Exemple : Valeur initiale égale à 250

Chargement du compteur à une valeur initiale de 250

250

initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252

251

initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252

252

initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252

253

initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252

→ 6 impulsions

254

initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252

255

initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252
initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252

0

initiale égale à 250 Chargement du compteur à une valeur initiale de 250 250 251 252

Les Timers du PIC 16F887

Composition générale d'un Timer sur un microcontrôleur PIC :

générale d'un Timer sur un microcontrôleur PIC : ● Calcul du temps mis par le Timer

Calcul du temps mis par le Timer pour faire lever son drapeau :

T = T quartz × Valeur du pré-compteur fixe × Valeur du pré-compteur réglable × Nombre d'impulsions à compter

Les Timers du PIC 16F887

Les Timers sont internes au microcontrôleur.

Le 16F887 en compte 3 :

Timer0 et Timer2 sur 8 bits

Timer1 sur 16 bits

sont internes au microcontrôleur. ● Le 16F887 en compte 3 : – Timer0 et Timer2 sur

Le Timer0 du 16F887

Composition du Timer0

Le pré-diviseur peut prendre une valeur parmi la liste suivante : 1, 2, 4, 8, 16, 32, 64, 128 ou

256

La valeur initiale peut prendre n'importe quelle valeur entière comprise entre 0 et 255.

32, 64, 128 ou 256  La valeur initiale peut prendre n'importe quelle valeur entière comprise

Le Timer0 du 16F887

Calcul du temps maximum :

Pour que le drapeau se lève le plus tard possible, il faut que la fréquence du signal appliqué au compteur soit la plus faible possible. Il faut donc configurer le pré-diviseur le plus grand : 256

Il faut également faire démarrer le compteur avec la valeur la plus petite possible pour qu'il compte le nombre d'impulsion le plus grand : valeur initiale = 0

T MAX = T quartz × Valeur du pré-compteur fixe × Valeur du pré-compteur réglable
T MAX = T quartz × Valeur du pré-compteur fixe × Valeur du pré-compteur réglable max × Nombre d'impulsions à compter max
1
4.10 6 × 4 × 256 × ( 256 − 0 ) = 65,536 ms
T MAX =

Le Timer0 du 16F887

Calcul d'un temps de 10 ms :

1

T = 10.10 3 = 4.10 6 × 4 × X × Y

soit

X × Y = 10000

Pré-diviseur = 64 Valeur à compter = 156 Soit valeur initiale = 100

64 × 156 = 9984

128

× 78 = 9984

256

× 39 = 9984

= 9984 128 × 78 = 9984 256 × 39 = 9984 avec X = valeur
= 9984 128 × 78 = 9984 256 × 39 = 9984 avec X = valeur
= 9984 128 × 78 = 9984 256 × 39 = 9984 avec X = valeur

avec

X = valeur du pré-compteur

Y = valeur à compter = 256 - valeur initiale

X

Y

Y arrondi

Valeur initiale (256 – Y arrondi)

 

1

10 000

Impossible

2

5 000

Impossible

4

2 500

Impossible

8

1 250

Impossible

16

625

Impossible

32

312,5

Impossible

64

156,25

156

256 – 156 = 100

128

78 ,125

78

256 – 78 = 178

256

39,0625

39

256 – 39 = 217

 

12

Le Timer0 du 16F887

Le Timer0 du 16F887 13

Le Timer0 du 16F887

Registre de configuration du Timer0 : OPTION_REG

/RBPU

INTEDG

T0CS

T0SE

PSA

PS2

PS1

PS0

?

?

?

?

?

?

?

?

: OPTION_REG /RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0 ? ? ? ? ? ?

14

Le Timer0 du 16F887

Registre de configuration du Timer0 : OPTION_REG

/RBPU

INTEDG

T0CS

T0SE

PSA

PS2

PS1

PS0

X (1)

X (0)

0

X (0)

0

1

0

1

PS0 X (1) X (0) 0 X (0) 0 1 0 1 Pré-diviseur = 64 Si
PS0 X (1) X (0) 0 X (0) 0 1 0 1 Pré-diviseur = 64 Si
PS0 X (1) X (0) 0 X (0) 0 1 0 1 Pré-diviseur = 64 Si

Pré-diviseur = 64

PS0 X (1) X (0) 0 X (0) 0 1 0 1 Pré-diviseur = 64 Si

Si pré-diviseur ≠ 1:1 alors PSA = 0

15

Le Timer0 du 16F887

Registres associés au Timer0 :

TMR0 : c'est le registre de comptage. C'est donc dans ce registre que nous allons rentrer la valeur de départ de notre compteur.

INTCON seuls les bits 7, 6, 5 et 2 sont utiles pour le Timer 0 (ce sont les seuls non grisés). Dans ce chapitre, nous ne nous intéresserons qu'au bit 2 appelé T0IF et qui correspond au flag permettant de tester la fin du comptage. Les

bits 7, 6 et 5 seront vus lors du chapitre sur les interruptions.

OPTION_REG : Nous venons de le voir

Les bits 7, 6 et 5 seront vus lors du chapitre sur les interruptions.  OPTION_REG

Le Timer0 du 16F887

Exemple de programme :

void tempo_timer0 ( void );

void init ( void );

// tempo de 10ms avec le timer0

// initialisation des périphériques

void main ( void )

{

 

init(); // initialisation des périphériques

while ( 1 )

// boucle infinie

{

PORTB.1 = !PORTB.1;

// on change l'état de RB1

tempo_timer0();

// tempo de 10 ms

}

}

void tempo_timer0 ( void )

// tempo de 10ms avec le timer0

{

 

TMR0 = 100;

// initialisation du registre de comptage

// initialisation du drapeau lié au timer0

T0IF = 0;

while ( T0IF == 0 );

// attente de la levée du drapeau

}

void init ( void )

// initialisation des périphériques

{

 

TRISB.1 = 0;

// RB1 configuré en sortie

OPTION_REG = 0x85;

// configuration du timer0 : pré-diviseur à 64

}

Le Timer0 du 16F887

Attention ! : Que se passe-t-il si on ne recharge pas le registre de comptage (TMR0) à chaque début de temporisation ? Par exemple :

void tempo_timer0 ( void )

{

// tempo de 10ms avec le timer0

} {
}
{

T0IF = 0;

// initialisation du drapeau lié au timer0

// attente de la levée du drapeau

while ( T0IF == 0 );

void init ( void )

// initialisation des périphériques

// RB1 configuré en sortie

TRISB.1 = 0;

OPTION_REG = 0x85;

TMR0 = 100;

// configuration du timer0 : pré-diviseur à 64

// initialisation du registre de comptage

À ne pas faire en TP ! (c'est pour illustrer ce qu'il ne faut pas faire

)

}

(c'est pour illustrer ce qu'il ne faut pas faire ) } La 1ère tempo est correcte

La 1ère tempo est correcte mais toutes les autres comptent de 0 à 255 au lieu de 100 à 255 … faites donc attention à cela !

Le Timer0 du 16F887

Exercice 1 : Temporisation de 1 ms avec le timer 0.

Question 1 : Quels sont les registres du TIMER0 qu'il est nécessaire de configurer ?

Question 2 : Calculer les valeurs du prescaler et du compteur nécessaire pour obtenir une temporisation de 1 ms.

Question 3 : Donner la configuration des registres du

TIMER0.

Question 4 :

Ecrivez la fonction void Tempo_Timer0_1ms (void) qui permet d'utiliser le Timer 0.

Le Timer0 du 16F887

Exercice 2 : Temporisation de 8 ms avec le timer 0.

Question 1 : Re-calculer les valeurs du prescaler et du compteur nécessaires pour obtenir cette fois une temporisation de 8 ms.

Question 2 : Donner la configuration des registres du

TIMER0.

Le Timer0 du 16F887

Exercice 3 : Temporisations variables avec le timer 0.

La temporisation maximale avec le Timer 0 est de 65 536 μs. Pour réaliser des temporisations plus longues nous allons faire des boucles.

Pour cela, nous allons écrire une fonction appelée TempoX10 qui lance X fois une temporisation de 10 ms. X sera une valeur passée en paramètre.

Par exemple, pour faire une temporisation de 1,5s, nous écrierons tempoX10(150).

Question : Écrire la fonction void tempoX10('X') en n'oubliant pas de configurer correctement le passage de paramètre qui lancera X fois une temporisation de

10ms.

Le Timer2 du 16F887

Il est légèrement différent du Timer 0 puisque le début de comptage est en principe 0x00 et que la fin de comptage est la valeur à entrer.

Il possède comme le Timer 0 un pré-compteur fixe et un pré-compteur variable (3 valeurs possibles : 1, 4 et 16). C'est aussi un compteur 8 bits.

fixe et un pré-compteur variable (3 valeurs possibles : 1, 4 et 16 ). C'est aussi

Le Timer2 du 16F887

Calcul de la durée de comptage

T MAX = T quartz × Valeur du pré-compteur fixe × Valeur du pré-compteur réglable max × (Valeur définie + 1)

Durée de comptage max :

1 4.10 6 × 4 × 16 × 256 = 4,096 ms T MAX =
1
4.10 6 × 4 × 16 × 256 = 4,096 ms
T MAX =

Le Timer2 du 16F887

Originalité de ce Timer :

Le flag ne se lève pas systématiquement à chaque fin de comptage.

Existance d'un post-compteur.

Ce post-compteur peut prendre chaque valeur entière entre 1 et 16.

Exemple pour un post-compteur de 4 :

 Ce post-compteur peut prendre chaque valeur entière entre 1 et 16.  Exemple pour un

Le Timer2 du 16F887

La temporisation max de ce Timer est donc :

T MAX = 16 * 4,096 ms soit 65,536 ms

La formule permettant de calculer la durée de la temporisation est donc :

1 T = Valeur du post-compteur × × 4 × Valeur du pré-compteur réglable ×
1
T = Valeur du post-compteur ×
× 4 × Valeur du pré-compteur réglable × (Valeur définie + 1)
F quartz

Le Timer2 du 16F887

Le Timer2 du 16F887 26

Le Timer2 du 16F887

Le Timer2 du 16F887 27

Le Timer2 du 16F887

Le Timer2 du 16F887 Attention, en TP : pour choisir un prescaler de 16, mettez T2CKPS<1:0>

Attention, en TP : pour choisir un prescaler de 16, mettez T2CKPS<1:0> = 10, sinon un bug de MPLABSIM vous donnera des résultats inchohérents

28

Le Timer2 du 16F887

void tempo_timer2 ( void ); // tempo avec le timer2 void init ( void );
void tempo_timer2 ( void );
// tempo avec le timer2
void init ( void );
// initialisation des périphériques
void main ( void )
{
init();
// initialisation des périphériques
while ( 1 )
// boucle infinie
{
PORTB.1 = !PORTB.1;
tempo_timer2();
// on change l'état de RB1
// tempo de 50 ms
}
}
void tempo_timer2 ( void )
// tempo de 50ms avec le
timer2
{
PR2 = 239;
T2CON = 0x66;
TMR2IF = 0;
// Valeur définie de fin de comptage
// configuration du timer2
// initialisation du drapeau lié au timer2
while ( TMR2IF == 0 );
// attente de la levée du drapeau
}
void init ( void )
// initialisation des périphériques
{
TRISB.1 = 0;
// RB1 configuré en sortie
}

void tempo_timer2 ( void );

void init ( void );

// tempo avec le timer2

// initialisation des périphériques

void main ( void )

{

 

init();

// initialisation des périphériques

while ( 1 )

// boucle infinie

{

PORTB.1 = !PORTB.1;

tempo_timer2();

// on change l'état de RB1

// tempo de 50 ms

}

}

void tempo_timer2 ( void )

// tempo avec le timer2

{

 

TMR2IF = 0;

// initialisation du drapeau lié au timer2

while ( TMR2IF == 0 );

// attente de la levée du drapeau

}

void init ( void )

// initialisation des périphériques

{

 

TRISB.1 = 0; PR2 = 239; T2CON = 0x66;

// RB1 configuré en sortie // Valeur définie de fin de comptage // configuration du timer2

}

Ces 2 programmes fonctionnent … mais la solution de droite est plus intelligente

Le Timer1 du 16F887

Particularités de ce Timer 1 :

Principe de fonctionnement similaire au Timer0

Le pré-compteur ne peut prendre que quatre valeurs : 1, 2, 4 ou 8.

Le compteur est un compteur 16 bits :

Registre de comptage composé de deux registres de 8 bits : TMR1H et TMR1L

Le compteur est un compteur 16 bits :  Registre de comptage composé de deux registres

Fonctions particulières des Timers

Les Timers 0 et 1 peuvent être utilisés en compteur d’événements extérieurs.

Exemples :

Compteur de pièces dans une machine industrielle

Affichage de la vitesse d’un véhicule

Timer 0 :

Signal à appliquer sur la broche RA4/T0CKl

Timer 0 :  Signal à appliquer sur la broche RA4/T0CKl (Il faut bien sûr penser

(Il faut bien sûr penser à mettre la ligne RA4 en entrée avec TRISA.4)

Bit T0CS à mettre à 1

Timer 0 en compteur d'évènements

Timer 0 en compteur d'évènements ● T0SE = 0 : les fronts montants attaquant le Timer0

T0SE = 0 : les fronts montants attaquant le Timer0 correspondent aux fronts montants de RA4 / T0CKI

T0SE = 1 : les fronts montants attaquant le Timer0 correspondent aux fronts descendants de RA4 / T0CKI

/ T0CKI ● T0SE = 1 : les fronts montants attaquant le Timer0 correspondent aux fronts

Timer 1 en compteur d'évènements

La broche du PIC associée au Timer 1 est la ligne RC0/T1OSO/T13CKI :

PIC associée au Timer 1 est la ligne RC0/T1OSO/T13CKI : La ligne RC1 / T1OSI est

La ligne RC1 / T1OSI est aussi associée au Timer 1, mais ne joue pas de rôle dans le comptage d'événements extérieurs.

Compte tenu de la remarque ci-dessus, il faut déconnecter la ligne RC1 / T1OSI en invalidant la porte logique inverseuse.

bit T1OSCEN = 0

Timer 1 associé à un quartz

Il est possible de connecter un quartz sur le Timer 1 et de compter les impulsions de celui-ci pour générer des temps plus précis comme par exemple pour créer une horloge de secondes, minutes, heures ou un chronomètre.

Très utile pour gérer le mode sommeil du micro-controleur.

En général, on prend un quartz dit d'”horloger” de 32768 Hz (on divise ensuite par 2 15 pour avoir 1s)

T1OSCEN = 1