📊 Qu'est-ce qu'un convertisseur ADC ?

Le convertisseur ADC (Analog-to-Digital Converter) transforme une tension analogique continue (par exemple 0V à 5V) en une valeur numérique exploitable par le microcontrôleur. C'est indispensable pour lire un potentiomètre, un capteur de température, une LDR, etc.

Le PIC16F877A intègre un ADC 10 bits. Selon la configuration, tu peux utiliser jusqu’à 8 entrées analogiques : AN0 à AN7.

Un ADC 10 bits convertit une tension en une valeur entre 0 et 1023, avec une résolution d’environ Vref / 1024 (ex : 5V / 1024 ≈ 4,88 mV par pas).

🔧 Configuration de l'ADC

Registres principaux

RegistreFonction
ADCON0Contrôle : sélection du canal, démarrage conversion, activation ADC
ADCON1Configuration : choix analogique/numérique, références, justification
ADRESH / ADRESLRésultat de la conversion (10 bits sur 2 registres)

Entrées analogiques (ANx) sur PIC16F877A

Sur le PIC16F877A, les entrées analogiques sont réparties ainsi :

La logique reste la même :

💡 Astuce

Sur le PIC16F877A, ADCON1 joue un rôle très important : il sert à choisir quelles broches restent analogiques et lesquelles deviennent numériques.

⚠️ Erreurs fréquentes

  • Oublier de configurer ADCON1 : certaines broches restent en mode analogique ou numérique sans que tu le veuilles.
  • Oublier de mettre la broche en entrée via TRISA/TRISE.
  • Lire ADRESH/ADRESL sans tenir compte de la justification choisie.

📝 Exemple : Lire un potentiomètre sur AN0

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

// Exemple PIC16F877A : lecture ADC sur AN0 (RA0)
// LED sur RB0

static unsigned int lireADC_AN0(void) {
    // Sélection canal AN0 + ADC ON
    ADCON0bits.CHS = 0;
    ADCON0bits.ADON = 1;

    __delay_us(20);          // temps d'acquisition

    ADCON0bits.GO_DONE = 1;   // start
    while(ADCON0bits.GO_DONE);

    return ((ADRESH << 8) | ADRESL); // 10 bits (justif. droite)
}

void main(void) {

    // Configure AN0 en analogique, références sur VDD/VSS, résultat justifié à droite
    ADCON1 = 0b10000000;

    // RA0 en entrée (AN0), RB0 en sortie (LED)
    TRISAbits.TRISA0 = 1;
    TRISBbits.TRISB0 = 0;

    PORTB = 0;

    // ADC ON + horloge ADC (exemple : Fosc/8)
    ADCON0 = 0b01000001;

    unsigned int valeur;

    while(1) {
        valeur = lireADC_AN0();

        // LED ON si > ~2.5V (512)
        if(valeur > 512) PORTBbits.RB0 = 1;
        else            PORTBbits.RB0 = 0;

        __delay_ms(100);
    }
}

🧮 Conversion tension ↔ valeur ADC

Formules de conversion

Valeur ADC → Tension : Tension = (Valeur_ADC × Vref) / 1023

Tension → Valeur ADC : Valeur = (Tension × 1023) / Vref

Avec Vref = 5V :

  • Valeur 0 = 0V
  • Valeur 512 ≈ 2.5V
  • Valeur 1023 = 5V
  • Résolution : 5V / 1024 ≈ 4.88 mV par pas

🌡️ Application : Capteur de température LM35

Le LM35 délivre 10mV par degré Celsius. Avec l'ADC 10 bits et Vref = 5V :

Calcul température
unsigned int adc_val = lireADC_AN0();
// Tension en mV = (adc_val × 5000) / 1023
// Température = Tension_mV / 10
float temperature = (adc_val * 5000.0 / 1023.0) / 10.0;
// Ex: adc_val=51 → 249mV → 24.9°C