Programmation Des PIC en C Part2

download Programmation Des PIC en C Part2

of 34

Transcript of Programmation Des PIC en C Part2

  • - 1 -

    Programmation des PIC en C

    Microcontrleur facile pour lectronicien amateur

    PARTIE 2

    Noxyben 2008

    www.noxyben.fr

  • - 2 -

    Introduction ................................................................................................................................ 3

    Le schma de base...................................................................................................................... 4

    Principe de fonctionnement des ports I/O .................................................................................. 7

    Utilisation des ports dentre/sortie (I/O)................................................................................... 8

    Utilisation dun PORT en sortie : un chenillard 8 leds .......................................................... 8

    Le matriel : ....................................................................................................................... 8

    Le programme : ................................................................................................................ 10

    Analyse du programme : .................................................................................................. 12

    Compilation du programme et injection dans le PIC : ..................................................... 16

    Tests ................................................................................................................................. 17

    Conclusion :...................................................................................................................... 17

    Utilisation dun PORT en entre : un chenillard 8 leds contrl par 2 boutons poussoirs. . 18

    Le matriel : ..................................................................................................................... 18

    Le programme : ................................................................................................................ 19

    Analyse du programme : .................................................................................................. 22

    Compilation du programme et injection dans le PIC : ..................................................... 23

    Tests ................................................................................................................................. 24

    Conclusion :...................................................................................................................... 24

    Le PORTB et les interruptions ............................................................................................. 25

    Principe de fonctionnement :............................................................................................ 25

    Le matriel : ..................................................................................................................... 26

    Le programme : ................................................................................................................ 27

    Analyse du programme : .................................................................................................. 29

    Tests ................................................................................................................................. 34

    Conclusion :...................................................................................................................... 34

  • - 3 -

    Introduction Aprs avoir vu dans la premire partie comment est structur le PIC, on va enchaner directement sur des montages concrets : rien de mieux pour apprendre et mmoriser que de faire soi-mme un montage en vrai . Je vous invite chaleureusement faire un tour chez votre marchand de composants lectroniques et faire chauffer votre fer souder. Vous allez avoir besoin dun PIC16F877, un programmateur, une platine dessai du genre pastilles pr-perces au pas de 2,54 mm, et quelques composants qui tranent certainement dans vos fonds de tiroirs : Led, rgulateur 7805, condensateurs, support 40 broches Pour la partie logicielle il vous faudra tlcharger la version de dmonstration de SourceBoost, qui comprend le compilateur BoostC que nous allons employer, et ventuellement un logiciel de transfert comme Icprog pour piloter votre programmateur de PIC. Si vous avez achet un programmateur en kit comme le Velleman K8076, le logiciel PICPROG est compris. Pensez tlcharger les mises jour.

  • - 4

    -

    Le schma de base

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    40

    39

    38

    37

    36

    35

    34

    33

    32

    31

    30

    29

    28

    27

    26

    25

    24

    23

    22

    21

    P

    I

    C

    1

    6

    F

    8

    7

    7

    7805

    C1 C2

    Q1

    C3 C4

    C5

    C6

    IC2

    IC1

    R1

    Led1

    ICSP

    9V =D1

  • - 5 -

    Le schma ci-dessus est la base sur laquelle on va pouvoir construire des applications utiles. Il ne fait rien dautre que de permettre au PIC de fonctionner, cest en quelque sorte le minimum vital . Bien entendu, dautres variantes sont possibles, mais plutt que den dresser la liste exhaustive, je vous propose de raliser cette version et de remettre plus tard ltude des diffrents circuits doscillateur, de reset Lalimentation : Pour alimenter le circuit, une source continue denviron 9V fera parfaitement laffaire (une pile 9V par exemple). La rgulation et ladaptation un niveau de 5V requis par le PIC incombent au rgulateur 7805. Remarque : pour que celui-ci fonctionne correctement, la tension dalimentation doit tre suprieure dau moins 2 ou 3 volts la tension rgule, donc 5 + 2 = 7 Volts. La diode D1 protge le circuit contre les inversions accidentelles de polarit (diode type 1N4001 ou 1N4007 par exemple). Le condensateur C3 sert de rservoir au rgulateur. La rgle habituelle est de prendre 1000F / Ampre. Dans notre cas, un condensateur lectrochimique de 470 avec une tension dau moins 16V convient parfaitement. Le condensateur C4 nous permet de dcoupler le rgulateur du reste du circuit : il absorbe les variations de tension parasite qui pourraient remonter vers le rgulateur. 10 ou 100 nF devraient convenir. Le couple R1 Led1 sert de tmoin de mise sous tension, et accessoirement dcharge le condensateur C3 lorsque lalimentation est coupe. Avec une tension dalimentation de 9V, on prendra pour R1 une valeur de 390 1/4W Les condensateurs C5 et C6 quant eux sont des condensateurs de dcouplage du PIC. monter au plus prs du 16F877, ils empchent que dventuels parasites collects par les lignes dalimentation ne pntrent dans le circuit intgr. Quelques pF ou nF du genre condensateur tantale goutte feront laffaire. Surtout pas de gros condensateur lectrochimique de plusieurs F qui aurait un effet nfaste sur le temps de monte de lalimentation et pourrait ainsi perturber le PIC au moment du dmarrage. Loscillateur : Il est constitu de Q1, un quartz parallle dont la frquence doscillation nominale peut aller jusqu 20MHz, et des condensateurs C1 et C2 pour lequel on prendra une valeur de 20pF, conformment aux indications de la documentation de Microchip.

  • - 6 -

    Le connecteur ICSP : Bien que ntant pas indispensable, on va quiper notre platine de ce connecteur In Circuit Serial Programming , qui nous permettra de programmer le PIC sans le retirer de son support. A vrai dire, le brochage nest pas vraiment normalis. Je vous propose donc la version suivante, que vous pourrez adapter votre guise. Le seul impratif est que les bonnes lignes du programmateur aboutissent sur les bonnes pattes du PIC

    patte 1 - 6 : Vpp (tension de programmation) patte 2 - 7 : VDD (tension dalimentation 5V) patte 3 - 8 : PGD (Program Data = ligne de transfert des donnes) patte 4 9 : Vss (tension de masse = 0V) patte 5 - 10 : PGC (Program Clock = ligne dhorloge de programmation)

    12345

    678910

    En fonctionnement normal, la pin 1 est ponte sur la pin 6, la pin 2 sur la 7, la 3 sur la 8, la 4 sur la 9 et la 5 sur la 10. Pour programmer le PIC on dconnecte lalimentation du circuit, on te tous les ponts du connecteur ICSP et on branche la place le cordon ICSP du programmateur, en veillant ce que les signaux correspondent bien. Si ce nest pas le cas, il vous faudra confectionner un cordon ad hoc en croisant les bonnes lignes. Le circuit de RESET : Rien de plus simple pour linstant : la ligne de reset

    MCLR (la pin 1 du PIC) est simplement relie la tension dalimentation.

    Ainsi, pour redmarrer le PIC, on coupe lalimentation et on ralimente.

  • - 7 -

    Principe de fonctionnement des ports I/O

    Les ports dentre / sortie numriques peuvent tre considrs comme les priphriques les plus simples du microcontrleur. Pour le PIC, on contrle leur fonctionnement laide de registres spciaux (deux registres par port). Par exemple, pour le port A, on a le registre PORTA et le registre TRISA. Les registres TRISx contrlent le mode de fonctionnement des entres / sorties : selon la valeur de chaque bit, 0 ou 1, la pin correspondante du port fonctionnera soit en sortie, soit en entre. Les registres PORTx contiennent les donnes, lues, ou crire sur le port. Certains ports possdent en plus des fonctionnalits spcifiques : le PORTB est quip de rsistances de tirage (pull-up) internes qui peuvent tre actives ou non. La pin RB0 du PORTB sert dentre dinterruption externe, et les pins RB4 RB7 peuvent gnrer une interruption lorsquun changement dtat est dtect leurs bornes. Toutes ces particularits sont bien entendu dcrites dans les documentations Microchip spcifiques chaque composant.

  • - 8 -

    Utilisation des ports dentre/sortie (I/O)

    Utilisation dun PORT en sortie : un chenillard 8 leds

    Le matriel :

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    40

    39

    38

    37

    36

    35

    34

    33

    32

    31

    30

    29

    28

    27

    26

    25

    24

    23

    22

    21

    PIC 16F877

    Rd1

    Rd2

    Rd3

    Rd4

    Rd5

    Rd6

    Rd8

    Rd8

    R9 R8 R7 R6 R5 R4 R3 R2

    VCC

    On va rajouter les quelques composants du schma ci-dessus notre montage de base. Le but est de pouvoir commander 8 leds travers les 8 lignes du PORTD. On pourrait raccorder les leds directement aux pins du PIC travers des rsistances appropries, (a marche aussi) mais au cas o lide vous viendrait dallumer les 8 leds en mme temps, le courant dbit par le PORTD pourrait dpasser la valeur limite. En effet, un coup dil la rubrique caractristiques lectriques du datasheet nous informe que le courant maximal pouvant tre dbit par un PORT est de 200 mA. Avec des rsistances lgrement sous-dimensionnes et 8 leds allumes on pourrait sen approcher dangereusement. Bon, cest vrai, jexagre un peu, mme avec 8 x 20 mA on nest encore qu 160mA de consommation sur le port. Mais autant adopter de bons rflexes ds le dpart. On choisit donc de passer par des transistors. On pourra prendre des transistors petit signaux standard. Si vous trouvez dans vos tiroirs des BC537 ou 2N2222 ou quoi que ce soit dquivalent, a conviendra parfaitement. Pour les rsistances R2 R9, si on considre que le point de fonctionnement des leds est environ 1,8V / 10 mA, et que VCC = 5 V : VRx = 5-1,8 = 3,2V ; donc R = VRx / I = 3,2 / 0.01 = 320.

  • - 9 -

    La valeur normalise la plus proche tant 330, on prendra donc pour les rsistances R2 R9 des 330 Ohms de Watt. Pour les rsistances Rd1 Rd8, afin dassurer une bonne saturation des transistors, on prendra des rsistances de 4,7 kOhms de Watt.

  • - 10 -

    Le programme :

    On rentre enfin dans le vif du sujet. Afin de piloter notre montage avec un joli effet K2000 , je vous propose le programme ci-dessous : #include //Cible PIC16F877, bits de configuration #pragma DATA _CONFIG, _PWRTE_OFF & _BODEN_OFF & _WDT_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF & _HS_OSC & _CP_OFF //Configuration de la frquence d'horloge, ici 20Mhz #pragma CLOCK_FREQ 20000000 void main( void ) { //Initialisation port A porta = 0x00; //Initialisation port B portb = 0x00; //Initialisation port C portc = 0x00; //Initialisation port D portd = 0x00; //Initialisation port E porte = 0x00; //Configuration port A trisa = 0x00; //Configuration port B trisb = 0x00; //Configuration port C trisc = 0x00; //Configuration port D trisd = 0x00; //Configuration port E trise = 0x00; //Configuration A/D pins adcon1 = 0x06; //dsactivation du mcanisme de gestion des interruptions clear_bit( intcon, GIE );

  • - 11 -

    //Validation des rsistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU ); //Boucle sans fin while( 1 ) { portd = 0b00000001; delay_ms(100); portd = 0b00000011; delay_ms(10); portd = 0b00000010; delay_ms(100); portd = 0b00000110; delay_ms(10); portd = 0b00000100; delay_ms(100); portd = 0b00001100; delay_ms(10); portd = 0b00001000; delay_ms(100); portd = 0b00011000; delay_ms(10); portd = 0b00010000; delay_ms(100); portd = 0b00110000; delay_ms(10); portd = 0b00100000; delay_ms(100); portd = 0b01100000; delay_ms(10); portd = 0b01000000; delay_ms(100); portd = 0b11000000; delay_ms(10); portd = 0b10000000; delay_ms(100); portd = 0b11000000; delay_ms(10); portd = 0b01000000; delay_ms(100); portd = 0b01100000; delay_ms(10); portd = 0b00100000; delay_ms(100); portd = 0b00110000; delay_ms(10); portd = 0b00010000; delay_ms(100); portd = 0b00011000; delay_ms(10); portd = 0b00001000;

  • - 12 -

    delay_ms(100); portd = 0b00001100; delay_ms(10); portd = 0b00000100; delay_ms(100); portd = 0b00000110; delay_ms(10); portd = 0b00000010; delay_ms(100); portd = 0b00000011; delay_ms(10); } }

    Analyse du programme :

    tudions cela un peu plus en dtails : #include Cette directive indique au prcompilateur dinclure le fichier system.h. Celui-ci contient son tour une inclusion pour le fichier spcifique votre PIC (16F877.h), dans lequel sont indiques les associations nom de registre / adresses mmoire. Do limportance de bien indiquer BoostC la cible (ici 16F877) pour laquelle vous dsirez compiler votre programme. #pragma DATA _CONFIG, _PWRTE_OFF & _BODEN_OFF & _WDT_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF & _HS_OSC & _CP_OFF Une autre directive de prcompilation, qui permet de dfinir les bits de configuration du PIC. Pour mmoire, ces bits de configuration permettent de configurer un certain nombre de paramtres de fonctionnement du PIC. Bien heureusement, SourceBoost reprend peu de chose prs les mmes dsignations que Microchip :

    PWRTE_OFF : dsactive le Power-up Timer Enable bit BODEN_OFF : dsactive le Brown-Out reset Enable bit WDT_OFF : dsactive le Watch Dog Timer LVP_OFF : dsactive le Low Voltage Programming CPD_OFF : dsactive la protection de la mmoire de donnes EEPROM ? DEBUG_OFF : dsactive lIn-Circuit Debugger HS_OSC : Configure loscillateur en mode HS (High Speed) CP_OFF : dsactive la protection du code

    Pour linstant on dsactive tout (OFF), part bien sr loscillateur quon configure en mode HS , mode recommand par Microchip pour lemploi dun quartz 20 MHz. Si vous utilisez un quartz 4 MHz, le mode le plus appropri sera XT . La diffrence rside entre HS et XT rside dans le gain de lamplificateur inverseur du circuit doscillateur du PIC. Plus la frquence de travail est leve, plus le gain doit tre

  • - 13 -

    lev. Mais dans la pratique, en mode HS et avec un quartz 4 MHz, a marche aussi. Pour savoir quel mode choisir, regardez dans la documentation Microchip sur la gamme des PIC mid-range , ou mieux sur la documentation du 16F877 dans la section oscillator . #pragma CLOCK_FREQ 20000000 A nouveau une directive de prcompilation. On indique ici quelle est la frquence du quartz utilis. Les temporisations gnres par la fonction delay utilise plus loin dans le programme sont bases sur cette valeur. void main( void ) { } La fonction main est obligatoire en langage C : cest le point dentre du programme. Le void plac avant main indique que la fonction ne retourne aucune valeur, et le void entre parenthses indique quon ne prend pas de valeur en argument. Tout le reste de notre programme viendra se placer entre les accolades ouvrante et fermante. //Initialisation port A porta = 0x00; //Initialisation port B portb = 0x00; //Initialisation port C portc = 0x00; //Initialisation port D portd = 0x00; //Initialisation port E porte = 0x00; Les variables porta, portb, portc, portd et porte sont affectes aux registres correspondant ltat des Entres/Sortie des ports. (respectivement le PORTA, PORTB, PORTC, PORTD, PORTE). Ces variables sont dclares dans le fichier dentte spcifique au PIC 16F877 (fichier avec lextension .h ), lui-mme inclus dans le fichier system.h. Ainsi, vous pouvez accder un registre du PIC simplement en lappelant par son nom, sans se soucier de son adresse. crire une donne dans un de ces registres affectera ds-lors les pins correspondantes du PORT, si celles-ci sont configures en sortie. Ici, on initialise tout 0.

  • - 14 -

    //Configuration port A trisa = 0x00; //Configuration port B trisb = 0x00; //Configuration port C trisc = 0x00; //Configuration port D trisd = 0x00; //Configuration port E trise = 0x00; Suivant le mme principe que pour les registres porta, portb, portc les variables trisa, trisb, trisc, trisd, trise sont affectes aux registres de contrle de direction des ports (respectivement le PORTA, PORTB, PORTC, PORTD, PORTE). On affecte au cinq registres tris la valeur hexadcimale (do le x pour heXa) 00. Un coup dil aux fiches dtailles des registres correspondant nous montre que cette valeur 00 passe toutes les lignes dEntrs/Sortie des ports en mode sortie . Une remarque : Microchip recommande de dinitialiser en premier lieu les registres portx , et de configurer la direction avec les registres trisx ensuite. Pour viter davoir un tat incertain sur les pins au moment du dmarrage. //Configuration A/D pins adcon1 = 0x06; Certaines pins des ports sont susceptibles dtre utilise par le convertisseur Analogique / Numrique. Par dfaut, (voir fiche dtaille du registre adcon1), les pins en question sont configures en mode analogique. La valeur hexadcimale 0x06 les passe en mode numrique.

    //dsactivation du mcanisme de gestion des interruptions clear_bit( intcon, GIE ); Le registre intcon contrle le mcanisme dinterruption. intcon pour INTerrupt CONtrol. GIE, Global Interrupt Enable bit, est un des bits du registre intcon, il active ou dsactive de manire globale toutes les interruptions. La fonction clear_bit() est une fonction implmente par BoostC, permettant de mettre un bit 0. Son pendant est la fonction set_bit() qui permet, elle de mettre un bit 1. La syntaxe ci-dessus signifie donc : mettre 0 le bit GIE du registre intcon .

  • - 15 -

    //Validation des rsistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU ); Le registre option_reg contrle certaines options du PIC, parmi lesquelles figure lactivation ou non des rsistances de pull-up du PORTB. Le bit correspondant cette option est NOT_RBPU. Celui-ci fonctionne en logique ngative (do le NOT devant RBPU). La syntaxe ci-dessus signifie donc mettre 0 le bit NOT_RBPU du registre option_reg . Or, tant donn que le bit NOT_RBPU fonctionne en logique ngative, le mettre 0 signifie ACTIVER les rsistances de pull-up du PORTB ! Pour linstant on ne se sert pas de ces rsistances, donc vous pouvez, si vous prfrez, mettre ce bit 1 pour les dsactiver. //Boucle sans fin while( 1 ) { } Comme lindique le commentaire, il sagit l dune boucle sans fin. While est une instruction de contrle de boucle du langage C. La traduction franaise donnerait : tant que 1 . Or, 1 na pas de raison de changer dtat, donc une fois lance, on ne sort pas de cette boucle. Tout le code entre les accolades ouvrante et fermante se rptera ds lors indfiniment. portd = 0b00000001; La variable portd est affecte au registre correspondant ltat des Entres/Sortie du PORTD. Ici, on crit la donne binaire (do le b de 0bxxxxxxxx) 0b00000001, ce qui a pour effet de passer la pin RD0 ltat 1, alors que les pins RD1 RD7 restent ltat 0. delay_ms(100); La fonction delay_ms() est une fonction implmente par BoostC, permettant dintroduire une temporisation. Ici, delay_ms(100) gnre une temporisation de 100 millisecondes. Cette temporisation est calcule en fonction de la valeur de la frquence dhorloge quon a indique plus en amont par la directive PRAGMA CLOCK_FREQ.

  • - 16 -

    portd = 0b00000011;

    delay_ms(10); On allume une deuxime pin du PORTD, et on attend ensuite 10 millisecondes, avant de passer la suite. Le principe utilis ici est le suivant : on allume une led, on attend 100 ms, on allume une deuxime led, on attend 10 ms, on teint la premire led, on attend 100 ms, etc. Lallumage simultan de deux les nest l que pour diminuer leffet de saccade lors du passage dune led lautre. Vous laurez remarqu : cette manire de faire est un peu rustique , on aurait pu remplacer la rptition des instructions par des boucles bien construites. Mais dun point de vue didactique a me semble plus simple comprendre, et comme on est loin davoir satur la mmoire du PIC

    Compilation du programme et injection dans le PIC :

    Aprs ltude thorique, il ne reste plus qu compiler notre programme et linjecter dans le PIC. Pour cela, on va suivre les tapes suivantes : COMPILATION :

    Lancez lIDE de SourceBoost. Assurer vous que le compilateur utilis est bien BoostC (dans le menu

    paramtres). Crez un nouveau projet (menu Projet : Nouveau). Dans ce projet, crez un nouveau fichier (menu Fichier : Nouveau) dans

    lequel vous allez copier le code ci-dessus. Slectionnez la cible , autrement dit le composant pour lequel vous voulez

    compiler le projet : PIC 16F877 (menu Paramtres : Cible) Compilez le programme (menu Construction : Construire) Si tout sest bien pass, le compilateur indique success et a gnr dans

    le rpertoire de votre projet plusieurs fichiers. Lun dentre eux a une extension en .hex.

    TRANSFERT (avec un programmateur Velleman K8076) :

    Configurez le programmateur pour le 16F877 (il faut que les ponts aboutissent sur les bonnes pattes du support ZIF, si vous utilisez ce dernier)

    A ce stade, soit vous placez le pic sur le support ZIF du programmateur, soit vous raccordez le cordon ICSP sur la platine sur laquelle est mont le PIC.

    Raccordez le programmateur au PC. Alimentez le programmateur. Lancez le programme PICPROG (livr avec le programmateur Velleman). Slectionnez la cible, ici un PIC 16F877 (si vous ne le trouvez pas dans la

    liste, vrifiez sur le site de Velleman sil ny a pas de mise jour). Ouvrez le fichier .hex gnr par le compilateur pour votre projet Cliquez sur le bouton write all data , et attendez que le transfert seffectue.

  • - 17 -

    Si ce stade tout est ok, dconnectez le programmateur, placez le PIC sur son circuit ou remettez les ponts la place du connecteur ICSP de votre platine prototype.

    Tests

    Vous pouvez alimenter votre circuit et He is alive ! Un magnifique effet de balayage anime vos 8 led. Elle est pas belle la vie ?

    Conclusion :

    Ca y est, vous avez cr une application base de microcontrleur ! Il est vrai que pour linstant, linteraction de notre montage avec le monde rel est trs limite. Il peut nanmoins servir crer de jolis effets lumineux. On pourrait galement envisager de sen servir comme tlcommande rustique ( une seule fonction ?) en montant une led infrarouge et en programmant la squence dallumages/extinctions adquate.

  • - 18 -

    Utilisation dun PORT en entre : un chenillard 8 leds contrl par 2 boutons poussoirs.

    tape suivante : on va utiliser des pins dun autre port en entre, pour contrler le fonctionnement de notre application.

    Le matriel :

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    40

    39

    38

    37

    36

    35

    34

    33

    32

    31

    30

    29

    28

    27

    26

    25

    24

    23

    22

    21

    PIC 16F877

    RB1

    RB0/INT

    switchon switchoff

    On reprend le schma prcdent, et on y ajoute deux boutons poussoirs directement raccords aux pins RB0 et RB1, autrement dit les deux bits de poids faible du PORTB. Vous allez me dire, Quand on appuie sur les boutons poussoirs, ok, les pins sont la masse, mais quand on relche le potentiel est flottant, non ? justement non, puisque quon va utiliser les rsistances de pull-up interne du PIC. Une remarque importante : il ny a que le PORTB qui soit quip de telles rsistances. Si vous utilisez un autre port, il faudra cbler vous-mme ces rsistances de tirage entre VCC et la pin correspondante.

  • - 19 -

    Le programme :

    La structure gnrale est identique lexemple prcdent, avec tout de mme quelques modifications : #include //Cible PIC16F877, bits de configuration #pragma DATA _CONFIG, _PWRTE_OFF & _BODEN_OFF & _WDT_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF & _XT_OSC & _CP_OFF //Configuration de la frquence d'horloge, ici 4Mhz #pragma CLOCK_FREQ 4000000 void main( void ) { //Initialisation port A porta = 0x00; //Initialisation port B portb = 0x00; //Initialisation port C portc = 0x00; //Initialisation port D portd = 0x00; //Initialisation port E porte = 0x00; //Configuration port A trisa = 0x00; //Configuration port B trisb = 0x03; // On configure les deux pins de poids faible en entre //Configuration port C trisc = 0x00; //Configuration port D trisd = 0x00; //Configuration port E trise = 0x00; //Configuration A/D pins adcon1 = 0x06; //dsactivation du mcanisme de gestion des interruptions clear_bit( intcon, GIE );

  • - 20 -

    //Validation des rsistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU ); volatile bit [email protected]; // 0 pour RB0 volatile bit [email protected]; // 1 pour RB1 bool go =0; // variable de contrle //Boucle sans fin while( 1 ) { if (switchon == 0) { go = 1; } if (switchoff == 0) { go = 0; portd = 0b00000000; } if ( go ) { portd = 0b00000001; delay_ms(100); portd = 0b00000011; delay_ms(10); portd = 0b00000010; delay_ms(100); portd = 0b00000110; delay_ms(10); portd = 0b00000100; delay_ms(100); portd = 0b00001100; delay_ms(10); portd = 0b00001000; delay_ms(100); portd = 0b00011000; delay_ms(10); portd = 0b00010000; delay_ms(100); portd = 0b00110000; delay_ms(10); portd = 0b00100000; delay_ms(100); portd = 0b01100000;

  • - 21 -

    delay_ms(10); portd = 0b01000000; delay_ms(100); portd = 0b11000000; delay_ms(10); portd = 0b10000000; delay_ms(100); portd = 0b11000000; delay_ms(10); portd = 0b01000000; delay_ms(100); portd = 0b01100000; delay_ms(10); portd = 0b00100000; delay_ms(100); portd = 0b00110000; delay_ms(10); portd = 0b00010000; delay_ms(100); portd = 0b00011000; delay_ms(10); portd = 0b00001000; delay_ms(100); portd = 0b00001100; delay_ms(10); portd = 0b00000100; delay_ms(100); portd = 0b00000110; delay_ms(10); portd = 0b00000010; delay_ms(100); portd = 0b00000011; delay_ms(10); } } }

  • - 22 -

    Analyse du programme :

    Le programme ressemble, quelques dtails prs, celui de lexemple prcdent. /Cible PIC16F877, bits de configuration #pragma DATA _CONFIG, _PWRTE_OFF & _BODEN_OFF & _WDT_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF & _XT_OSC & _CP_OFF //Configuration de la frquence d'horloge, ici 4Mhz #pragma CLOCK_FREQ 4000000 Comme vous pouvez le constater, on a chang de quartz. De 20 MHz on est pass 4 MHz. Pourquoi ? Pas de raison particulire, cest uniquement dans un but didactique. Si vous voulez conserver votre quartz 20 MHz, conservez les valeurs de lexemple prcdent pour cette section. //Configuration port B trisb = 0x03; // On configure les deux pins de poids faible en entre Les deux boutons poussoirs ( switchon et switchoff sur le schma) sont cbls sur les pins du port B : RB0 et RB1. Dans lexemple prcdent, ces pins taient configures en sortie. Il nous faut maintenant les configurer en entre. Pour cela, on met 1 les bits correspondants du registre trisb, qui contrle la direction du PORTB. Ce qui nous donne, en binaire : 0b00000011, et donc, en hexadcimal : 0x03.

    volatile bit [email protected]; // .0 pour RB0 volatile bit [email protected]; // .1 pour RB1 On cre ici deux variables, switchon et switchoff , de type bit , donc codes chacune sur 1 bit. Ces variables ne devront pas tre places nimporte o en mmoire. Ce quon veut, cest les associer aux bits correspondants aux pins RB0 et RB1 du PORTB. On spcifie donc au compilateur ladresse de ces variables. Par exemple, pour switchon, @0x06.0 , signifie ladresse 0x06, le bit 0 . 0x06 tant, bien entendu, ladresse du PORTB. Le .0 spcifie le rang du bit, ici le bit de poids 0, autrement dit RB0. Et pour switchoff, on procde de la mme manire mais en associant le bit .1 , autrement dit RB1. Lattribut volatile devrait surprendre les familiers du langage C. Cest un ajout de BoostC au langage C ANSI standard, utilis pour spcifier au compilateur que la variable peut tre modifie en dehors du flot normal du programme. Imaginez, vous venez de lire ltat dune variable, vous ne lavez pas modifie, et voil quelle change dtat ! Incomprhensible. Do lattribut volatile. On avait jusqu prsent les variables const constantes, les variables standard modifiables par le programme, et on a maintenant les variables volatile dont ltat peut changer en dehors du programme.

  • - 23 -

    bool go =0; // variable de contrle On cre une autre variable, go , de type bool qui ne peut prendre que deux tats : vrai ou faux (1 ou 0). On ne spcifie pas dadresse, cest donc le compilateur qui lui en attribuera une dans lun des registre gnraux de lespace RAM. On initialise cette variable 0. Celle-ci servira de variable de contrle, nous permettant de valider ou non lallumage des 8 leds. if (switchon == 0) { go = 1; } On introduit une condition de test. Si switchon est gal 0, on attribue la valeur 1 la variable go. Si vous dcouvrez le langage C, remarquez ici la diffrence entre un = qui permet dattribuer une valeur et un == qui permet de tester une galit. if (switchoff == 0) { go = 0; portd = 0b00000000; } Cest au tour de switchoff dtre test. Sil est gal 0 (le bouton poussoir switchoff est actionn et ramne le potentiel Vss sur RB1), on excute la portion de code entre accolades : on attribue la valeur 0 la variable go, puis on met toutes les pins du PORTD 0 -> toutes les leds sont teintes. if ( go ) { portd = 0b00000001; delay_ms(100); ... ... ... } On teste enfin la variable go . Si elle est vraie (tat =1), on excute le code entre accolades qui allume successivement les leds via le PORTD. Si elle est fausse (tat = 0) on recommence la boucle en testant switchon, puis switchoff, puis nouveau go, etc.

    Compilation du programme et injection dans le PIC :

    Rien de particulier ici. Procdez comme pour lexemple prcdent, et tout devrait bien se passer.

  • - 24 -

    Tests

    Vous pouvez alimenter votre circuit et Rien ! Normal, vous navez pas encore appuy sur switchon. Rparez cet oubli : un magnifique effet de balayage anime nouveau vos 8 leds. Appuyez maintenant sur switchoff. Le balayage steint, mais, pas tout de suite ! Uniquement la fin du cycle de balayage des leds (eh oui, on doit attendre que le programme repasse par le test de switchoff).

    Conclusion :

    Le contrle du fonctionnement de notre chenillard par deux boutons poussoirs marque incontestablement un progrs. Vous savez maintenant utiliser les ports I/O du pic en entre et en sortie, utiliser les rsistances de pull-up du PORTB. Cependant, le fonctionnement actuel ne nous satisfait pas pleinement. Ce quon voudrait, cest que le balayage steigne tout de suite, ds quon appuie sur switchoff. Pour remdier cela, on pourrait introduire des tests de switchoff avant chaque allumage de la led suivante, plutt quune seule fois avant de drouler toute la squence. On pourrait galement remplacer la squence par une fonction excute en boucle, le test sur switchoff tant alors ralis avant chaque itration. Quoi quil en soit, nous allons passer ltape suivante : lutilisation du mcanisme dinterruption sur changement dtat du PORTB.

  • - 25 -

    Le PORTB et les interruptions

    Principe de fonctionnement :

    Le port B possde une caractristique particulirement intressante : au mme titre que certains autres modules priphriques du PIC, il a la possibilit de gnrer des interruptions. Pour mmoire, le principe de fonctionnement des interruptions est le suivant : un moment donn (alatoire), un vnement particulier dclenche une interruption (dbordement dun compteur, fin de conversion analogique numrique). Lexcution normale et linaire du programme est interrompue, et le PIC se branche sur une portion de code particulire : la routine dinterruption. Celle-ci excute alors un traitement particulier en rponse lvnement dclencheur de linterruption. Puis, on sort de la routine dinterruption et on retourne lexcution normale du programme. Pour grer ce mcanisme, il faut : valider dans le programme la ou les sources dinterruption, et crire une routine dinterruption approprie. Le contrle des interruptions se fait grce aux registres INTCON, PIE1, PIR1, PIE2, PIR2. Le registre INTCON regroupe les bits de validation (= enable bit) et de signalisation (= flag ou drapeau) des interruptions de base . Les interruptions des modules priphriques sont gres par les registres PIE et PIR. Sur le PIC 16F877 on a deux PIE et deux PIR, tant donn le nombre important de sources dinterruptions possibles. Avec BoostC, la routine dinterruption prend la forme dune fonction particulire, intitule interrupt . Dans lexemple suivant, on va utiliser une interruption gnre par le PORTB pour contrler la vitesse de dfilement des 8 leds contrles par le PORTD. Linterruption sur changement dtat du PORTB est gnre ds quun changement dtat est dtect sur une des pin RB4, RB5, RB6, ou RB7. Dans notre cas, ce sera RB4.

  • - 26 -

    Le matriel :

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    40

    39

    38

    37

    36

    35

    34

    33

    32

    31

    30

    29

    28

    27

    26

    25

    24

    23

    22

    21

    PIC 16F877

    switchint

    Pour cet exemple, pas de grand changement : on se contente de cbler un bouton poussoir supplmentaire sur la pin RB4 (la patte n37 du PIC 16F877). On appelle ce poussoir switchint .

  • - 27 -

    Le programme :

    #include //Cible PIC16F877, bits de configuration #pragma DATA _CONFIG, _PWRTE_OFF & _BODEN_OFF & _WDT_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF & _XT_OSC & _CP_OFF //Configuration de la frquence d'horloge, ici 4Mhz #pragma CLOCK_FREQ 4000000 //*********************************************************************************************** volatile bit [email protected]; // 4 pour RB4 int i; // variable utilise comme compteur dans une boucle "for" bool speed=1; // variable "mmoire" //*********************************************************************************************** void interrupt( void ) //routine de gestion des interruptions { if (intcon & 0b00000001) { delay_ms(10); // attente de 10 ms, pour viter les rebonds du contact if (switchint == 0) // on teste si RB4 est maintenu l'tat bas. { speed = !speed; // inverse l'tat de la variable speed } //portb = portb; //lecture du portb pour supprimer le mismatch. clear_bit( intcon, RBIF); //On efface le bit drapeau de l'interruption } } //*********************************************************************************************** void leds(void) // fonction allumant successivement les leds { portd = 0b00000001; if (speed == 0) { delay_ms(50); } delay_ms(50); for ( i=0; i

  • - 28 -

    } } //*********************************************************************************************** void main( void ) { //Initialisation port A porta = 0x00; //Initialisation port B portb = 0x00; //Initialisation port C portc = 0x00; //Initialisation port D portd = 0x00; //Initialisation port E porte = 0x00; //Configuration port A trisa = 0x00; //Configuration port B trisb = 0x10; // On configure la pin RB4 en entre (0x10 0b00010000) //Configuration port C trisc = 0x00; //Configuration port D trisd = 0x00; //Configuration port E trise = 0x00; //Configuration A/D pins adcon1 = 0x06; //Validation des rsistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU ); //dsactivation (temporaire) du mcanisme de gestion des interruptions clear_bit( intcon, GIE );

    //mise 0 flags + dsactivation toutes interruptions sauf interruption sur //changement PORTB

    intcon = 0b00001000; // on efface les flags, et on valide le bit RBIE : bit de validation d'interruption sur changement du PORTB

    //validation des interruptions : set_bit(intcon, GIE );

  • - 29 -

    //Boucle sans fin while( 1 ) { leds(); } }

    Analyse du programme :

    Notre programme nous permet de faire dfiler les 8 leds contrles par le PORTD : Contrairement aux exemples prcdents o on effectuait un va et vient avec un effet de fondu, les leds sont allumes successivement lune aprs lautre. Puis on recommence. Deux vitesses de dfilement sont possibles. On passe de lune lautre en actionnant le bouton poussoir switchint . #include //Cible PIC16F877, bits de configuration #pragma DATA _CONFIG, _PWRTE_OFF & _BODEN_OFF & _WDT_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF & _XT_OSC & _CP_OFF //Configuration de la frquence d'horloge, ici 4Mhz #pragma CLOCK_FREQ 4000000 Mme squence dinitialisation qu lexemple prcdent : on inclut le fichier system.h, on configure les bits de configuration, et on indique la frquence dhorloge. volatile bit [email protected]; // 4 pour RB4 int i; // variable utilise comme compteur dans une boucle "for" bool speed=1; // variable "mmoire" On dclare ensuite les variables utilises dans le programme : switchint qui est une variable de type bit , affecte la pin RB4 du PORTB, i qui est une variable de type int qui nous servira compter les itrations dune boucle for , et speed , variable boolenne (qui ne peut donc valoir que 0 ou 1) qui nous permettra de contrler les temporisations entre lallumage des leds et donc, la vitesse du dfilement.

  • - 30 -

    void interrupt( void ) //routine de gestion des interruptions { if (intcon & 0b00000001) { delay_ms(10); // attente de 10 ms, pour viter les rebonds du contact if (switchint == 0) // on teste si RB4 est maintenu l'tat bas. { speed = !speed; // inverse l'tat de la variable speed } //portb = portb; //lecture du portb pour supprimer le mismatch. clear_bit( intcon, RBIF); //On efface le bit drapeau de l'interruption } } Voici donc la fameuse routine dinterruption ! Il sagit dune fonction spciale charge du traitement des interruptions. Pas besoin de lappeler dans le corps du programme (contenu dans la fonction main() ), elle sera excute automatiquement lorsquune source dinterruption valide se manifestera. Son nom est fig, donc si vous la remplacez par une fonction void interruption( void ) , a ne marchera pas ! SourceBoost ne reconnaitrait pas quil sagit l de la routine de traitement des interruptions. Quelle que soit la source dinterruption, la fonction interrupt() sera appele. Donc, si vous avez plusieurs sources dinterruptions possibles, il faudra tester quelle est lorigine, afin dexcuter le traitement adquat. Cest ce quon fait ici avec linstruction if (intcon & 0b00000001) : on fait un ET logique entre le registre INTCON et la valeur binaire 0b00000001. Si le bit de poids 0 du registre INCON est gal 1, le rsultat vaudra 1 et la portion de code suivant le test if sera excute. Le bit de poids 0 dINTCON nest autre que RBIF, bit drapeau de signalisation de linterruption sur changement du port PORTB. On aurait pu ici se passer de ce test, tant donn quon a quune seule source dinterruption dans notre exemple. Vient ensuite une temporisation de 10 millisecondes (delay_ms(10) ) qui nous permet de nous affranchir des rebonds du contact de switchint. Sans cela, ces rebonds gnreraient une multitude dinterruptions successives. Puis, on test la valeur de switchint, le traitement effectif nayant lieu que sil est 0, autrement dit si le bouton poussoir est appuy. Je dois vous faire remarquer ici que contre le PIC, vous navez aucune chance : il est beaucoup plus rapide que vous ! Une interruption sera gnre lorsque vous appuierez sur switchint, mais aussi lorsque vous le relcherez ! Mais dans ce dernier cas, switchint sera gal 1, et le traitement sera ignor : la condition du if sera fausse. Vient ensuite le code utile du traitement de notre interruption : on inverse ltat de la variable speed grce loprateur ! (lire NOT ) qui complmente loprande situe sa droite. Ainsi, speed devient gal linverse de speed . Pour mmoire, jai mis en commentaire linstruction portb = portb . Pourquoi ? Il faut savoir ici que linterruption est gnre lorsque ltat physique dune pin du PORTB est diffrent de ltat mmoris dans son tampon de rception. On a alors un mismatch , autrement dit un dcalage. Pour supprimer ce dcalage, il faut effectuer une opration de lecture du PORTB pour raligner ltat thorique et ltat physique du port. Dans notre cas, une lecture de la variable switchint provoque la lecture du port, cest donc dj fait. Mais dans lhypothse ou votre code de

  • - 31 -

    traitement de linterruption naccderait pas au PORTB, il faudrait effectuer cette lecture. Sans quoi, peine sorti de la routine dinterruption, on y retournerait, le mismatch tant toujours prsent ! On efface enfin le bit de signalisation dinterruption, RBIF (poRt B Interrupt Flag bit) grce linstruction clear_bit(intcon, RBIF) . void leds(void) // fonction allumant successivement les leds { portd = 0b00000001; if (speed == 0) { delay_ms(50); } delay_ms(50); for ( i=0; i

  • - 32 -

    void main( void ) { //Initialisation port A porta = 0x00; //Initialisation port B portb = 0x00; //Initialisation port C portc = 0x00; //Initialisation port D portd = 0x00; //Initialisation port E porte = 0x00; //Configuration port A trisa = 0x00; //Configuration port B trisb = 0x10; // On configure la pin RB4 en entre (0x10 0b00010000) //Configuration port C trisc = 0x00; //Configuration port D trisd = 0x00; //Configuration port E trise = 0x00; //Configuration A/D pins adcon1 = 0x06; //Validation des rsistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU ); On entre ensuite dans le corps du programme (la fonction main ), la seule diffrence par rapport lexemple prcdent tant la valeur affecte au registre trisb : seule la pin RB4 est configure en entre.

  • - 33 -

    //dsactivation (temporaire) du mcanisme de gestion des interruptions clear_bit( intcon, GIE );

    //mise 0 flags + dsactivation toutes interruptions sauf interruption sur //changement PORTB

    intcon = 0b00001000; // on efface les flags, et on valide le bit RBIE : bit de validation d'interruption sur changement du PORTB

    //validation des interruptions : set_bit(intcon, GIE ); Viens ensuite la partie configuration du mcanisme dinterruption. Jaurais pu faire plus simple et remplacer les trois instructions par une seule, mais je prfre procder comme suis : 1 dsactivation globale des interruptions avec linstruction clear_bit( intcon, GIE) qui efface le bit GIE du registre INTCON. 2 effacement des bits drapeaux de signalisation dinterruption ventuellement positionns, et configuration de la source dinterruption : pour valider linterruption sur changement dtat du PORTB, on met 1 le bit RBIE. 3 activation globale des interruptions avec linstruction set_bit( intcon, GIE) qui met 1 le bit GIE (Global Interrupt Enable) du registre INTCON. A partir de l, cest parti : si vous appuyez sur switchint, le PIC excutera la fonction interrupt . //Boucle sans fin while( 1 ) { leds(); } Puis vient enfin, comme dans les exemples prcdents, une boucle sans fin qui se contente dappeler la fonction leds() dfinie prcdemment.

  • - 34 -

    Tests Aprs avoir compil et transfr votre programme comme prcdemment, vous pouvez alimenter le montage : les leds se mettent dfiler lune aprs lautre, sans fin. Une pression sur le bouton poussoir switchint fait passer la vitesse de dfilement de rapide lente. Une nouvelle pression sur switchint et la vitesse de dfilement repasse de lente rapide. Autrement dit, a marche : une pression sur le bouton poussoir switchint lance bien la routine dinterruption, et celle-ci inverse effectivement la variable boolenne speed . Trop fort, non ?

    Conclusion :

    Vous connaissez maintenant le mcanisme de base de gestion des interruptions. Les bits de validation (RBIE) et de signalisation (RBIF) de linterruption sur changement du PORTB tant prsents dans le registre INTCON, nous navons pas eu pour linstant nous proccuper des registres PIE1, PIR1, PIE2, PIR2. Mine de rien, notre dernier exemple nous a fait passer dune programmation squentielle , o toutes les actions taient effectues dans lordre, lune la suite de lautre, une programmation vnementielle capable de prendre en compte un vnement tout moment du droulement du programme. Autrement dit : on devient bons !