Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Faculté de la Technologie
Département d’Electronique
Thème
Programmation en C
du Microcontrôleur
PIC 16F877
Master S1 2009/2010
Sommaire
Introduction Générale…………………………………………………………………………………………...1
Conclusion……………………………………………………………………………………....…………….20
1. Choix du compilateur…………………………………………………………………………………….21
2. Quelques notions de programmation en C sous SourceBoost…………………………..21
3. Structure d’un programme…………………………………………………………………………….27
4. Exemple d’application……………………………………………………………………………………27
Conclusion…………………………………………………………………………………………………….32
Conclusion Générale……………………………………………………………………………………..……..33
Bibliographie
Introduction Générale
Le développement des applications à base des microcontrôleurs PIC est devenu de plus en
plus courant, ceci est dû à plusieurs causes : beaucoup de ressources internes (périphériques
intégrés), mémoires embarquées de plus en plus grande, vitesse de calcul accrue… En effet, un
microcontrôleur est un composant parfaitement adapté à des applications embarquées, il permet, en
le programmant, d’effectuer et de contrôler une tâche tout en comparant son état à des conditions
préfixées par l’utilisateur.
L’utilisation des microcontrôleurs fait appel tout d’abord à leur programmation. Il existe
plusieurs méthodes de programmation selon le langage utilisé, par exemple en assembleur on peut
écrire un programme où on va tirer le maximum des performances du microcontrôleur mais ce
programme nécessite beaucoup de travail et surtout beaucoup de temps. Heureusement, avec la
montée en puissance des microcontrôleurs, on voit apparaitre des compilateurs en langage C qui
permettent de gagner un temps considérable pour le développement des programmes.
Dans ce travail notre choix est porté vers le PIC 16F877. Dans le premier chapitre nous allons
étudier d’une manière générale ce microcontrôleur et ses différentes ressources internes, ensuite un
deuxième chapitre destiné à la programmation de ce microcontrôleur en langage C en utilisant le
compilateur SourceBoost, dans ce chapitre nous allons exposer quelques notions de programmation
en C et de proposer un exemple d’application.
1
Chapitre 1 Etude théorique du PIC 16F877
Introduction :
Un microcontrôleur est un composant électronique ayant une unité de traitement de
données, des mémoires, des interfaces de communication (entrées/sorties, ports séries . . .) et de
multiple ressources interne. Souvent un microcontrôleur se contente d’un bus de données de 8-bits
ou 16-bits, on peut dire alors qu’il est moins puissant qu’un microprocesseur.
Un PIC est un composant dit RISC (Reduced Instructions Set Computer), ou encore composant à
jeu d’instruction réduit. Ces microcontrôleurs sont conçus sur une architecture dite HAVARD, elle est
basée sur deux bus, un pour les données (bus de données) et l’autre pour les instructions (bus de
programme).
Base line : c’est la famille où l’unité centrale travaille sur 12-bits, exemple : 12CXXX…
Mid-Range : c’est la famille où l’unité centrale travaille sur 14-bits, exemple : 16F877.
High Performance : c’est la famille où l’unité centrale travaille sur 16-bits, exemple : 18FXXX,
18CXXX …
Exemple du 16F877-20 :
2
Chapitre 1 Etude théorique du PIC 16F877
33 pins d’entrées/sorties
multiplexées avec d’autres
fonctions.
4 pins pour l’alimentation :
VDD et VSS.
2 pins pour l’oscillateur :
OSC0 et OSC1.
1 pin pour le RESET : MCLR.
3
Chapitre 1 Etude théorique du PIC 16F877
Une fois le programme est stocké dans la mémoire (Program Memory) et le µC est initialisé,
l’instruction à exécuter est désignée par le PC (Program Counter) et sera chargée dans le registre
d’instruction (Instruction reg) au moyen d’un bus de programme sur 14-bits, puis elle sera décodée
dans le décodeur et le contrôleur d’instruction (Instruction Decode & Control) et ensuite dirigée vers
l’UAL (ALU) avec les données chargées à partir des pins configurées comme entrées, l’UAL fera
l’opération nécessaire et sauvegardera le résultat temporairement dans le registre de travail (W reg)
sur 8-bits, ce résultat sera aussi mit dans la RAM à l’aide d’un bus de données sur 8-bits.
4
Chapitre 1 Etude théorique du PIC 16F877
5
Chapitre 1 Etude théorique du PIC 16F877
L’EEPROM est sur 256 octets prévue pour sauvegarder les données en cas de perte
d’alimentation, le nombre de cycle lecture/écriture est limité à l’ordre de 106 cycles.
Chacun de ces modes peut être sélectionné à travers les bits de configuration FOSC1 et FOSC0
(registre : CONFIGURATION WORD à 2007h), comme suit :
Toujours dans l’un de ces modes de fonctionnement, le microcontrôleur peut avoir une horloge
externe connectée à la broche OSC1/CLKIN comme le montre la figure suivante :
6
Chapitre 1 Etude théorique du PIC 16F877
3.2 Oscillateur RC :
La fréquence de l’oscillation dépend du voltage, des valeurs de R et C et de la température de
fonctionnement. La figure (1.4.2) montre comment connecter un circuit RC au microcontrôleur :
4.1 PORT A :
Le PORTA est un port bidirectionnel de 6-bits (6 entrées/sorties) : de RA0 jusqu'à RA5; le
registre correspondant qui définit la direction des données est le TRISA, la mise à ‘1’ d’un bit du
TRISA configura la broche correspondante à ce bit comme entrée, et la mise à ‘0’ de ce bit mettra la
broche correspondante comme sortie.
La broche RA4 est multiplexée avec une autre fonction qui est l’entrée pour l’horloge du
TIMER0, cette broche deviendra donc RA4/T0CKI. Les autres pins sont multiplexées avec les entrées
analogiques du CAN et l’entrée VREF, pour cela, le registre ADCON1 permet de déterminer la fonction
de chaque pin.
7
Chapitre 1 Etude théorique du PIC 16F877
Valeur Valeur
Adresse Nom Bit-7 Bit- Bit- Bit- Bit-3 Bit-2 Bit-1 Bit-0 sur sur
6 5 4 POR, autres
BOR RESET
05h PORTA - - RA5 RA4 RA3 RA2 RA1 RA0 --0x 0000 --0u 0000
85h TRISA - - Registre de direction des données PORTA --11 1111 --11 1111
9Fh ADCON1 ADFM - - - PCFG3 PCFG2 PCFG1 PCFG0 --0- 0000 --0- 0000
x : inconnu, u : inchangé, - : emplacements non implémentés (‘0’), les cellules ombragées ne sont pas
utilisées par le PORTA.
Au démarrage (Power-On Reset ‘POR’), les pins de ce port sont configurés comme des entrées
analogiques et lus comme ‘0’.
4.2 PORT B :
Le PORTB est un port bidirectionnel de 8-bits (8 entrées/sorties) : de RB0 jusqu'à RB7; le
registre correspondant qui définit la direction des données est le TRISB, la mise à ‘1’ d’un bit du TRISB
configura la broche correspondante à ce bit comme entrée, et la mise à ‘0’ de ce bit mettra la broche
correspondante comme sortie.
En mode entrée, chaque broche du PORTB doit être maintenue à un niveau haut à l’aide des
résistances de pull-up, ceci en mettant à ‘0’ le bit RBPU (du registre OPTION). En mode sortie ou lors
d’un POR (Power-On Reset), ces pull-ups sont désactivés. Un changement d’état sur l’une des
broches RB4, RB5, RB6 et RB7 déclenche une interruption, ceci n’est possible que pour celles qui sont
configurées comme entrées.
Valeur Valeur
Adresse Nom Bit-7 Bit-6 Bit-5 Bit-4 Bit-3 Bit-2 Bit-1 Bit- sur sur
0 POR, autres
BOR RESET
06h, PORTB RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 xxxx xxxx uuuu uuuu
106h
86h, TRISB Registre de direction des données PORTB 1111 1111 1111 1111
186h
81h, OPTION_REG RBPU INTEDC T0CS T0SE PSA PS2 PS1 PS0 1111 1111 1111 1111
181h
x : inconnu, u : inchangé, les cellules ombragées ne sont pas utilisées par le PORTB.
4.3 PORT C :
Le PORTC est un port bidirectionnel de 8-bits (8 entrées/sorties) : de RC0 jusqu'à RC7; le
registre correspondant qui définit la direction des données est le TRISC, la mise à ‘1’ d’un bit du TRISC
configura la broche correspondante à ce bit comme entrée, et la mise à ‘0’ de ce bit mettra la broche
correspondante comme sortie.
8
Chapitre 1 Etude théorique du PIC 16F877
4.4 PORT D :
Le PORTD est un port bidirectionnel de 8-bits (8 entrées/sorties) : de RD0 jusqu'à RD7; le
registre correspondant qui définit la direction des données est le TRISD, la mise à ‘1’ d’un bit du
TRISD configura la broche correspondante à ce bit comme entrée, et la mise à ‘0’ de ce bit mettra la
broche correspondante comme sortie.
Le PORTD peut être configuré comme port parallèle esclave : PSP (Parallel Slave Port) en
mettant à ‘1’ le bit PSPMODE du registre TRISE.
Valeur Valeur
Adresse Nom Bit-7 Bit- Bit-5 Bit-4 Bit-3 Bit-2 Bit-1 Bit-0 sur POR, sur
6 BOR autres
RESET
08h PORTD RD7 RD6 RD5 RD4 RD3 RD2 RD1 RD0 xxxx xxxx uuuu uuuu
88h TRISD Registre de direction de données PORTD 1111 1111 1111 1111
89h TRISE IBF OBF IBOV PSPMODE - Registre de direction 0000 -111 0000 -111
de données PORTE
x : inconnu, u : inchangé, - : emplacements non implémentés (‘0’), les cellules ombragées ne sont pas
utilisées par le PORTD.
4.5 PORT E :
Le PORTE a 3 broches : RE0, RE1 et RE2, configurables en entrées ou en sorties à partir des
trois premiers bits du registre TRISE. Ces broches sont multiplexées avec les entrées du CAN
(Convertisseur Analogique Numérique).
Au démarrage (Power-On Reset ‘POR’), les pins de ce port sont configurés comme des entrées
analogiques et lus comme ‘0’.
9
Chapitre 1 Etude théorique du PIC 16F877
Valeur Valeur
Adresse Nom Bit-7 Bit- Bit-5 Bit-4 Bit-3 Bit-2 Bit-1 Bit-0 sur sur
6 POR, autres
BOR RESET
09h PORTE - - - - - RE2 RE1 RE0 ---- -xxx ---- -uuu
89h TRISE IBF OBF IBOV PSPMODE - Registre de direction de 0000 -111 0000 -111
données PORTE
9Fh ADCON1 ADFM - - - PCFG3 PCFG2 PCFG1 PCFG0 --0- 0000 --0- 0000
x : inconnu, u : inchangé, - : emplacements non implémentés (‘0’), les cellules ombragées ne sont pas
utilisées par le PORTE.
Le PSP peut interfacer directement avec un microprocesseur 8-bits (bus de données sur 8-bits)
à l’aide des broches :
L’écriture dans le PSP ce fait lorsque CS et WR sont à ‘0’, et quand l’une de ces broches se met à ‘1’ le
bit flag IBF (Input Buffer Full) (du registre TRISE) se met à ‘1’ pour signaler la fin de l’écriture.
La lecture du PSP ce fait lorsque CS et RD sont à ‘0’. Dès la mise à ‘0’ de ces derniers, le bit flag OBF
(Output Buffer Full) (du registre TRISE) se met immédiatement à ‘0’ pour indiquer que le PORTD est
en attente pour être lue par le bus externe. Quand CS ou RD se met à ‘1’, c’est la fin de la lecture et
qui sera signalée par le bit PSPIF (PSP Interrupt Flag) (du registre PIR1) en se mettant à ‘1’.
Quand le mode PSP est désactivé, les bits IBF et OBF doivent être à ‘0’. Cependant, même si le bit
IBOV était à ‘1’, il doit être effacé par logiciel.
10
Chapitre 1 Etude théorique du PIC 16F877
5 Timers :[4]
5.1 Timer0 :
Le Timer0 est un 8-bits temporisateur /compteur.
Le mode compteur est sélectionné en mettant à ‘1’ le bit T0SC (OPTION_REG), dans ce cas le
Timer0 sera incrémenté soit sur front montant soit sur front descendant de l’horloge externe sur la
patte RA4/T0CKI. Le front d’incrémentation est sélectionné à partir du bit T0SE (OPTION_REG).
Le Timer0 peut engendrer une interruption lors d’un débordement de FFh à 00h, ce
débordement mit à ‘1’ le bit T0IF (INTCON) pour signaler l’interruption, après la fin de l’interruption
ce bit doit être effacé par logiciel. Il suffit de mettre à ‘0’ le bit T0IE (INTCON) pour désactiver
l’interruption du Timer0.
Pour ce module Timer0 un pré-diviseur (Prescaler) est disponible et il est partagé avec le
Timer Chien de garde WDT (Watchdog Timer), l’assignation du pré-diviseur au Timer0 fait que le
WDT n’a pas de pré-diviseur associé, et vice-versa. L’assignation et la sélection de taux de division de
fréquence se fait à l’aide des bits PSA (pour l’assignation) et PS2 :PS0 (pour le taux) (registre
OPTION_REG). Quand le pré-diviseur est assigné au Timer0, l’écriture dans le registre TMR0 efface le
pré-diviseur mais ne change pas son assignation, et aussi, cette écriture fait que l’incrémentation ne
reprenne qu’après un délai de trois cycles d’instructions.
5.2 Timer1 :
Le Timer1 est un temporisateur/compteur 16-bits, il possède 2 registres : TMR1H et TMR1L
chacun est sur 8-bits qui s’incrémentent de 0000h à FFFFh. Le Timer1 déclenche une interruption sur
un passage de FFFFh à 0000h (débordement du Timer1), cette interruption est signalée par la mise à
‘1’ du bit TMR1IF (registre PIR1). Cette interruption peut être activée/désactivée en mettant à’1’/’0’
le bit TMR1IE (registre PIE1).
Ce module peut être activé/désactivé à l’aide du bit TMR1ON (registre T1CON) ,1/0.
11
Chapitre 1 Etude théorique du PIC 16F877
a. Mode temporisateur :
Dans ce cas le Timer1 est incrémenté chaque cycle d’instruction. Ce mode est sélectionné en
mettant à ‘0’ le bit TMR1CS (registre T1CON), cependant l’horloge du timer est FOSC/4 et le bit de
contrôle de synchronisation avec l’horloge interne T1SYNC (registre T1CON) n’a pas d’effet puisque
l’horloge utilisée est l’interne.
b. Mode compteur :
Ce mode est sélectionné en mettant à ‘1’ le bit TMR1CS. Et dès que le Timer1 est activé en
mode compteur, le module doit avoir un front descendant avant que l’incrémentation ne commence.
Cependant le Timer1 fonctionne soit en mode synchrone, soit en mode asynchrone.
En mode synchrone, sélectionné en mettant à ‘0’ le bit T1SYNC, le timer est incrémenté
chaque front montant de l’horloge externe sur la patte RC1/T1OSI/CCP2 si le bit T1OSCEN est mis à
‘1’, ou sur la patte RC0/T1OSO/T1CKI si le bit T1OSCEN est mis à ‘0’. Dans ce cas l’horloge externe est
synchronisée avec la phase de l’horloge interne. Dans cette configuration et durant le mode SLEEP
(mode sommeil), l’incrémentation du timer est arrêtée puisque le circuit de synchronisation est
arrêté.
En mode asynchrone, sélectionné en mettant à ‘1’ le bit T1SYNC, le timer est incrémenté à
chaque front montant de l’horloge externe sans que cette dernière ne soit synchronisée avec
l’horloge interne. Dans cette configuration et durant le mode SLEEP (mode sommeil), le timer
continu l’incrémentation et peut générer une interruption sur un débordement qui réveille le µC de
son sommeil.
Remarque : [3]
Il existe deux sources d’horloge externe : un signal externe appliqué à la patte RC0/T1OSO/T1CKI, ou
il peut utiliser le signal d’un oscillateur qui lui est propre en mettant à ‘1’ le bit T1OSCEN, réalisé en
connectant un quartz entre les pattes RC0/T1OSO/T1CKI et RC1/T1OSI/CCP2.
12
Chapitre 1 Etude théorique du PIC 16F877
Quand TMR1CS = 0 :
Ce bit est ignoré. Le Timer1 utilise l’horloge interne quand TMR1CS = 0.
Bit 1 TMR1CS : Bit de sélection de source d’horloge du Timer1.
1 = Horloge externe sur la pin RC0/T1OSO/T1CKl (sur le front montant).
0 = Horloge interne (FOSC / 4).
Bit 0 TMR1ON : Bit de mise en marche du Timer1.
1 = Active le Timer1.
0 = Stoppe le Timer1.
5.3 Timer2 :
Le Timer2 est un temporisateur 8-bits avec un pré-diviseur, un post-diviseur et un registre sur
8-bits PR2 dit registre de période. Le registre TMR2 est incrémenté, à l’aide de l’horloge interne
(FOSC/4), de 00h jusqu’à une valeur spécifiée dans le registre PR2, puis il recommence de 00h.
Lorsqu’il y a une égalité entre le contenu du registre TMR2 et celui du PR2, un signal sera appliqué au
post-diviseur (4-bits) pour générer une interruption.
Le Timer2 est arrêté sur la mise à ‘0’ du bit TMR2ON (du registre T2CON).
13
Chapitre 1 Etude théorique du PIC 16F877
00 = Pré-division par 1.
01 = Pré-division par 4.
1x = Pré-division par 16.
Le port MSSP est activé en mettant à ‘1’ le bit SSPEN (registre SSPCON). Pour redémarrer et
reconfigurer le mode SPI, on mit à ‘0’ le bit SSPEN, réinitialise le registre SSPCON, ensuite on mit à ‘1’
le bit SSPEN. Ceci configure les pattes SDO, SDI, SCK et SS pour le MSSP.
14
Chapitre 1 Etude théorique du PIC 16F877
Une donnée est reçue/transmise s’il y aura une écriture dans le registre SSPBUF, et quand cette
opération est établie, le bit SSPIF se mit à ‘1’ pour le signaler (déclanchement d’une interruption).
En mode maître, le µC peut transférer les données à m’importe quel moment parce que c’est lui qui
contrôle l’horloge (SCK). Tandis qu’en mode esclave, les données sont reçues ou transmises à
chaque coup de l’horloge (SCK).Cependant, il peut recevoir/transmettre des données en mode SLEEP,
le µC s’éveillera lors de la réception de données.
Le transfert de données se fait à travers le registre SSPSR qui n’est accessible qu’à partir le
registre SSPBUF, donc les données qui seront transmises/reçues, seront écrites dans le registre
SSPBUF. Vu qu’on peut connecter plusieurs maîtres/esclaves dans ce cas, le µC utilise des adresses
pour l’information envoyée ne sera prise en compte que par le composant de destination.
Le bit SPEN (registre RCSTA) et les bits 6 et 7 du registre TRISC doivent être à ‘1’ pour que les deux
pattes RC6/TX/CK et RC7/RX/DT soient configurées en USART.
Initialisation du registre SPBRG par une valeur pour déterminer la vitesse de transmission.
Validation du port asynchrone série.
Si on désire des interruptions, on doit mettre à ‘1’ le bit TXIE (bit de validation de
l’interruption de transmission de l’USART) (registre PIE1 à l’adresse 8Ch).
Si on désire transmettre 9-bits, on doit mettre à ‘1’ le bit TX9 (registre TXSTA).
Validation de la transmission en mettant à ‘1’ le bit TXEN (registre TXSTA), ce qui mettra le bit
TXIF (registre PIR1, adresse 0Ch) à ‘1’.
Ecriture du 9ème bit dans TX9D (registre TXSTA), si la transmission 9-bits est sélectionnée.
15
Chapitre 1 Etude théorique du PIC 16F877
Réception asynchrone :
Initialisation du registre SPBRG par une valeur pour déterminer la vitesse d’émission.
Validation du port asynchrone série.
Si on désire des interruptions, on doit mettre à ‘1’ le bit RCIE (bit de validation de
l’interruption de réception de l’USART) (registre PIE1 à l’adresse 8Ch).
Si on désire recevoir 9-bits, on doit mettre à ‘1’ le bit TX9 (registre RCSTA, adresse 18h).
Validation de la réception en mettant à ‘1’ le bit CREN (registre RCSTA).
Génération d’une interruption lors de la fin de réception, qui sera signalée par la mise à ‘1’
du bit RCIF (registre PIR1). Cette interruption ne sera générer que lorsque le bit de validation
de l’interruption RCIE (registre PIE1) est ‘1’.
Lecture du registre RCSTE pour avoir le 9ème bit (si la réception 9-bits est validée).
Lecture du registre RCREG pour avoir l’octet reçu.
Si on utilise les interruptions, il faut s’assurer que les bits GIE et PEIE (registre INTCON) sont à
‘1’.
Le principe est le même que celui du mode asynchrone avec deux différences majeures :
Émission et réception simultanées ne sont pas possibles, le fait d’activer l’une désactive
automatiquement l’autre.
Lorsque l’USART est en mode maître, c’est lui qui fournit l’horloge sur la patte RC6/TX/CK à
une fréquence fixée par le contenu du registre SPBRG ; lorsqu’il est en mode esclave, il reçoit
l’horloge sur cette même patte RC6/TX/CK.
ADCON0 : qui est un registre de contrôle des opérations du CAN, il est disponible à l’adresse
1Fh.
ADCON1 : qui est un registre de configuration du CAN, il est disponible à l’adresse 9Fh.
ADRESL : registre de résultat de la conversion, il contient les bits du poids faible, disponible à
l’adresse 9Eh.
16
Chapitre 1 Etude théorique du PIC 16F877
ADRESH : registre de résultat de la conversion, il contient les bits du poids fort, disponible à
l’adresse 1Eh.
Remarque :
Du fait que le registre pair du résultat (ADRESH : ADRESL) est sur 16-bits, on a donc la possibilité de
justifier le résultat (qui est sur 10-bits) soit à gauche en mettant à ‘0’ le bit ADFM (registre ADCON1),
soit à droite en mettant le bit ADFM à ‘1’.
17
Chapitre 1 Etude théorique du PIC 16F877
Registre de capture.
Registre de comparaison.
Registre de la PWM.
Ce registre de 16-bits CCPR1 pour le module CCP1 (ou CCPR2 pour le module CCP2) est constitué de
deux registres de 8-bits chacun : CCPR1L (CCPR2L) qui contient l’octet bas et CCPR1H (CCPR2H) qui
contient l’octet haut.
18
Chapitre 1 Etude théorique du PIC 16F877
Vu que les deux modules sont identiques, on ne décrira qu’un seul : CCP1.
Quand une capture est faite, il y aura génération d’une interruption signalée par le bit CCP1IF.
Le Timer1 étant associé au mode capture, il doit fonctionner en mode temporisateur ou compteur
synchronisé. La patte RC2/CCP1 doit être configurée en entrée.
En ce même temps, le bit CCP1IF se mit à ‘1’ pour signaler une interruption.
Même chose pour le Timer1, il doit être configuré en temporisateur ou en compteur synchronisé,
tandis que la patte RC2/CCP1 doit être configurée en sortie.
19
Chapitre 1 Etude théorique du PIC 16F877
Le registre CCPR1H est utilisé comme esclave du CCPR1L et ne peut être écrit par le
programmateur, il sert, avec les deux autres bits, à sauvegarder la valeur du rapport cyclique pour
ensuite générer une même période que la précédente, cette sauvegarde ne se produit que lorsque la
valeur du PR2 soit égale à celle du TMR2 (cette égalité signifie qu’une période est terminée).
Conclusion :
Cette étude théorique nous a permis de traiter et de comprendre le fonctionnement des
différentes ressources interne du PIC 16F877, d’envisager des applications pour ce µC et on va
présenter une de ces applications dans le chapitre qui suit.
20
Chapitre 2 Programmation en C et application
Introduction :
La programmation des microcontrôleurs PIC est supportée par plusieurs langages de
programmation tel que : MPLAB, l’Assembleur, le C ou C++. Dans ce chapitre on va présenter de
manière générale la procédure de programmation en C des microcontrôleurs PIC et donner quelques
exemples d’application.
2.1.Les directives :
Directives de compilation :
#include <nomdufichier.h>
Cette directive indique au pré-compilateur d’inclure le fichier.h indiqué par son nom entre ‘< >’, ce
fichier est une bibliothèque contenant toutes les définitions qui seront utilisées par la suite dans le
programme. Si ce fichier est non disponible, une erreur sera générée et la compilation est stoppée.
Cette directive indique des équivalences. iden est le nom de l’équivalence déclarée dans
statement, avec (a,b,…) des variables utilisées dans cette équivalence.
#undef iden
21
Chapitre 2 Programmation en C et application
Directives pragma :
#pragma CLOCK_FREQ fréquence en Hz
Cette directive indique au pré-compilateur la valeur de la fréquence (en Hz) utilisée par notre PIC.
Cette directive permet à l’utilisateur de se placer dans la mémoire à l’adresse désignée par addr et
de mettre les constantes d1, d2, … qui sont sur 8-bits.
Dans ce cas cette directive permet de configurer le µC à travers le registre configuration word, tel
que l’oscillateur, le WDT, LVP…
2.2.Les données :
En général, les données sous SourceBoost sont de type tel qu’il est indiqué dans le tableau suivant :
Types Taille
bit, bool 1-bit
char 8-bits
Int, unsigned int, signed int 16-bits
short, unsigned short, signed short 16-bits
long, unsigned long, signed long 32-bits
Tableau 2.3.2 : Type de données
Et en plus de ces données il y ales constantes et les variables :
Constantes :
Variables :
Les variables peuvent être déclarées et utilisées comme dans tout compilateur de langage C.
Les variables peuvent être forcées de se placer dans une certaine adresse. La syntaxe est la suivante :
char var@<addr>;
Où <addr> est une adresse en hexadécimal ou en décimal. Cette technique est utilisée pour
accéder à un registre spécifié depuis le programme.
22
Chapitre 2 Programmation en C et application
Les variables bit peuvent aussi avoir une adresse fixe. Cette adresse peut inclure la position du bit et
peut se faire suivant deux formes :
char var;
var.2 = 1; //mettre à ‘1’ le bit 2 de la variable ‘var’
Il existe un type de variable appelé volatile qui est utilisé pour déclarer des variables bit qui :
a) peuvent changer en dehors du programme, par exemple : l’assigner à une patte d’un port.
b) reçoivent des valeurs immédiates.
Exemple :
Opérateurs arithmétiques :
‘+’ : addition, ‘-‘ : soustraction, ‘*’: multiplication, ‘/’ : division, ‘%’ : donne le reste de la division de
deux opérandes, ‘++’ : incrémentation, ‘--’ : décrémentation.
Exemples :
Opérateurs d’affectation :
Ces opérateurs permettent d’affecter une valeur à une variable avec possibilité d’effectuer une
opération sur cette variable, ces opérateurs sont :
‘=’ : opérateur d’affectation, la valeur ou l’expression à droite de cet opérateur est affectée à
la variable qui est à gauche de cet opérateur.
23
Chapitre 2 Programmation en C et application
‘/=’ : opérateur division et affectation, la variable à gauche de cet opérateur sera divisée par
celle d’à droite, puis le résultat sera affecté à la variable d’à gauche.
‘%=’ : opérateur reste de la division et affectation, le reste de la division de la variable qui est
à gauche de cet opérateur par celle qui est à droite sera affecté à la variable qui est à gauche.
‘&=’ : opérateur ET bit à bit et affectation. Cet opérateur effectue le ET logique (bit à bit)
entre la variable à sa gauche et celle à sa droite, ensuite il affecte le résultat à la variable à
gauche.
‘|=’ : opérateur OU bit à bit et affectation. Cet opérateur effectue le OU logique (bit à bit)
entre la variable à sa gauche et celle à sa droite, ensuite il affecte le résultat à la variable à
gauche.
‘^=’ : opérateur XOR et affectation. Cet opérateur effectue le XOR logique (bit à bit) entre la
variable à sa gauche et celle à sa droite, ensuite il affecte le résultat à la variable à gauche.
‘<<=’ : opérateur de décalage à gauche et affectation. Les bits de la variable à gauche vont
être décalés à gauche, le nombre de cases de décalage est indiqué par la variable à droite.
24
Chapitre 2 Programmation en C et application
‘>>=’: opérateur de décalage à droite et affectation. Les bits de la variable à gauche vont être
décalés à droite, le nombre de cases de décalage est indiqué par la variable à droite.
Opérateurs de comparaison :
== Egalité
!= Non égalité
<= Inférieur ou égale
< Inférieur
>= Supérieur ou égale
> Supérieur
Opérateurs de condition :
Ces opérateurs permettent d’exécuter une partie du programme sous certaines conditions.
if (condition)
else
case a :
case b :
25
Chapitre 2 Programmation en C et application
Cette permet de contrôler le nombre de fois à exécuter un bloc d’instructions. Dans la syntaxe de
cette boucle on trouve : la valeur initiale du compteur, ça valeur finale et la valeur avec laquelle il
doit être incrémenté (ou décrémenté) chaque fois que le bloc d’instructions est exécuté.
Exemple :
portd = portd++;
Supposons que le port d a 0 comme valeur initiale, donc en sortant de cette boucle le port d aura la
valeur 10 puisque il sera incrémenté en fonction de i, de 0 à 10.
La boucle ‘while’ :
La boucle ‘while’ ou bien ‘tant que’ en français, permet l’exécution d’une suite d’instructions
plusieurs fois tant que une condition soit vraie. Si cette condition à un moment donné ne soit pas
vérifiée (fausse), l’exécution de cette boucle va être stoppée.
Exemple:
While (x>5)
portb = portb++;
--x ;
Supposons que x a une valeur initiale de 8 et le port b une valeur 0. Tant que la valeur de x est
supérieure à 5, le port b est incrémenté. Quand la valeur de x soit égale à 5 cette boucle ne sera plus
exécutée.
Cette boucle permet l’exécution d’une suite d’instructions avant de vérifiée la condition, donc cette
boucle est exécutée au moins une fois même si la condition n’est pas vérifiée. Si la condition n’est
pas vérifiée l’exécution est stoppée, sinon elle continue.
Exemple:
do
portb = portb++;
--x ;
26
Chapitre 2 Programmation en C et application
} while (x>5) ;
Si la valeur initiale de x est inférieure à 5, le port b sera incrémenté une seule fois puis l’exécution de
la boucle est stoppée. Sinon il sera incrémenté jusqu'à ce que la valeur de x soit inférieure à 5.
clear_bit (var,num) : Cette fonction permet de mettre à zéro le bit ‘num’ de la variable ‘var’.
set_bit (var,num) : Cette fonction permet de mettre à un le bit ‘num’ de la variable ‘var’.
test_bit (var,num) : test si le bit ‘num’ de la variable ‘var’ est à un.
MAKESHORT (dst,lobyte,hibyte) : cette fonction permet créer une valeur sur 16 bit qui sera
stockée dans ‘dst’ à partir de deux valeurs de 8 bit, ‘lobyte’ pour l’octet du poids faible et
‘hibyte’ pour l’octet du poids fort. Notons que ‘dst’ doit être une variable sur 16 bit.
LOBYTE (dst,src) : permet d’avoir l’octet du poids faible à partir de ‘src’ et de le stocker dans
‘dst’.
HIBYTE (dst,src) : permet d’avoir l’octet du poids fort à partir de ‘src’ et de le stocker dans
‘dst’.
void nop (void) : c’est une fonction inline c-à-d que ça syntaxe dans le programme est la
suivante : nop(). Cette fonction permet de générer l’instruction ‘nop’ (no operation).
void sleep (void) : c’est une fonction inline c-à-d que ça syntaxe dans le programme est la
suivante : sleep(). Cette fonction permet de générer l’instruction ‘sleep’ qui mettra en
veille le µC.
void reset (void) : c’est une fonction inline c-à-d que ça syntaxe dans le programme est la
suivante : reset(). Cette fonction permet de générer un reset.
Le programme doit commencer par une directive de compilation qui indique au compilateur
quel sont les fichiers à inclure, ensuite il faut configurer le µC à travers le registre
configuration word, et après ça il faut indiquer au compilateur la fréquence du µC.
La deuxième partie du programme consiste à définir les interruptions et le programme de
chacune.
La dernière partie est la partie du programme principale, elle est subdivisée en deux parties :
dans la première partie le programmateur doit configurer et initialiser chaque port,
configurer les timers et d’autres ressources internes et aussi configurer les interruptions. La
deuxième partie est dédiée au programme qui va définir la tâche à effectuer par le µC.
4. Exemple d’application :
Après avoir vu comment programmer un µC PIC, nous allons présenter, dans cette partie, un
exemple d’application où le PIC est programmé en C sous SourceBoost.
27
Chapitre 2 Programmation en C et application
L’exemple que nous allons présenter est une application très simple à réaliser, c’est un compteur
qui peut aller de 0 à 99 (8 bits) avec un bouton de remise à zéro. Le circuit de cet exemple a été
réalisé et simulé sous le logiciel ISIS, la figure suivante illustre ce montage :
15pF
(1)
U1
13 33
OSC1/CLKIN RB0/INT
14 34
OSC2/CLKOUT RB1
1 35
MCLR/Vpp/THV RB2
36
RB3/PGM
15pF 2 37
RA0/AN0 RB4
3 38
4
RA1/AN1 RB5
39
R1
RA2/AN2/VREF- RB6/PGC
5 40
RA3/AN3/VREF+ RB7/PGD 6M8
6
RA4/T0CKI
7 15
RA5/AN4/SS RC0/T1OSO/T1CKI
16
RC1/T1OSI/CCP2
8 17
RE0/AN5/RD RC2/CCP1
9 18
RE1/AN6/WR RC3/SCK/SCL
10 23
RE2/AN7/CS RC4/SDI/SDA
24
RC5/SDO
25
RC6/TX/CK
D1 D2 RC7/RX/DT
26
comptage Mise à zéro
19
RD0/PSP0
20
RD1/PSP1
21
RD2/PSP2
22
RD3/PSP3
27
RD4/PSP4
28
RD5/PSP5
29
RD6/PSP6
30
RD7/PSP7
PIC16F877
Comme nous pouvons le voir, ce circuit est constitué d’un µC PIC 16F877, deux afficheurs 7 segments
avec circuits de décodage BCD intégrés l’un est connecté au port d et l’autre au port c, deux LED :
une rouge pour indiquer le comptage et une jaune pour indiquer la remise à zéro et un bouton
poussoir pour la remise à zéro. Un autre circuit connecté entre OSC1 et OSC2 qui est composé d’un
quartz de 4MHz en parallèle avec deux condensateurs de 15pF qui permet de fixer l’horloge à 4MHz.
Pour que ce circuit fonctionne il faut que le µC soit programmé correctement. Le programme qui
permet d’effectuer cette tâche est le suivant :
#include <system.h>
#include <pic16F877.h>
trisb = 0xFF;
trisc = 0x00;
28
Chapitre 2 Programmation en C et application
portc = 0x00;
portd = 0x00;
intcon = 0x90;
sleep();
for (i=0;i=99;i++)
clear_bit(porte,1);
set_bit(porte,0);
portd=portd++;
delay_ms(20);
portd=0;
portc=portc++;
break;
portd=0;
portc=0;
if(INTF==1)
portd=0;
portc=0;
29
Chapitre 2 Programmation en C et application
set_bit (porte,1);
4.1.Analyse de la structure :
#include <system.h>
Cette directive indique au pré-compilateur d’inclure le fichier system.h. Celui-ci contient à son
tour un fichier contenant toutes les informations sur les différents PIC et de plus il permet d’inclure
des fonctions qui seront utilisées dans le programme.
#include <pic16F877.h>
Cette directive indique au pré-compilateur d’inclure le fichier pic16F877.h. Celui-ci contient des
informations sur le PIC 16F877 telles que les associations nom de registre/adresse mémoire.
Une autre directive de pré-compilation, qui permet de définir les bits de configuration du PIC. Ces
bits de configuration permettent de configurer un certain nombre de paramètres de fonctionnement
du PIC:
• WDT_OFF: désactive le Watch Dog Timer.
• XT_OSC : Configure l’oscillateur en mode XT.
Pour l’instant on désactive tout (OFF), à part bien sûr l’oscillateur qu’on configure en mode « XT »
puisque l’oscillateur utilisé est en quartz à 4MHz.
A nouveau une directive de pré-compilation. On indique ici quelle est la fréquence du quartz utilisé.
C’est à partir de cette valeur que les temporisations sont générées par la fonction « delay ».
La fonction main est obligatoire en langage C, elle indique le début du programme principal. C’est
dans cette zone entre accolades ‘{ }’ qu’on a:
Configurer les différents ports utilisés dans cette application :
trisb = 0xFF; configurer toutes les pins du port b en entrées.
30
Chapitre 2 Programmation en C et application
intcon = 0x90; INTCON est un registre qui permet de contrôler les interruptions. L’équivalent de
90h en binaire est 10010000b, affecter cette valeur au registre INTCON permet de mettre à ‘1’ le 8 ème
bit qui correspond au bit de validation globale des interruptions et le 5ème bit qui correspond au bit
de validation de l’interruption sur changement de RB0, et de mettre à ‘0’ tous les autres bits pour
désactiver toute autre interruption.
Après que le µC exécute les étapes précédentes, il va exécuter la fonction ‘sleep’ qui va le mettre en
veille. L’intérêt de cette mise en veille dans notre exemple est de ne pas commencer le comptage
qu’après avoir reçu un changement d’état sur RB0 (en appuyant sur le bouton poussoir), donc il va
exécuter la routine d’interruption pour ensuite continuer l’exécution du programme.
Dès que le µC sort de la routine d’interruption, il retourne au programme principal pour exécuter la
boucle ‘for’.
Initialement, au début du programme, on déclarer un entier ‘i’ qui va servir de compteur pour la
boucle et qui va être incrémenté chaque fois que la boucle est exécutée de ‘0’ à ‘99’:
for (i=0;i=99;i++)
clear_bit(porte,1);qui va mettre à ‘0’ la pin RE1 pour éteindre la LED jaune qui est connectée à
cette pin, ce qui va signaler la fin de la mise à ‘0’ du compteur et début du comptage.
set_bit(porte,0);qui mettra à ‘1’ la pin RE0 où une LED rouge est connectée. Cette mise à ‘1’
allume la LED pour signaler le comptage et elle reste allumée tant qu’une remise à zéro ne s’est
produite.
Ensuite on rencontre un bloc d’instructions précédé par un operateur de condition (un test) :
if ((portd==9) && (portc!=9))
Si la valeur du port d est égale à 9 et celle du port c est différente de 9, le bloc d’instructions
va être exécuté, dans ce bloc on va:
i. Mettre à ‘0’ le port d : portd=0;, cette remise à zéro est nécessaire puisque le port d ne
doit pas dépasser 9.
31
Chapitre 2 Programmation en C et application
ii. Incrémenter la valeur du port c : portc=portc++; ,puisque il n’a pas encore atteint la
valeur ‘9’. Cette incrémentation nous permet de passer, par exemple, des dizaines aux
vingtaines.
Sinon, c-à-d que les conditions ne sont pas vérifiées, le bloc ne va pas être exécuté et le µC
passe directement à l’instruction qui suit le bloc.
Si ces conditions ne sont pas vérifiées, donc le compteur n’a pas encore atteint la valeur ‘99’
et il faut l’incrémenté, pour cela le µC va ignorer l’instruction qui suit ce test pour ensuite se
retrouver à la fin de la boucle ‘for’ ce qui lui permettra de reboucler tout en incrémentant le
‘i’ et de ré-exécuter cette boucle.
Sinon, le µC trouve que les conditions son vérifiées (le compteur à atteint ‘99’), donc il va
exécuter l’instruction qui suit et c’est un ‘break’, cette instruction est utilisée généralement à
la fin d’une boucle ‘for’ et exécutée après vérification d’une certaine condition, l’exécution
de cette instruction permet au µC de sortir de la boucle. Dans ce cas notre condition est
vérifiée donc le µC sort de la boucle pour continuer l’exécution du reste du programme.
Si, durant l’exécution du programme ou à la fin de l’exécution, le µC a reçu un changement d’état sur
RB0 (en appuyant sur le bouton poussoir), ceci va engendrer une interruption. Le sous programme
qui traite cette interruption ce mis entre les accolades de la fonction ‘interrupt’ comme suit :
interrupt est la fonction qui traite les interruptions, Le void signifie que cette fonction ne
retourne rien. Dans ce sous programme on a :
Affecter un ‘0’ au port d et au port c pour permettre au µC de mettre à zéro chaque pins de
ces ports, ce qui fait que le compteur sera mit à zéro.
Mis à ‘1’ la patte RE1, où une LED jaune est connectée, par set_bit(porte,1);. Dès que
cette patte est mise à ‘1’, la LED s’allume indiquant la remise à zéro.
clear_bit(intcon,INTF);permet de mettre à zéro le bit INTF du registre INTCON, ce bit
qui signale un changement sur RB0 et de déclenche une interruption en se mettant à ‘1’,
d’où la nécessité de le remettre à ‘0’ pour signaler la fin de cette interruption.
32
Chapitre 2 Programmation en C et application
Conclusion :
A travers les notions et l’application présentée dans ce chapitre, nous avons fait un pas dans la
programmation des PIC en C.
33
Conclusion Générale
L’élaboration de ce modeste travail nous a permis de comprendre un peu le fonctionnement
du microcontrôleur PIC 16F877 à travers une étude théorique de ces différentes ressources internes,
ensuite de s’initier à leur programmation en langage C, pour cela nous avons utilisé le compilateur
SourceBoost et comme nous l’avons vu il est d’une grande simplicité. Cela nous a permis aussi
d’élaborer une application pour mettre en œuvre toutes les notions théoriques.
A la fin nous espérons avoir apporté une contribution au domaine des microcontrôleurs PIC
et à leur programmation en langage C.
33
Bibliographie