Vous êtes sur la page 1sur 14

Microcontrôleurs Iset de Nabeul

Leçon N°9
LES TIMERS EN MIKROC
1. Principe de fonctionnement
Rôle : Réaliser une temporisation
Elément essentiel : Compteur qui s'incrémente à chaque front montant du signal qui lui est appliqué
:

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.

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 boite aux lettres, c'est au programme de
rebaisser le drapeau pour recommencer un cycle de comptage (ça ne se fait pas tout seul !).

2. 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 applique 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.
Modification de la fréquence du signal applique au compteur : le pré-diviseur (prescaler en anglais)

Mr Nizar TOUJENI 81
Microcontrôleurs Iset de Nabeul

Exemple : pour compter 4 fois moins vite

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

3. Les Timers du PIC 16F877


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

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

Les Timers sont internes au microcontrôleur.


Le 16F877 en compte 3 :
– Timer0 et Timer2 sur 8 bits
– Timer1 sur 16 bits

Mr Nizar TOUJENI 82
Microcontrôleurs Iset de Nabeul

3.1. Le Timer0 du 16F877


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.

Calcul du temps maximum


Pour que le drapeau se lève le plus tard possible, il faut que la fréquence du signal applique 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.

Mr Nizar TOUJENI 83
Microcontrôleurs Iset de Nabeul

Calcul d'un temps de 10


ms

Registre de configuration du Timer0 : OPTION_REG

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 grises).
Dans ce chapitre, nous ne nous intéresserons qu'au bit 2 appelé T0IF et qui correspond au flag

Mr Nizar TOUJENI 84
Microcontrôleurs Iset de Nabeul

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

Exemple de programme
void tempo_timer0 ( void ); // tempo de 10ms avec le timer0
void init ( void ); // initialisation des périphériques
void main ( void )
{
init(); // initialisation des périphériques
while ( 1 ) // boucle infinie
{
PORTB.F1 = !PORTB.F1; // 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
T0IF = 0; // initialisation du drapeau lié au timer0
while ( T0IF == 0 ); // attente de la levée du drapeau
}
void init ( void ) // initialisation des périphériques
{
TRISB = 0; // RB1 configuré en sortie
OPTION_REG = 0x85; // configuration du timer0 : pré-diviseur à 64
}

Mr Nizar TOUJENI 85
Microcontrôleurs Iset de Nabeul

3.2. Le Timer2 du 16F877


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.

Calcul de la durée de comptage

Durée de comptage maximale

Originalité de ce Timer
Le flag ne se lève pas systématiquement à chaque fin de comptage.
Existence d'un post-compteur.
Ce post-compteur peut prendre chaque valeur entière entre 1 et 16.
Exemple pour un post-compteur de 4 :

La temporisation max de ce Timer est donc :


TMAX = 16 * 4,096 ms soit 65,536 ms
La formule permettant de calculer la durée de la temporisation est donc :

Mr Nizar TOUJENI 86
Microcontrôleurs Iset de Nabeul

Registres associés au Timer2


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

Mr Nizar TOUJENI 87
Microcontrôleurs Iset de Nabeul

Exemple de programme
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.F1 = !PORTB.F1; // on change l'état de RB1
tempo_timer2(); // 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 = 0; // RB1 configuré en sortie
PR2 = 239; // Valeur définie de fin de comptage
T2CON = 0x66; // configuration du timer2
}
3.3. Le Timer1 du 16F877
Les particularités du Timer 1 sont :
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 compose de deux registres de 8
bits (TMR1H et TMR1L).

Mr Nizar TOUJENI 88
Microcontrôleurs Iset de Nabeul

4. 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/T0CKI

4.1. Timer 0 en compteur d'évènements


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

4.2. Timer 1 en compteur d'évènements


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

Mr Nizar TOUJENI 89
Microcontrôleurs Iset de Nabeul

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
4.3. Timer 1 associe à 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 precis 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 microcontrôleur.
En général, on prend un quartz dit d'”horloger” de 32768 Hz (on divise ensuite par 215 pour
avoir 1s).
T1OSCEN = 1
5. Exemples
Exemple 1 : RELAI
Dans ce projet la minuterie, sur la base de registre TMR0, est utilisée comme un compteur. L'entrée
de comptage est reliée à un bouton-poussoir Input de sorte que toute pression sur Input provoque
TMR0 à compter une impulsion. Lorsque le nombre d'impulsions correspond au nombre stocké dans
le registre nommé TEST, la valeur logique 1 (5V) apparaît sur le pin3 de PORTD. Cette tension
active un relais électromécanique, et ce bit est appelé « RELAI » dans le programme.

Mr Nizar TOUJENI 90
Microcontrôleurs Iset de Nabeul

