Programmation du PIC16F877A - 3e partie

Cette troisième partie consacrée à la programmation du PIC16F877A, a pour but de faire varier le rapport cyclique d’un signal carré délivré par le microcontrôleur.  Ce composant est capable de générer un signal numérique dont la largeur des impulsions est variable  (PWM : Pulse Wide Modulation).

Schéma du montage

schema pwm pic16f877a

Le module PWM

Pour créer un signal carré dont la largeur des impulsions varie, le PIC16F877A utilise un module dédié appelé CCP (Capture Compare PWM).  C’est un module multifonction qui peut servir de registre de capture et de comparaison sur 16 bits ou de modulation de largeur d’impulsion sur 10 bits.

Chacun de ces modules est associé à trois registres :

CCPxCON : CCP Control Register c’est un registre de contrôle du CCP (x = 1 ou 2 car le composant en possède 2) ;

CCPRxH :  contient les 8 bits les plus significatifs du CCP ;

CCPRxL :  contient les 8 bits les moins significatifs du CCP.

Chaque module CCP est associé à une broche du composant dénommée CCPx (x = 1 ou 2).

 

Le registre CCPxCON

ccpxcon register pic16f877a

Les bits 7 et 6 ne sont pas implémentés et sont interprétés comme des valeurs 0 ;

Les bits 5 et 4 : DCxB1 et DCxB0, sont utilisés pour le rapport cyclique du PWM (bit1 et bit0). Ils représentent les 2  bits de poids faibles du rapport cyclique qui lui-même est codé sur 10 bits ; les 8 autres bits restant sont implémentés dans  le registre CCPRxL ;

Les bits 3, 2, 1 et 0 : CCPxM3, CCPxM2, CCPxM1, et CCPxM0 permettent de choisir le mode du fonctionnement du module CCP. Lorsque CCPxM3…CCPxM0 prennent  les valeurs :

0000  =>  Capture/Comparaison/PWM sont désactivés ;

0100  =>  Capture, sur front descendant ;

0101  =>  Capture, sur front montant ;

0110  =>  Capture tous les 4è front montant ;

0111 => Capture tous les 16è front montant ;

1000 => Comparaison, la broche de sortie correspondante est forcée à l’état bas ; elle passera à l’état haut si la comparaison est effective ou vraie ;

1001 => Comparaison, la broche de sortie correspondante est forcée à l’état haut ; elle passera à l’état bas si la comparaison est effective ou vraie ;

1010 => Comparaison, génère une interruption lorsque la comparaison est effective ;

1011 => Comparaison, déclenche des événements spéciaux (le bit CCPIF est positionné dans ce cas) ;

11xx => Mode PWM.

Pour l'exemple qui sera présenté, les bits CCPxM3, CCPxM2, CCPxM1, et CCPxM0 seront configurés pour le mode PWM.

 

Schéma bloc du module de capture - comparaison - PWM :

ccp module pic16f877a

Ce schéma montre en effet que le PWM est associé au Timer2.

Le signal de sortie sur la broche CCPx aura l’allure suivante :

chronogramme ccp pic16f877a

La période du signal, en unités de temps est obtenue par la formule suivante :

Période PWM = [PR2 + 1] x 4 x Tosc x (Valeur de pré diviseur TMR2) ;

PR2  contenu du registre 8 bits PR2, et TMR2  contenu du registre du Timer2.

Le mot binaire N des dix bits DCxB0…à DCxB9, permet de calculer le rapport cyclique en unités de temps par la formule :

N x Tosc x (Valeur du pré diviseur de TMR2).

 

Le PWM utilise le Timer2 pour fonctionner, il est géré par module T2CON (Timer2 Control):

t2con register pic16f877a

D’après la structure ci-dessus, le Timer2 sera actif à l’état haut grâce au bit TMR2ON.

Pour avoir une valeur 4 pour le pré diviseur, il suffit de positionner le bit T2CKPS0 à 1.

Le restant des bits sera égal à 0.

 

Programmation

Avant de commencer, on va noter que, les commentaires des programmes sont écrits en anglais pour essayer de rester en cohérence avec les instructions de programmation qui, par ailleurs le sont.

A titre d'illustration, on va créer un programme de test qui pemettra au microcontrôleur de générer un signal PWM sur la broche 2 du port C (RC2).

Le test visuel consiste à connecter une LED sur cette sortie afin de vérifier que sa luminosité dépend du signal PWM généré par le composant.

Dans un premier temps, on va créer des fichiers d’entêtes nécessaires pour les ports et les modules internes.

Le fichier « pwm.h » contient  les prototypes de fonction « initialisation du PWM » et « définition du rapport cyclique » :

#ifndef __PWM_H

#define __PWM_H

void PwmInit(void);
void PwmDutyCycleSet(unsigned int);

#endif

 

Le fichier « Includes.h », contient les entêtes nécessaires pour le programme :

#ifndef __INCLUDES_H

#define __INCLUDES_H

// Define CPU Frequency
// This must be defined, if __delay_ms() or
// __delay_us() functions are used in the code

#define _XTAL_FREQ   20000000 

#include "xc.h"

#include "pwm.h"

#endif

 

Les fichiers sources :

Ils sont au nombre de deux : « pwm.c » et « main.c ».

Le fichier « pwm.c » initialise le module PWM :

#include "Includes.h"

// Here CCP1 module is used to generate the required PWM
// Timer2 module is also used to generate the PWM
// PWM has 10bit resolution

void PwmInit(void)

{

     TRISC2  = 0;            // Make CCP1 pin as output
     CCP1CON = 0x0C;         // Make CCP1 module PWM mode
     PR2   = 0xFF;           // Configure the Timer2 period
     T2CON = 0x01;           // Set Prescaler to 4, so PWM frequency is 4.88KHz.
     PwmDutyCycleSet(0);     // Intialize the PWM duty cycle to 0
     T2CON |= 0x04;          // Enable the Timer2 with PWM

}

void PwmDutyCycleSet(unsigned int DutyCycle) // Give a DutyCycle value between 0 and 1024  

{

     CCPR1L   = DutyCycle>>2;             // Put MSB 8 bits in CCPR1L
     CCP1CON &= 0xCF;                     // Make bit4 and 5
     CCP1CON |= (0x30&(DutyCycle<<4));   // Assign Last 2 LSBs to CCP1CON

}

 

Le fichier « main.c » ; c’est le fichier principal du programme, dans ce fichier sera donnée la valeur de la largeur de l’impulsion désirée :

#include "Includes.h"

// Main function

void main(void)

{

     PwmInit ();    
     PwmDutyCycleSet (512);   //50% duty cycle
     while(1)

     {

     }

}

 

Simulation

Tous les fichiers étant créés, dans le fichier « main.c »,le rapport  cyclique est fixé par défaut à 512, soit 50%.On a donc modifié cette valeur à 128; le projet étant enrégistré, en cliquant sur « Build Project » , Proteus est lancé automatiquement et l’oscillogramme ci-après s’ouvre :

 

Donc pour 128 on a un rapport cyclique de 12,5%:

chronogramme pwm 128 pic16f877a

Pour 512, on a bien un rapport cyclique de 50%:

chronogramme pwm 512 pic16f877a

Il ne reste plus qu'à vérifier ceci sur le montage physique.

 

Réalisation

On va câbler le montage sur plaque à essais, conformément au schéma. On dispose pour cela d'une diode LED blanche afin de bien visualiser les différences de luminosité; d'une résistance de protection de la LED; d'un oscillateur à quartz de 20 MHz; de deux condensateurs de 15pF; puis du microcontrôleur PIC16F877A.

Une fois le microcontrôleur programmé, pour une valeur de rapport cyclique de 12,5%, on a ceci:

pwm led 2

Pour un rapport cyclique de 50%, on obtient:

pwm led 1

Ces deux photos illustrent bien l'effet de la variation du rapport cyclique sur la luminosité de la LED. On peut donc dire que le microcontrôleur génère bien un signal carré de fréquence fixe, dont la largeur des impulsion peut varier, PWM. C'est une  fonction, parmi tant d'autres que l'on trouve dans ce composant.