CONVERTISSEUR ANALOGIQUE NUMERIQUE DES PIC16F87x.

La famille des PIC16F87x possède un convertisseur analogique numérique (CAN) sur 10 bits et 5 à 8 canaux d'entrée analogique -RA0-RA1-RA2-RA3- RA5 et RE5 à RA7 (seulement PIC 40 pins). Sur 10 bits, le nombre de pas de mesure est de 1024 soit avec une référence VREF+ de 5V, un écart entre pas de 4,88 mV. Les registres utilisés sont:

ADRESH : poids fort du résultat de la conversion

ADRESL: poids faible du résultat de la conversion

ADCON0: Registre de contrôle 0

ADCON1: registre de contrôle 1

Le résultat de la mesure peut être justifié à droite ou à gauche en configurant le bit ADFM (ADCON1) à 1 ou 0. Dans l'exemple ADFM = 1, ce qui implique que le registre ADRESL à 8 bits significatifs et ADRESH 2 bits significatifs (bit 0 et 1) => justifié à droite.

Le registre ADCON0:

ADCS1 ADCS0 CHS2 CHS1 CHS0 GO/DONE   ADON

ADCS0-1 : Choix de la fréquence d'horloge du CAN (fosc/2, fosc/8, fosc/32) avec un quartz à 12 MHz choisir fosc/32 (1-0)

CHS2-0: Choix du canal de conversion (00 = canal 0, 11 = canal 7)

GO/DONE: (ADGO du programme) 1= lance la conversion

ADON: 1= valide le fonctionnement du CAN

Le registre ADCON1:

ADFM       PCFG1 PCFG1 PCFG1 PCFG0

ADFM: Justification à droite ou à gauche du résultat 1= droite 0=gauche

PCFG3-0: Configuration des ports du CAN, permet d'adapter les ports du CAN au schéma réalisé. Par exemple (PIC16F876) pour ne configurer que des entrées analogiques RA0-3 et RA5(0010) ou une référence positive (VREF+) sur l'entrée RA3 et le reste en entrée analogique (0011).

Dans l'exemple qui suit, les deux premières mesures se font sur les canaux 0 et 1 avec une référence à +5V (l'alimentation du PIC), la troisième se fait sur le canal 2 avec une référence à +2,5V. Bien entendu si dans les deux premiers cas l'entrée analogique ne doit pas être supérieure à 5V, dans le troisième, l'entrée analogique ne doit pas être supérieure à 2,5V. Dans la pratique, on procède à une première mesure avec VREF+ = 5V, puis si le résultat est inférieur à 2,5V (4,88mV * résultat), ont peut alors fixer VREF+ = 2,5V et ainsi obtenir un pas de (2,5V/1024= 2,44 mV).

Le programme configure ainsi le CAN : Entrée 0 = RA0, entrée 1 = RA1, entrée 2 = RA2, VREF+ (2,5V) = RA3.

Le bit GO/DONE (ADGO) = 1 lance la conversion. C'est le bit ADIF (PIR1) qui est testé pour vérifier la fin de la conversion avant de lire le résultat, ce bit est positionné à 0 avant une conversion. Sous interruption, c'est également ce bit qui est utilisé et qu'il faudra tester. La tempo de 5mS est obligatoire lors d'un changement de canal sinon la mesure est fausse.

Télécharger le programme en C

En assembleur le principe reste le même !

/*********************************************************************
* Claudedel@wanadoo.fr
* http://www.geocities.com/claudedel/
* http://perso.wanadoo.fr/claude.dreschel/
********************************************************************/

#include <pic1687x.h>
#include "delay.h"


#define REF_5V 128
#define REF_2_5V 129
#define INIT_PORTA TRISA = 0x3F;
//PortA = entrees

void init_pic(void);
unsigned int mesure(unsigned char ADC_channel);

//******************************************************************
void main(void)
{

unsigned int valeur0,valeur1,valeur2;

init_pic();
valeur0 = mesure(0); //mesure du canal 0 - 0< x <5v
valeur1 = mesure(1); //mesure du canal 1 - 0< x <5v
ADCON1=REF_2_5V; // ref = 2,5v
valeur2 = mesure(2); // mesure du canal 2 - 0< x < 2,5V
while(!0); // fin

}

//**************************************************************
void init_pic(void)
{
INIT_PORTA;
ADCON1=REF_5V; //ADFM=1 VREF=+5V
ADIE=0; // pas d'interruption
ADCS1=1; //fosc/32
ADON=1; // CAN on
}
//**************************************************************
unsigned int mesure(unsigned char ADC_channel)
{
unsigned int valeur;
ADCON0 = (ADC_channel << 3)+ 129; // charge le canal de mesure
DelayMs(5); // tempo 5 ms obligatoire si changement de canal de mesure
valeur=0;
ADIF=0; //initialise le flag
ADGO=1; // lance la mesure
while(!ADIF); // et attend la fin
valeur = ADRESL; // lit le poids faible
valeur +=(ADRESH << 8); // puis le poids fort
return(valeur);
}
//****************************************************************