• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 16/05/2019

Mettez en œuvre un timer et un convertisseur analogique/numérique

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Le « timer » et ses registres utiles

Le microcontrôleur doit souvent générer des actions durant un temps donné :

  • solution n° 1, le microcontrôleur exécute des actions pour patienter, sachant que la durée d’une instruction est connue et précise. Problème : le microcontrôleur ne fait rien d’autre !

  • solution n° 2, le comptage du temps est dévolu à un périphérique, et le microcontrôleur mène des actions productives.

Le périphérique de comptage a plus à voir avec un seau d’eau rempli goutte à goutte. La taille des gouttes n’est pas réglable mais leur fréquence, si. Au bout d’un certain temps qui dépend du volume du seau, celui-ci déborde.

Principe du registre à accumulation
Principe du registre à accumulation.

Le timer est un compteur, qui incrémente son contenu de 1 à chaque coup d’une horloge réglable. En fonction de la profondeur du compteur, celui-ci déborde, c’est-à-dire qu’un bit particulier, appelé drapeau de débordement, est mis à 1.

Synoptique du timer 0
Synoptique du timer 0.

Le microcontrôleur peut alors :

  • soit surveiller le bit de débordement TMR0IF régulièrement ;

  • soit, comme nous l’avons vu juste avant, le microcontrôleur attend que le bit de débordement, transformé en source d’interruption, vienne interrompre le cours du programme principal. La fin du comptage du temps se manifeste alors d'elle-même.

Le schéma fonctionnel du timer 1 est représentatif du périphérique timer en général, comme illustré sur la figure suivante :

Synoptique complet du timer 1.
Synoptique complet du timer 1.
  • 2 octets représentent le comptage du temps, avec le bit de débordement :  TMR1L,   TMR1  et  TMR1IF  respectivement ;

  • le compteur peut être préchargé si la durée de temps à produire est plus courte, par le registre  TMR1H. Le registre  TMR1H  peut être lu ou écrit à tout moment ;

  • l’horloge qui rythme l’incrémentation du timer peut être externe, ou bien celle du microcontrôleur lui-même. Un multiplexeur autorise le choix avec le bit  TMR1CS ;

  • la fréquence de l’horloge est réglable par un prescaler qui divise la fréquence initiale par un choix sur 2 bits ( T1CKPS<1:0> ) ;

  • les bits de contrôle sont rassemblés dans le registre spécial  T1CON  (timer 1 configuration). En particulier, TMR1ON active le comptage.

Contenu du registre T1CON
Contenu du registre T1CON.

En particulier, le programme doit spécifier des routines d’interruption (haute et/ou basse). Comme le montre le synoptique suivant, le schéma logique câblant les interruptions est ici simplifié pour le cas de notre timer – le timer 0.

En partant de TMR0 (IF, IE, IP), il faut passer le filtre du bit IPEN (interrupt peripheral enable), puis celui de GIEH/GIE, qui autorise globalement le mécanisme d'interruption. Le timer 0 fait donc réagir une interruption de haut niveau (GIEH). Donc autant de bits à correctement positionner dans autant de registres qui les contiennent.

Schéma logique câblant les interruptions.
Schéma logique câblant les interruptions.

Le registre spécial attaché aux interruptions est  INTCON  – interruption configuration. Son organisation est donnée sur la figure suivante :

Le registre INTCON
Le registre INTCON.
Schéma logique du timer
Schéma logique du timer

Il faut remarquer ici  que le drapeau TMR0IF (interrupt flag) était à zéro avant d’écrire sur  GIE. Au fur et à mesure que le temps passe, le timer se remplit petit à petit (barre bleue). Le timer va finir par déborder et le drapeau  TMR0IF  se dresse, l’interruption de haut-niveau apparaît, qui déroute le programme principal vers la routine d’interruption.

Débordement du timer
Débordement du timer.

Après le timer, passons dans un nouveau cours au cas du convertisseur analogique-numérique.

Le  convertisseur analogique/numérique - CAN et ses registres utiles

 Comme on peut le voir sur la figure suivante, le microcontrôleur PIC18F45K20 embarque un seul convertisseur analogique/numérique, mais multiplexé sur 13 entrées analogiques différentes.

Le convertisseur A/D
Le convertisseur A/D.

Un convertisseur A/D convertit en binaire le rapport entre la tension d'entrée et une tension de référence. La référence de tension peut être la tension d’alimentation du microcontrôleur, ou toute valeur choisie par l’utilisateur.

Si le convertisseur A/D est correctement configuré, la tension analogique à convertir est d’abord comparée à la tension de référence, et le rapport est traduit sur 1 024 valeurs (ou 10 bits).

Les 10 bits du résultat  sont rangés dans 2 octets,  ADRESH  et  ADRESL, pour former un mot de 16 bits avec des bits complémentaires à zéro.

