Bienvenue aux nouveaux arrivants sur FantasPic !

- Pensez à lire les règles durant votre visite, il n'y en a pas beaucoup, mais encore faut-il les respecter .
- N’hésitez pas à faire des remarques et/ou suggestions sur le Forum, dans le but de l'améliorer et de rendre vos prochaines visites plus agréables.
- Vous pouvez regarder votre "panneau de l'utilisateur" afin de configurer vos préférences.
- Un passage par "l'utilisation du forum" est recommandé pour connaître les fonctionnalités du forum.

--- L’équipe FantasPic ---
Commentez, partagez et proposez des Tutos en langage C !
le Timer : TMR0
Jérémy
Administrateur du site
Administrateur du site
Messages : 2155
Âge : 39
Enregistré en : juillet 2015
Localisation : Dans le sud
Contact :

#1 Message par Jérémy » dim. 23 août 2015 10:58

Bonjour à tous ,

Je vais aujourd'hui vous parlez des Timers et plus particulièrement du Timer0 en MikroC avec un PIC 18F45K22.
Le Timer0 ou TMR0 , est tout simplement un compteur qui s’incrémente à chaque instruction. Il est en quelque sorte, le fréquencemètre de nôtre µC . Plus la fréquence est élevée plus il compte vite,il à donc une relation avec le temps .

OBJECTIF :
- Nous allons apprendre à configurer le Timer 0 et à l'utiliser dans un exemple .

Bien comprendre ! :
Pour imager , si votre µC fais une instruction par seconde ( 1Hertz ), votre compteur va s’incrémenter 1 fois par seconde. Disons que si votre compteur est sur 8 bits ( 0b00000000 à 0b11111111) alors il va compter de 0 à 255 , une fois arriver à 255 , il revient à 0 , mais en le signalant en mettant un drapeau à 1. ce drapeau va nous être grandement utile par la suite .

dans la réalité un µC ne tourne pas a 1 hertz , mais plusieurs dizaines de Mhz voir centaines pour certains et même encore plus ! Mais pour mes exemples je vais rester sur une base de temps plus pratique la seconde . je pense que ce sera plus parlant .

Vous l'aurez compris un compteur sur 16 bits compte jusqu'à 65535 avant de repasser à 0 et de mettre son drapeau à 1.

Quand notre programme tourne,le Timer s’incrémente,la variable qui s’incrémente est appelée TMR0L , elle compte le nombre de cycles d'instructions. Comme le nombre d'instruction va à la vitesse phénoménale de 1 fois par seconde, notre TMR0L compte donc les secondes.