Dans le registre de TEST est stocké un nombre de 5 pour cet exemple. Bien sûr, il peut être n'importe
quel nombre défini comme une constante. Par ailleurs, le microcontrôleur peut activer un autre
appareil au lieu de relais, tandis que le capteur peut être utilisé à la place du bouton-poussoir. Cet
exemple illustre l'une des applications les plus courantes du microcontrôleur dans l'industrie ; quand
quelque chose est effectué autant de fois que nécessaire, puis quelque chose d'autre doit être activé ou
désactivé, etc.
Code-source 1
void main()
{
char TEST = 5; // Constante TEST = 5
enum sortie {RELAI = 3}; // Constante RELAI = 3
ANSEL = 0; // Les E/S sont configurées en numériques
ANSELH = 0;
PORTA = 0; // Initialisation du porte A
TRISA = 0xFF; // Port A est configure en entrée
PORTD = 0; // Initialisation du PORTD
TRISD = 0b11110111; // Broche 3 du PORTD3 est configure en sortie
OPTION_REG.F5 = 1; // Compteur TMR0 reçoit des impulsions par la broche RA4
OPTION_REG.F3 = 1; // Taux de prédiviseur est de 1:1
TMR0 = 0; // Initialisation du compteur TMR0
do
{
if (TMR0 == TEST) PORTD.RELAI = 1;
// Est-ce que le nombre d’impulsion TMRO est égal à constante TEST?
// Nombre est égal à TEST. La broche RD3 est en 1 (RELAIS est active)
}
while (1); // Restez dans la boucle sans fin
}
Exemple 2. Registres TMR0 et TMR1 comme minuteries
Dans l'exemple précédent, le microcontrôleur ne fait rien entre des impulsions de comptage en
utilisant des boucles sans fin. Ces déchets du temps sont un luxe inadmissible et par conséquent une
autre méthode doit être appliquée. Considérons le schéma à microcontrôleur 16F887 de la figure 4
qui sera toujours le même pour réaliser les nouvelles fonctions.
Le fichier INTERRUP_TMR0.C du code-source 2 montre l’utilisation du registre TMRO avec pré
diviseur pour générer une interruption. Une fois que le registre TMR0 est « trop-plein » le routin

Mr Nizar TOUJENI 91
Microcontrôleurs Iset de Nabeul

d’interruption incrémente automatiquement la variable cnt par 1. Lorsque sa valeur atteint 400, le
PORTB est incrémenté de 1. L'ensemble de la procédure est « masqué », qui permet au
microcontrôleur de faire autre chose.

Code-source 2
unsigned cnt; // Définir la variable cnt
void interrupt( )
{
cnt++; // Interruption cause l’incrémentation par 1 de la variable cnt
TMR0 = 100; // Valeur initiale du TMR0
INTCON = 0x20; // Bit T0IE est positionné à 1, bit T0IF est en 0
}
void main()
{
OPTION_REG = 0x84; // Prédiviseur pour TMR0
ANSEL = 0; // Toutes les broches E/S sont configuré en digital
ANSELH = 0;
TRISB = 0; // PORTB est configuré en sortie
PORTB = 0x0; // Initialisation du PORTB

Mr Nizar TOUJENI 92
Microcontrôleurs Iset de Nabeul

TMR0 = 100; // TMR0 compte de 100 à 255


INTCON = 0xA0; // Interruption par TMR0 est autorisés
cnt = 0; // Variable cnt est initialisée à 0
do
{
if (cnt == 400)
{ // Incrémenter port B après 400 interruptions
PORTB = PORTB++; // Incrémenter PORTB par 1
cnt = 0; // Initialiser la variable cnt
}
}
while(1);
}
On voit que l’Interruption se produit sur chaque débordement du registre TMR0. Le nombre
d’interruption à 400, dans cet exemple, provoque l’incrémentation du PORTB comme indique la
figure ci-dessous.

Dans le code-source 3 (fichier INTERRUP_TMR1) on utilise l’interruption produit par le


débordement de registre TMR1(TMR1H, TMR1L). Après 76 d’interruption se produit l’évolution sur
le PORTB comme indique la figure ci-dessous.

Code-source 3
unsigned short cnt; // Définir la variable cnt
void interrupt()
{
cnt++ ; // Interruption cause l’incrémentation par 1 de la variable cnt
PIR1.TMR1IF = 0; // Remise à 0 bit TMR1IF
TMR1H = 0x80;

Mr Nizar TOUJENI 93
Microcontrôleurs Iset de Nabeul

TMR1L = 0x00; // Valeurs initiales du TMR1H and TMR1L


}
void main()
{
ANSEL = 0; // Broches E/S sont configure en numériques
ANSELH = 0;
PORTB = 0xF0; // Initialisation de PORTB
TRISB = 0; // PORTB est configuré en sortie
T1CON = 1; // Remise à 1 du TMR1
PIR1.TMR1IF = 0; // Remise à 0 du TMR1IF
TMR1H = 0x80; // Initialisation du TMR1
TMR1L = 0x00;
PIE1.TMR1IE = 1; //Activer l’interruption en cas de débordement du TMR1
cnt = 0; // Remis à 0 la variable cnt
INTCON = 0xC0; // Activer interruption (bits GIE et PEIE)
do
{ // Boucle sans fin
if (cnt == 76)
{
PORTB = ~PORTB; //Bits du PORTB sont inversés après 76 d’interruptions
cnt = 0; // Initialisation de la variable cnt
}
}
while (1);
}

Mr Nizar TOUJENI 94