Un autre point important est que la conversion analogique-numérique est faite itérativement depuis le bit 9 jusqu’au bit 0, à raison d’un temps TAD  entre deux itérations. Aussi, l’horloge de conversion qui rythme les itérations doit avoir une période légèrement supérieure à   TAD.

Nous reprenons l’exemple du chenillard dont la vitesse de défilement est fixée par un potentiomètre, monté en diviseur de tension, comme on peut le voir sur le schéma de la figure suivante :

Réglage de la vitesse du chenillard
Réglage de la vitesse du chenillard.

Ceci permet de présenter au convertisseur AD une tension variable de 0V à VDD, qui est la tension maximale.

#pragma config FOSC=0b0110, FCMEN=OFF, IESC=OFF

Commençons par l’initialisation du convertisseur analogique-numérique :

  • le bit 0 du port A est configuré en entrée et en mode analogique. Quatre registres spéciaux doivent être affectés ;

  • ensuite, la référence de tension est fixée à l’alimentation du microcontrôleur :  ADCON1=0;

  • le registre spécial “AD Configuration 0” sélectionne l’entrée AN0 du multiplexeur analogique et met le convertisseur analogique-numérique sous tension :  ADCON0=0b00000001;

  • le registre spécial ADCON2 est plus subtil. L’horloge de conversion est l'exacte moitié du temps d'horloge du microcontrôleur (FOSC/2), soit 500 kHz ou 2µs de période, pour respecter la contrainte sur TAD   ADCON2=0b00111000;.

Par ailleurs, lorsque le bit GO est activé, la tension analogique sur AN0 est connectée à l’entrée du convertisseur analogique-numérique pendant une certaine durée, contrôlée par les bits ACQT (acquisition time). Dans notre cas, le potentiomètre diviseur de tension est lent, et on choisit une durée égale à 20 fois TAD.

Dans le programme principal, vous reconnaissez l’instruction qui configure le port D en sortie. Un timer va servir à compter du temps, c’est-à-dire créer une temporisation.

Une conversion analogique-numérique est lancée avec le bit GO. Dès lors, ce bit GO peut être lu pour détecter la fin de la conversion. Quand c’est le cas, les 8 bits de poids fort sont écrit dans ADRESH et la routine de conversion est terminée. La durée de la temporisation est mise à jour.

#pragma code // declare executable instructions
void main (void)
{
LED_Display = 1; // initialize
// Init I/O
TRISD = 0b00000000; // PORTD bits 7:0 are all outputs (0)
TRISAbits.TRISA0 = 1; // TRISA0 input
// Init Timer0
Timer0_Init();
// Init ADC
ADC_Init();
while (1)
{
LED_Display <<= 1; // rotate display by 1 from 0 to 7
if (LED_Display == 0)
LED_Display = 1; // rotated bit out, so set bit
LATD = LED_Display; // output LED_Display value to PORTD LEDs
} while (INTCONbits.TMR0IF == 0);
// Timer expired
INTCONbits.TMR0IF = 0; // Reset Timer flag
// Take an ADC conversion and use it to set Timer0
TMR0H = ADC_Convert(); // MSB from ADC
TMR0L = 0; // LSB = 0
}
}
void Timer0_Init(void)
{
INTCONbits.TMR0IF = 0; // clear roll-over interrupt flag
T0CON = 0b00000001; // prescale 1:4 - about 1 second maximum delay.
TMR0H = 0; // clear timer - always write upper byte first
TMR0L = 0;
T0CONbits.TMR0ON = 1; // start timer
}
void ADC_Init(void)
{ // initialize the Analog-To-Digital converter.
// AN0 pin is enabled as an analog input
ANSEL = 0; //turn off all other analog inputs
ANSELH = 0;
ANSELbits.ANS0 = 1; // turn on RA0 analog
// Sets bits VCFG1 and VCFG0 in ADCON1 so voltage reference is VSS to VDD
ADCON1 = 0;
// TAD minimum for the PIC18F45K20 is 1.4us.
// At 1MHz clock, selecting ADCS = FOSC/2 = 500kHz. One clock period
// 1 / 500kHz = 2us, greater than minimum required 1.4us.
// So ADCON2 bits ADCS2-0 = 000
//
// RC circuit with potentiometer is very long
// so ACQT2-0 set to 20*TAD = 111
//
// ADFM = 0 --> 8 Most Significant bits from ADRESH
ADCON2 = 0b00111000;
// Select channel 0 (AN0) to read the potentiometer voltage and turn on ADC
ADCON0 = 0b00000001;
}
unsigned char ADC_Convert(void)
{ // start an ADC conversion and return the 8 most-significant bits of the result
ADCON0bits.GO_DONE = 1; // start conversion
while (ADCON0bits.GO_DONE == 1); // wait for it to complete
return ADRESH; // return high byte of result
}

Dans la suite du cours, vous aborderez la problématique de la gestion du mode de consommation du microcontrôleur.

Exemple de certificat de réussite
Exemple de certificat de réussite