:!: Définition de TMR0L :
-TMR ( c'est le trigramme de Timer)
- 0 pour le numéro du timer il en existe plusieurs attention a bien ecrire zéro et non la lettre "o"
- L pour Low, car quand on le configure sur 16bit , on aura un TMR0H ( H pour High) qui indique les bits de poids fort et faible.

Allez on y va !!

Après avoir compris la notion de Timer avec la théorie , passons à la pratique.

Exemple :
faire clignoter toutes les leds branchées sur le PORTC avec une période de 2s ( une seconde allumée et une seconde éteinte). Ceci avec la plaque easyPic V7 , un oscillateur réglé à 8Mhz ( loin de nos 1 Hertz).

Dans un premier temps il va falloir configurer notre Timer certainement la chose la plus compliquée . car notre µC ne fonctionne pas à 1 Hertz :D ( et heureusement)
Commençons par définir le temps que dure une instruction ( 1 seconde dans l’exemple d'avant). Il faut savoir que le microcontrôleur à besoin de 4 cycles d'horloge , pour faire une instruction.
Ce qui nous donne déjà un premier calcul : Fréquence de l’oscillateur (noté Fosc) divisé par 4 . donc 8Mhz / 4 = 2Mips ( ips = instruction per second).

De la, on sait que notre Timer va s’incrémenter 2 Millions de fois par secondes . soit toutes les 0.5µs .

Cela va tellement vite , que dans de nombreux cas, il va encore falloir ralentir notre Timer . Pour cela on utilise ce qu'on appelle un PRE-SCALER , qui va encore diviser notre fréquence. Ce PRE-SCALER est réglable par la configuration du TIMER que nous verrons dans peu de temps .
Dans notre exemple nous allons diviser notre fréquence par 256.
Ce qui nous donne . 2Mips / 256 = 7812.5 ips . donc 1/7812.5 = 0.000128s = 128µs

Ok résumons : un oscillateur a 8 Mhz , avec un pré-scaler réglé sur 256 nous donne une instruction toutes les 128µs donc notre compteur(TMR0L) va s’incrémenter toutes les 128 µs.

Voici notre base de temps.


si on part sur la base d'un compteur 8 bit donc allant de 0 à 255 soit 256 valeurs. il pourra compter 256 instructions avant de mettre son Flag à 1 . si qui nous donnes 256(Nbe instruction) X 128 (µs/instruction) = 32768µs = 32.768ms

On arrive enfin au but .

on auras une interruption toutes les 32.768ms . si a chaque interruption on incrémente un compteur . il faudra 1000ms (1s) / 32.768 ms = 30.51 incrémentation de compteur .
Notre compteur devra compter jusqu’à 31 pour obtenir approximativement une seconde . 31x32.768= 1.015s

Attention toutefois ! il y 15ms de trop ! , pour certaines applications, ce n'est pas grave, pour d'autre beaucoup plus. Il nous faudra ajuster un petit peu la première boucle d'interruption pour tomber pile poil.Ce sera évoquer dans le Tuto N°7b, mais avant ça un peu de pratique avec notre premier exemple.

Configuration du Timer0 :

Cela se passe à la page 159 de notre DS .

Image
Image

bit 7 : TMR0ON : Timer0 On/Off Control, Nou permet tout simplement d'activer ou non notre Timer
bit 6 : T08BIT : Timer0 8-bit/16-bit Control : Nous choisissons si le compteur sera en 8 bit( 0 à 255) ou en 16bit ( 0 à 65535)
bit 5 : T0CS : Timer0 Clock Source Select : on choisit soit de compter l'horloge interne ( notre oscillateur) ou alors les fronts sur la broche T0CKL ( RA4)
bit 4 : T0SE : Timer0 Source Edge Select : on choisit le fronts sur lequel on va incrementer le timer sur la broche T0CKL
bit 3 : PSA : Timer0 Prescaler Assignment : On active ou non le Pre-scaler : 1= désactivé ; 0=activé
bit 2 à 0 : pour configurer notre pre-scler sur 3bit

Ce qui fera pour notre exemple:
bit7 = 1 activation du timer
bit6 = 1 en 8 bit
bit 5 = 0 sur osc interne
bit 4 = 0 en s'en fou ici
bit 3 = 1 activation du prescaler
bit 2,1,0 = 111 pour avoir une valeur de 256

Code : Tout sélectionner

T0CON : 0b11000111


Comme vous êtes censé avoir regardé, lu et compris le Tuto N°6 sur les interruptions qui bizarrement était orienté sur le TMR0 , je ne reviendrais pas dessus .

Code : Tout sélectionner

//#################################       DECLARATION      #########################################

 char compteur = 0;          // Déclaration de la variable compteur en char ( 0 à 255) et on l'initialise à 0 en même temps
 
//#################################        FONCTION       #########################################

void interrupt() {           // Ici c'est notre fonction d'interruption

                             // On regarde quel drapeau a été mis à 1, pour connaitre la source de l'interutpion
  if (INTCON.TMR0IF == 1)         // Ici le bit TMR0IF (bit2) du registre INTCON est testé
  {
   ++compteur;               // On incremente notre compteur sur une interrutpion

   INTCON.TMR0IF = 0;        // IMPORTANT !!! On ré-arme notre drapeau en le remettant à 0
  }
}

//#########################     FONCTION PRINCIPALE ET CONFIGURATION    #################################

void main() {                // ceci contiendra notre programme, c'est la fonction principale(main) et elle est obligatoire.

     ANSELC = 0;             // Met le PORT C en numérique

     PORTC = 0;              // Affecte 0 au PORT C

     TRISC = 0b00000000;     // Place le PORT C en sortie pour afficher les leds
     
     T0CON 
= 0b11000111 ;    // Configuration du TIMER0
     TMR0L = 0;              // chargement de la valeur 0 dans le TIMER du bas
     TMR0H = 0;              // chargement de la valeur 0 dans le TIMER du haut
     
     INTCON 
= 0b10100000;    // Configuration de l'interruption

 //#################################     Boucle infinie    #########################################

 while(1)                 // Ici c'est notre boucle sans fin.
 {
      if (compteur >= 31) // Si notre compteur d'interruption à atteint la valeur calculée de 31
         {
          PORTC = ~PORTC; // alors on inverse nos sorties
          compteur = 0;   // On remet à 0 notre compteur pour une nouvelle tempo
         }

  }
 }                        // Fin de notre fonction principale, la boucle est bouclée                    


:idea: Conseils :
- Je rappelle que j'aurais pus remplacer dans l'interruption: " if (INTCON.TMR0IF)" à la place de " if (INTCON.TMR0IF == 1)" .je préfère le marteler que vous ne soyez pas surpris quand vous le retrouvez quelques part .
- Dans l'interruption je n'ai pas remis les TIMER à 0 car on travaille en variable pleine, nous avons pas besoin de réinitialiser nos Timers .
- Vos remarquez la petite fonction "~" qui inverse tout simplement toutes les bits d'un octet . pour faire la vague , il faut appuyer sur "Alt Gr" + deux fois la touche "~" ( touche au dessus du "Z"), et suprrimer une vague sur les deux créer
C'est en faisant des erreurs, que l'on apprend le mieux !!!

Retourner vers « Langage C »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité