ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M.
GUEYE
Leçon 1 :
Débuter en C avec le PIC
Utiliser le compilateur PIC C (CCS compilateur) nécessite de débuter chaque projet par où vous
programmer une en-tête, où il est réalisé, les configurations du PIC. Dans cette section on
déclare, la vitesse à laquelle l'appareil effectue chaque instruction, la position de certains
dossiers dans la mémoire, etc.
#include <16f877a.h>
#use delay(clock=4000000)
#fuses xt, noprotect, nowdt, nobrownout, put, nolvp
#define sw1 portb,2
#define sw2 portb,1
#define led portb,0
#byte portb= 6
int cont;
• La première ligne indique le compilateur le type de microcontrôleur utilisé
• La deuxième ligne indique que vous travaillez avec un cristal de 4MHz.
• La troisième ligne est les fusibles de configuration
Type XT cristal oscillateur peut être choisi parmi les suivants (XT, RC, SH, LP)
XT: Un acronyme qui vient de XTAL (verre ou en castillan). Ce mode de fonctionnement
signifie que nous devons avoir un cristal de quartz externe et deux condensateurs à Pic. La
valeur sera généralement 4 MHz de cristal ou 10 MHz, et des condensateurs en céramique sont
entre 27 et 33 nF. La précision de ce dispositif est très élevée, ce qui est hautement recommandé
pour presque toutes les applications.
RC: Ceci est le système le plus simple et peu coûteuse. Elle est basée sur un ensemble avec une
résistance et un condensateur. La vitesse à laquelle travaille le PIC dépend des valeurs de la
capacité et de la résistance.
HS: A utlilser lorsque les applications ont besoin de «haute vitesse», entre 8 et 10 Mhz. Il est
également basé sur un cristal de quartz, comme la XT
LP: "Low Power" vitesse maximale avec cet oscillateur est de 200kHz. Comme le XT et HS,
on a besoin d'un cristal de quartz et des condensateurs ..
NOPROTECT pas de protection contre la lecture protégée
NOWDT pas activer le chien de garde
NOBROWNOUT faible tension de remise à zéro
NOPUT ne pas activer le temporisateur qui retarde le fonctionnement en présence de tension
NOLVP aucune programmation basse tension
• Le quatrième, cinquième et sixième ligne servent à définir un nom pour les différents bits à
utiliser dans le programme.
• La septième ligne indique la direction du port B en RAM (Ces adresses sont observées dans
la page Fiche technique.
• La huitième ligne indique que la variable est déclarée CONT entier, cette variable est globale,
comme il a été déclaré dans l'en-tête du programme et peut être utilisée à la fois dans le
programme principal et les différentes fonctions.
1
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
Avant de commencer la programmation, nous allons voir des instructions de code les plus
élémentaires avec lesquelles nous allons apprendre à demander une entrée spécifique et
simultanément pour activer une sortie spécifique.
Comment demander si une entrée est activée ?
if(bit_test(SW1))
{
décision;
}
La décision correspond à la décision à prendre dans le cas où l'entrée appelée "SW1" est activée,
l'entrée «SW1» a été défini dans l'en-tête
Ex: PORTB, 2 (RB2).
Si on ne souhaite pas nommer la broche dans l’entête du programme, on peut aussi se demander
si une entrée est active
if(bit_test(portb,2))
{
decision;
}
Comment demander si une entrée est désactivée ?
if(!bit_test(SW1))
{
decision;
}
Ou:
if(!bit_test(portb,2))
{
decision;
}
La décision correspond à la décision à prendre dans le cas où l'entrée est désactivée.
Comment transformer une sortie ?
bit_set(led);
ou
bit_set(portb,0);
Comment désactiver une sortie ?
bit_clear(led);
ou
bit_clear(portb,0);
Comment apporter une valeur à un port ?
(Notez que chaque port a un maximum de 8 bits)
PORTB = 15;
PORTB = 0X0F;
PORTB = 0B00001111:
(Décimal) (hexadécimal) (binaire)
Les trois instructions correspondent exactement à la même chose, affecter la valeur de 15 au
Port B uniquement dans un format différent.
2
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
Nous allons créer notre premier programme en langage C pour notre microcontrôleur. Il est
basé sur le système électronique suivant constitué d'un PIC16F877A un interrupteur et une Led.
EXEMPLE 1: Allumer la LED connectée à RB0 si le commutateur connecté à RB1 est actif.
include <16f877a.h>
#use delay(clock=4000000)
#fuses xt,protect,nowdt,nobrownout,put,nolvp
#define sw porta,1
#define led portb,0
#byte porta= 5
#byte portb= 6
main()
{
set_tris_a(0b10000000); // configurer le port a
set_tris_b(0b11111110); //configurer le port b
while(true) // faire toujours
{
if(bit_test(sw)) // si sw est actif
{
bit_set(led); // allumer la led
}
else // si non
{
bit_clear(led); // éteindre la led
}
}
}
EXEMPLE 2
Pour ce deuxième exemple, nous allons voir une nouvelle fonction de base, appelée "delay_ms
(en millisecondes) " . Ceci est une instruction de temporisation qui est très utile, car elle permet
de mettre le microcontrôleur en attente pour une période de temps, ne rien faire, pour ensuite
continuer avec votre routine.
3
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
Dans de nombreux programmes on aura besoin que le PIC soit toujours en attente de
visualisation ou d'attente pour un temps avant de poursuivre le programme.
delay_ms(1000); // retard d’une seconde
Dans l'exemple suivant, nous allons maintenant désactiver une LED connectée à rb0 chaque
demi-seconde.
#include <16f877A.h>
#use delay(clock=4000000)
#fuses
xt,noprotect,nowdt,nobrownout,put,nolvp
#define led portb,0
#byte portb= 6
main()
{
set_tris_b(0b11111110); //configure le portb en sortie
while(true) // faire toujours
{
bit_set(led); // allumer la led
delay_ms(500); // temprisation de 0.5 s
bit_clear(led); // éteindre la led
delay_ms(500); // temprisation de 0.5 s
}
}
EXEMPLE 3:
Dans cet exemple, on va utiliser une commande qui nous permet de changer l'état logique d'une
sortie, à savoir si la broche est en 1 passe à 0, et vice versa. Instruction est output_toggle (pin_x)
où «x» est remplacé par le niveau logique du pin qu’on veut changer.
output_toggle(pin_b1); //Modifie l'état logique de la broche b1
output_toggle(pin_c4); // Modifie l'état logique de la broche c4
4
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
output_toggle(pin_a2); // Modifie l'état logique de la broche a2
Dans l'exemple suivant, on va utiliser trois LED connectés au portb, l'idée est alors d’allumer
la led 1 toutes les 233 ms, la LED 2 tous les 592 ms et 879 ms pour la LED 3.
#include <16f887.h>
#use delay(clock=4000000)
#fuses xt,noprotect,nowdt,nobrownout,put,nolvp
#byte portb= 6
long led1, led2, led3; //declaration de variables
//programme principal
void main()
{
set_tris_b(0); //configurer le portb en entrée
//initialisation des variables
led1=0;
led2=0;
led3=0;
while(true) // faire toujours
{
delay_ms(1); //temporization de 1 ms
Led1++; // incrémenter le compteur led 1
led2++; // incrémenter le compteur led 2
led3++; // incrémenter le compteur led 3
if (led1==233) //si le compteur atteint 233 ms
{ output_toggle(pin_b0); // changer l’état logique de b0
led1=0;
}
if (led2==595){ // si le compteur atteint 595 ms
output_toggle(pin_b1); // changer l’état logique de b1
led2=0;
}
if (led3==879){ // si le compteur atteint 879 ms
output_toggle(pin_b2); // changer l’état logique de b2
led3=0;
5
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
}
}}
Lecon 2 : LE CONVERTISSEUR ANALOGIQUE NUMERIQUE
Les microcontrôleurs PIC16F887 ont un convertisseur analogique / numérique de 10 bits et 14
canaux d'entrée (AN0, AN1, ..., AN7).
Un signal analogique est un signal continu, par exemple un signal de 0 à 5V est un signal
analogique qui peut prendre des valeurs (1V, 2V, 2,5 V, etc.). Un signal numérique ne peut
avoir que deux valeurs 0 ou 5 V, ouvert ou fermé, allumé ou éteint.
Avec le microcontrôleur, on cherche à rapprocher un signal analogique d’un signal numérique
à travers des images numériques de petits rectangles, comme indiqué dans la figure ci-dessus.
Avec La résolution de traitement du microcontrôleur, les petits rectangles peuvent obtenus sont
proches du signal analogique s’ils sont associés.
Un capteur de niveau qui génère un signal analogique n’informe pas seulement si un réservoir
est plein ou vide, mais il délivre à tout instant un signal proportionnel au niveau de la cuve.
Un convertisseur A / N convertit le signal analogique à un nombre numérique (binaire), le
nombre est proportionnel au signal analogique.
Pour le PIC16F877A le convertisseur A / N comporte 10 bits et le signal d'entrée analogique
peut être comprise entre 0 V et 5 V, il comporte aussi deux niveaux de référence Vref + et Vref
– où doit évoluer la valeur du signal d'entrée analogique. La tension différentielle minimale est
de 2 V, soit la différence entre Vref + et Vref - et ne peut pas dépasser 2V.
Avec 10 bits le plus grand nombre binaire peut est de 1024, la résolution de l'A / D est donnée
par la formule:
−
é =
1024
Par exemple, si Vref + = 5V et Vref - = 0 V, la résolution est de 5 V / 1024 = 4.8 mV lorsque
le signal analogique est 0 V correspond à 0000000000 et 5V aura comme nombre numérique
1111111111.
Si VREF + = + 5V et Vref- = 0 V peuvent être déterminées à tout moment à un nombre binaire
correspond approximativement à l’entrée du signal analogique par la formule :
6
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
é é
=
4,8 0,0048
Par exemple, si le signal analogique est 2V, le nombre numérique approximatif, est :
2
= 416
4,8
La tension de référence Vref peut être mise en œuvre avec la tension d'alimentation VDD
interne, ou bien avec une tension externe qui est placée sur le broche RA2 / AN2.
Les étapes de travailler avec A / D
1. Dans l'en-tête du programme on met la ligne suivante, si o utilise l'A / D 10 bits par défaut
fonctionnant à 8 bits
#DEVICE ADC=10
2. Dans le programme principal
- Définir les entrées analogiques.
- Sélectionnez le type de convertisseur horloge A/ D.
- Spécifiez le canal à utiliser pour la conversion
a) SETUP_ADC_PORTS(Valeur);
Cette fonction configure les repères de la CAN à être analogique, entrées numériques ou une
combinaison des deux. Les combinaisons autorisées varient en fonction du microcontrôleur.
Les constantes (ALL analogique) toutes les entrées sont analogiques et (NO_ANALOG) toute
les entrées ne sont pas analogiques
b) SETUP_ADC (Mode)
Sélectionnez le type d'horloge A/ D mode convertisseur peut être :
1. ADC_CLOCK_DIV_2
2. ADC_CLOCK_DIV_8
3. ADC_CLOCK_DIV_32
4. ADC_CLOCK_INTERNAL
Ceci est le temps nécessaire pour avoir la conversion numérique de la tension analogique
appliquée à l’entrée. Ce temps dépend de l’horloge sélectionné pour la conversion. Pour que la
conversion soit correcte, l'horloge doit être sélectionnée pour assurer un temps de 1.6 us.
c) SET_ADC_CHANNEL (Canal)
Spécifie le canal à utiliser par la fonction
READ_ADC()
Lire la valeur de la conversion
I=READ_ADC ()
Cette fonction lit la valeur numérique du convertisseur analogique-numérique.
EXEMPLE :
Faire un thermomètre numérique en utilisant PIC16F877A avec un capteur de température
(LM35) raccordé sur la broche RA0. Utiliser la conversion numérique-analogique pour la
lecture du capteur de température et afficher la température sur un afficheur LCD16x2.
Le capteur envoie 0,25V au PIC si la température vaut LM35 25 ° C . Basé sur cette information,
on peut faire la conversion de la température de BITS en degrés celcius. En utilisant une règle
de base, on peut déterminer cela.
7
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
, ×
, = = 51,2 bits
On peut transformer les bits correspondant à 25° C en degrés celcius.
× _
degrésC = = × 0,4883
,
#include <16f887.h>
#device adc=10
#USE DELAY(CLOCK=4000000)
#FUSESXT,NOPROTECT,NOWDT,NOBROWNOUT,NOPUT,NOLVP
#INCLUDE <LCD.C>
#BYTE PORTA= 5
#BYTE PORTD= 8
long bits; // Variable bits
float tem; //variable temperature
void main()
{
set_tris_a(0b00000001); //configuration de RA0 en entrée
setup_adc_ports(all_analog); // toutes les broches de l’A/D en entrée analogique
setup_adc(adc_clock_internal); // selection de l’Horloge interne pour la conversion
lcd_init(); //Initialiser le LCD
lcd_putc("\f"); //effacer le LCD
while(1)
{
set_adc_channel(0); // Selectionner le canal 0 (RA0)
delay_ms(1); // temporisation de 1 ms
bits=read_adc(); //Sauvegardez les données de LM dans bits
tem=bits*0.4882; //Conversion de bits en température
lcd_gotoxy(1,1); //aller à la position 1,1 sur l’afficheur
lcd_putc("LA TEMPERATURE");
lcd_gotoxy(2,2); // aller à la position 2,2 sur l’afficheur
printf(lcd_putc,"ES C= %f ",tem); // Affiche la valeur numérique de la conversion
}
}
Leçon 3 : Le signal PWM
Pour générer un signal PWM avec le PIC, on peut utiliser le module PCC suivant trois modes
de fonctionnement.
- En mode de capture de la valeur du timer est copiée dans le registre de CCP_X lorsque
l'événement se produit sur la broche d'entrée
- En mode de comparaison il va déclencher une action lorsque les valeurs du timer et du CCP_x
sont égales
En mode PWM il va générer une onde carrée
Le PIC16F877A comporte deux modules PCC comme on le voit sur la figure ci-dessous, qui
correspondent aux broches 16 et 17 (RC1 et RC2).
8
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
Le PWM ou MLI (Pulse width modulation, modulation de largeur d’impulsion) est un module
qui génère sur les broches CCP1 (Pin 17) et CCP2 (Pin 16) un signal périodique avec rapport
cyclique variable. Cette PWM peut avoir une résolution maximale de 10 bits. En d'autres
termes, comme nous savons que le PIC fonctionne avec des tensions binaires (0V ou + 5V),
nous pouvons définir le PWM à travailler un certain temps à + 5V (Ton) et au niveau bas 0V
(Toff), que nous pouvons voir sur la figure ci-dessous.
Ainsi, la tension moyenne appliquée à la charge est proportionnelle à la durée du signal (Ton)
et ainsi on peut par exemple contrôler la luminosité d’une lampe, ou la vitesse d'un moteur.
MODULE CCP
Le compilateur nous donne les instructions de base pour le fonctionnement du PWM. Pour
configurer le module CCP:
setup_ccpx(mode); Définit les modes, capturer, comparer ou PWM.
set_pwmx_duty(valeur); où x désigne le module du CCP utilisé, dans le cas de PIC16F877A
on a seulement CCP1 et CCP2.
Comme utiliser ces instructions ?
Pour générer un signal PWM au PIC, nous devons utiliser le timer 2 qui est un temporisateur 8
bits.
En interne, le PIC utilise TIMER 2 comme base de temps pour la modulation PWM utilisant le
module PCC.
9
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
Avec la formule suivante on peut calculer la fréquence de sortie
é
é =( )×( )×
Le Prescaler du timer 2 peut être de 1, 4 ou 16. La charge du timer2, pourrait également être
appelée comme la période du signal et peut prendre des valeurs entre 0 et 255.
Si nous utilisons un quartz de 4 MHz, la fréquence minimale est :
4 4000000
= = = 244
é
(255 + 1) × 16 × 4 16,384
Valeur maximale
é = = = 500000 Hz
( )× ×
Exemple : nous allons générer une onde carrée de 1 kHz en utilisant le timer 2, le module de
CCP1 du Pic et le compilateur CCS C.
Pour générer une onde carrée de 1 kHz il est nécessaire de calculer d’abord la période (inverse
de la fréquence) f = 1 kHz = 1000 Hz.
= = 1 ms
Calculer le temps de débordement du timer 2 avec la formule suivante.
= (charge du timer 2 +1)× 4 × ( 2) × ×
En remplaçant les valeurs nous aurons :
1
1ms = (X + 1) × 4 × (4) × ×1
4000000
Nous constatons que la valeur de X = 249. (Rappelant que X doit être comprise entre 0-255)
Le timer 2 se lirait comme suit :
setup_timer_2(T2_DIV_BY_4, 249,1);
Le cycle de travail est fixé par la déclaration suivante :
set_pwm1_duty(valeur);
Valeur : est un facteur de 8 ou 16 bits qui détermine le cycle de travail. Cette valeur avec la
valeur de l'étage d'adaptation TMR2, déterminer la valeur du rapport cyclique. Dans la
configuration du timer 2, le pos est de 1 pour une valeur 16 bits.
Nous allons mettre en pratique le concept de PIC PWM :
Il existe de nombreux procédés électroniques ou industriels où nous avons besoin de contrôler
la vitesse d'un moteur à courant continu. Une façon simple d'y parvenir est d'utiliser un contrôle
PWM.
Pour cela, nous allons concevoir le schéma et le code à implémenter dans le microcontrôleur
via CCS compilateur C pour réguler la vitesse d'un moteur à courant continu via un
potentiomètre relié au port RA0.
10
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
#include <16f877A.h>
#device ADC=10
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
int16 duty=0;
int Timer2, Pos;
void main()
{
Timer2=249; // le timer 2 est chargé avec la valeur 249
//Prescaler=4; // Prescaler ne peut prendre des valeurs: 1, 4, 16
// le mettre dans le diviseur "t2_div_by_4"
Pos=1; //pos ne peut prendre que la valeur de 1
setup_timer_2(t2_div_by_4,Timer2,Pos); //Configurer le Timer 2 pour une fréquence du
PWM à 1kHz.
setup_ccp1(ccp_pwm); // configurer le timer 2 pour CCP1 en mode PWM
setup_adc_ports(all_analog);
//Configurer le convertisseur analogique numérique
setup_adc(adc_clock_internal);
while(1)
{
set_adc_channel(0);
delay_us(100);
duty=read_adc();
set_pwm1_duty(duty);
}
}
11
ENSETP/5eBS2 INFORMATIQUE INDUSTRIELLE M. GUEYE
12