⏱️ Qu'est-ce qu'un Timer ?

Un Timer (ou compteur) est un périphérique matériel intégré au microcontrôleur qui compte les impulsions d'horloge de manière autonome, sans intervention du processeur. Cela permet de créer des délais précis, de mesurer des durées, ou de générer des événements périodiques.

Le PIC12F683 dispose de deux timers : le Timer0 (8 bits, compte de 0 à 255) et le Timer1 (16 bits, compte de 0 à 65535). Chaque timer peut fonctionner en mode timer (horloge interne) ou en mode compteur (signal externe), selon la configuration.

L'avantage principal des timers par rapport à __delay_ms() est qu'ils fonctionnent en arrière-plan. Le processeur peut exécuter d'autres tâches pendant que le timer compte, ce qui est essentiel pour les applications temps réel.

📊 Timer0 — Compteur 8 bits

Le Timer0 est le timer le plus simple du PIC12F683. Il utilise un registre 8 bits (TMR0) qui s'incrémente à chaque cycle d'horloge (ou chaque front du signal externe).

Registres de configuration

RegistreBitFonction
OPTION_REGT0CS (bit 5)Source : 0 = horloge interne, 1 = signal externe (T0CKI)
OPTION_REGPSA (bit 3)Prescaler : 0 = assigné au Timer0, 1 = assigné au WDT
OPTION_REGPS2:PS0 (bits 2-0)Valeur du prescaler : 000=1:2, 001=1:4, ... 111=1:256
INTCONT0IF (bit 2)Flag d'overflow : passe à 1 quand TMR0 déborde (255→0)
INTCONT0IE (bit 5)Active l'interruption Timer0

💡 À retenir

Avec Fosc = 4 MHz et un prescaler 1:256, un overflow complet de Timer0 dure environ 65,536 ms. Donc si tu “toggle” une LED à chaque overflow, elle va clignoter assez vite : c’est normal.

Exemple : Clignotement avec Timer0 (polling)

C (XC8)
#include <xc.h>
#define _XTAL_FREQ 4000000

// PIC12F683 : LED sur GP0

void main(void) {

    ANSEL = 0b00000000;     // Tout en numérique (important)
    CMCON0 = 0b00000111;   // Désactive comparateurs

    TRISIO = 0b00001000;   // GP3 entrée (souvent), le reste en sortie
    GPIO = 0;

    // Timer0 : horloge interne (Fosc/4), prescaler 1:256
    // 0b00000111 -> T0CS=0, PSA=0, PS=111
    OPTION_REG = 0b00000111;

    TMR0 = 0;
    INTCONbits.T0IF = 0;

    while(1) {
        if(INTCONbits.T0IF) {
            INTCONbits.T0IF = 0;           // Reset overflow
            GPIO ^= 0b00000001;         // Toggle GP0
        }
    }
}

📊 Timer1 — Compteur 16 bits

Le Timer1 offre une plage de comptage beaucoup plus grande (0 à 65535) grâce à ses deux registres 8 bits : TMR1H (octet haut) et TMR1L (octet bas). Il peut aussi utiliser un cristal externe 32.768 kHz pour un comptage très précis.

Registre T1CON

BitNomFonction
7T1GINVInversion du gate
6TMR1GEGate enable
5-4T1CKPSPrescaler : 00=1:1, 01=1:2, 10=1:4, 11=1:8
3T1OSCENOscillateur Timer1 activé
2T1SYNCSynchronisation externe
1TMR1CSSource : 0 = Fosc/4, 1 = externe
0TMR1ON1 = Timer1 activé

Exemple : Délai de 500ms avec Timer1 (polling)

C (XC8)
#include <xc.h>
#define _XTAL_FREQ 4000000

// PIC12F683 - Timer1 : Fosc=4MHz => Fosc/4 = 1MHz
// Prescaler 1:8 => tick = 8µs
// 500ms => 500000/8 = 62500 ticks
// Précharge = 65536 - 62500 = 3036 = 0x0BDC

void main(void) {
    ANSEL = 0;
    CMCON0 = 0b00000111;
    TRISIO = 0b00001000;
    GPIO = 0;

    PIR1bits.TMR1IF = 0;

    // T1CKPS=11 (1:8), TMR1CS=0 (Fosc/4), TMR1ON=1
    T1CON = 0b00110001;

    TMR1H = 0x0B;
    TMR1L = 0xDC;

    while(!PIR1bits.TMR1IF);
    PIR1bits.TMR1IF = 0;

    // Exemple : toggle LED GP0 après 500ms
    GPIO ^= 0b00000001;

    while(1) { // boucle vide }
}

💡 Timer0 vs Timer1

Timer0 (8 bits) : Simple, idéal pour des délais courts et des tâches de base. Déborde fréquemment (max ~65,536ms avec prescaler 256).

Timer1 (16 bits) : Plus polyvalent, permet des délais plus longs (jusqu'à ~524,288ms avec prescaler 8 à 4MHz). Peut utiliser un cristal externe pour une précision maximale.

🧮 Calcul des délais Timer

Formule générale pour calculer le temps de débordement :

// Temps = (Valeur_max - Valeur_initiale) × Prescaler × (4 / Fosc)
//
// Timer0 (8 bits, Fosc=4MHz, prescaler=256) :
// Temps = 256 × 256 × (4/4000000) = 65.536 ms
//
// Timer1 (16 bits, Fosc=4MHz, prescaler=8) :
// Temps max = 65536 × 8 × (4/4000000) = 524.288 ms