Your SlideShare is downloading. ×
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Programmation des pic_en_c_part2
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Programmation des pic_en_c_part2

1,770

Published on

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,770
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
123
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Programmation des PIC en CMicrocontrôleur facile pour électronicien amateur PARTIE 2 Noxyben 2008 www.noxyben.fr -1-
  • 2. Introduction ................................................................................................................................ 3Le schéma de base...................................................................................................................... 4Principe de fonctionnement des ports I/O .................................................................................. 7Utilisation des ports d’entrée/sortie (I/O)................................................................................... 8 Utilisation d’un PORT en sortie : un chenillard 8 leds .......................................................... 8 Le matériel : ....................................................................................................................... 8 Le programme : ................................................................................................................ 10 Analyse du programme : .................................................................................................. 12 Compilation du programme et injection dans le PIC : ..................................................... 16 Tests ................................................................................................................................. 17 Conclusion :...................................................................................................................... 17 Utilisation d’un PORT en entrée : un chenillard 8 leds contrôlé par 2 boutons poussoirs. . 18 Le matériel : ..................................................................................................................... 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 matériel : ..................................................................................................................... 26 Le programme : ................................................................................................................ 27 Analyse du programme : .................................................................................................. 29 Tests ................................................................................................................................. 34 Conclusion :...................................................................................................................... 34 -2-
  • 3. IntroductionAprès avoir vu dans la première partie comment est structuré le PIC, on va enchaînerdirectement sur des montages concrets : rien de mieux pour apprendre et mémoriserque de faire soi-même un montage « en vrai ». Je vous invite chaleureusement àfaire un tour chez votre marchand de composants électroniques et à faire chauffervotre fer à souder. Vous allez avoir besoin d’un PIC16F877, un programmateur, uneplatine d’essai du genre « pastilles pré-percées » au pas de 2,54 mm, et quelquescomposants qui traînent certainement dans vos fonds de tiroirs : Led, régulateur7805, condensateurs, support 40 broches…Pour la partie logicielle il vous faudra télécharger la version de démonstration deSourceBoost, qui comprend le compilateur BoostC que nous allons employer, etéventuellement un logiciel de transfert comme Icprog pour piloter votreprogrammateur de PIC. Si vous avez acheté un programmateur en kit comme leVelleman K8076, le logiciel « PICPROG » est compris. Pensez à télécharger lesmises à jour. -3-
  • 4. Le schéma de base IC2 D1 9V = 7805 R1 C3 C4 Led1 1 40 2 39 ICSP 3 38 4 37 5 36 6 35 7 34 PIC 16F877 8 33 C6-4- 9 32 10 31 C5 11 30 12 29 13 28 14 27 15 26 C2 16 25 C1 17 24 Q1 18 23 19 22 20 21 IC1
  • 5. Le schéma ci-dessus est la base sur laquelle on va pouvoir construire desapplications utiles. Il ne fait rien d’autre que de permettre au PIC de fonctionner, c’esten quelque sorte le « minimum vital ». Bien entendu, d’autres variantes sontpossibles, mais plutôt que d’en dresser la liste exhaustive, je vous propose deréaliser cette version et de remettre à plus tard l’étude des différents circuitsd’oscillateur, de reset…L’alimentation : Pour alimenter le circuit, une source continue d’environ 9V feraparfaitement l’affaire (une pile 9V par exemple). La régulation et l’adaptation à unniveau de 5V requis par le PIC incombent au régulateur 7805.Remarque : pour que celui-ci fonctionne correctement, la tension d’alimentation doitêtre supérieure d’au moins 2 ou 3 volts à la tension régulée, donc 5 + 2 = 7 Volts.La diode D1 protège le circuit contre les inversions accidentelles de polarité (diodetype 1N4001 ou 1N4007 par exemple).Le condensateur C3 sert de « réservoir » au régulateur. La règle habituelle est deprendre 1000 F / Ampère. Dans notre cas, un condensateur électrochimiquede 470 avec une tension d’au moins 16V convient parfaitement.Le condensateur C4 nous permet de découpler le régulateur du reste ducircuit : il absorbe les variations de tension parasite qui pourraient remontervers le régulateur. 10 ou 100 nF devraient convenir.Le couple R1 – Led1 sert de témoin de mise sous tension, et accessoirementdécharge le condensateur C3 lorsque l’alimentation est coupée.Avec une tension d’alimentation de 9V, on prendra pour R1 une valeur de390 1/4WLes condensateurs C5 et C6 quant à eux sont des condensateurs dedécouplage du PIC. À monter au plus près du 16F877, ils empêchent qued’éventuels parasites collectés par les lignes d’alimentation ne pénètrent dansle circuit intégré. Quelques pF ou nF du genre condensateur « tantale goutte »feront l’affaire. Surtout pas de gros condensateur électrochimique de plusieurs F qui aurait un effet néfaste sur le temps de montée de l’alimentation etpourrait ainsi perturber le PIC au moment du démarrage.L’oscillateur : Il est constitué de Q1, un quartz « parallèle » dont la fréquenced’oscillation nominale peut aller jusqu’à 20MHz, et des condensateurs C1 etC2 pour lequel on prendra une valeur de 20pF, conformément aux indicationsde la documentation de Microchip. -5-
  • 6. Le connecteur ICSP : Bien que n’étant pas indispensable, on va équipernotre platine de ce connecteur « In Circuit Serial Programming », qui nouspermettra de programmer le PIC sans le retirer de son support. A vrai dire, lebrochage n’est pas vraiment normalisé. Je vous propose donc la versionsuivante, que vous pourrez adapter à votre guise. Le seul impératif est que lesbonnes lignes du programmateur aboutissent sur les bonnes pattes du PIC • patte 1 - 6 : Vpp (tension de programmation) • patte 2 - 7 : VDD (tension d’alimentation 5V) • patte 3 - 8 : PGD (Program Data = ligne de transfert des données) • patte 4 – 9 : Vss (tension de masse = 0V) • patte 5 - 10 : PGC (Program Clock = ligne d’horloge de programmation) 1 6 2 7 3 8 4 9 5 10En fonctionnement normal, la pin 1 est pontée sur la pin 6, la pin 2 sur la 7, la3 sur la 8, la 4 sur la 9 et la 5 sur la 10.Pour programmer le PIC on déconnecte l’alimentation du circuit, on ôte tousles ponts du connecteur ICSP et on branche à la place le cordon ICSP duprogrammateur, en veillant à ce que les signaux correspondent bien. Si cen’est pas le cas, il vous faudra confectionner un cordon ad’ hoc en croisant lesbonnes lignes.Le circuit de RESET : Rien de plus simple pour l’instant : la ligne de reset MCLR (la pin 1 du PIC) est simplement reliée à la tension d’alimentation.Ainsi, pour redémarrer le PIC, on coupe l’alimentation et on réalimente. -6-
  • 7. Principe de fonctionnement des ports I/O Les ports d’entrée / sortie numériques peuvent être considérés comme lespériphériques les plus simples du microcontrôleur. Pour le PIC, on contrôle leurfonctionnement à l’aide de registres spéciaux (deux registres par port). Par exemple,pour le port A, on a le registre PORTA et le registre TRISA.Les registres « TRISx » contrôlent le mode de fonctionnement des entrées / sorties :selon la valeur de chaque bit, 0 ou 1, la pin correspondante du port fonctionnera soiten sortie, soit en entrée. Les registres « PORTx » contiennent les données, lues, ouà écrire sur le port. Certains ports possèdent en plus des fonctionnalités spécifiques :le PORTB est équipé de résistances de tirage (pull-up) internes qui peuvent êtreactivées ou non. La pin RB0 du PORTB sert d’entrée d’interruption externe, et lespins RB4 à RB7 peuvent générer une interruption lorsqu’un changement d’état estdétecté à leurs bornes. Toutes ces particularités sont bien entendu décrites dans lesdocumentations Microchip spécifiques à chaque composant. -7-
  • 8. Utilisation des ports d’entrée/sortie (I/O)Utilisation d’un PORT en sortie : un chenillard 8 ledsLe matériel : 1 40 2 39 3 38 4 37 VCC 5 36 6 35 R9 R8 R7 R6 R5 R4 R3 R2 7 34 PIC 16F877 8 33 9 32 10 31 11 30 Rd8 12 29 13 28 Rd8 14 27 15 26 Rd6 16 25 17 24 Rd5 18 23 19 22 Rd4 20 21 Rd3 Rd2 Rd1On va rajouter les quelques composants du schéma ci-dessus à notre montage debase. 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 résistancesappropriées, (ça marche aussi) mais au cas où l’idée vous viendrait d’allumer les 8leds en même temps, le courant débité par le PORTD pourrait dépasser la valeurlimite. En effet, un coup d’œil à la rubrique caractéristiques électriques du datasheetnous informe que le courant maximal pouvant être débité par un PORT est de 200mA. Avec des résistances légèrement sous-dimensionnées et 8 leds allumées onpourrait s’en approcher dangereusement. Bon, c’est vrai, j’exagère un peu, mêmeavec 8 x 20 mA on n’est encore qu’à 160mA de consommation sur le port. Maisautant adopter de bons réflexes dès le départ. On choisit donc de passer par destransistors. On pourra prendre des transistors petit signaux standard. Si vous trouvezdans vos tiroirs des BC537 ou 2N2222 ou quoi que ce soit d’équivalent, çaconviendra parfaitement.Pour les résistances R2 à R9, si on considère que le point de fonctionnement desleds est à environ 1,8V / 10 mA, et que VCC = 5 V : VRx = 5-1,8 = 3,2V ; doncR = VRx / I = 3,2 / 0.01 = 320. -8-
  • 9. La valeur normalisée la plus proche étant 330, on prendra donc pour les résistancesR2 à R9 des 330 Ohms ¼ de Watt.Pour les résistances Rd1 à Rd8, afin d’assurer une bonne saturation des transistors,on prendra des résistances de 4,7 kOhms ¼ de Watt. -9-
  • 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 <system.h>//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 fréquence dhorloge, ici 20Mhz#pragma CLOCK_FREQ 20000000void 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; //désactivation du mécanisme de gestion des interruptions clear_bit( intcon, GIE ); - 10 -
  • 11. //Validation des résistances de pull-ups du port Bclear_bit( option_reg, NOT_RBPU );//Boucle sans finwhile( 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; - 11 -
  • 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 détails :#include <system.h>Cette directive indique au précompilateur d’inclure le fichier system.h. Celui-cicontient à son tour une inclusion pour le fichier spécifique à votre PIC (16F877.h),dans lequel sont indiquées les associations nom de registre / adresses mémoire.D’où l’importance de bien indiquer à BoostC la cible (ici 16F877) pour laquelle vousdésirez compiler votre programme.#pragma DATA _CONFIG, _PWRTE_OFF & _BODEN_OFF & _WDT_OFF &_LVP_OFF & _CPD_OFF & _DEBUG_OFF & _HS_OSC & _CP_OFFUne autre directive de précompilation, qui permet de définir les bits de configurationdu PIC. Pour mémoire, ces bits de configuration permettent de configurer un certainnombre de paramètres de fonctionnement du PIC. Bien heureusement, SourceBoostreprend à peu de chose près les mêmes désignations que Microchip : • PWRTE_OFF : désactive le Power-up Timer Enable bit • BODEN_OFF : désactive le Brown-Out reset Enable bit • WDT_OFF : désactive le Watch Dog Timer • LVP_OFF : désactive le Low Voltage Programming • CPD_OFF : désactive la protection de la mémoire de données EEPROM ? • DEBUG_OFF : désactive l’In-Circuit Debugger • HS_OSC : Configure l’oscillateur en mode HS (High Speed) • CP_OFF : désactive la protection du codePour l’instant on désactive tout (OFF), à part bien sûr l’oscillateur qu’on configure enmode « HS », mode recommandé par Microchip pour l’emploi d’un quartz 20 MHz.Si vous utilisez un quartz 4 MHz, le mode le plus approprié sera « XT ». La différenceréside entre HS et XT réside dans le gain de l’amplificateur inverseur du circuitd’oscillateur du PIC. Plus la fréquence de travail est élevée, plus le gain doit être - 12 -
  • 13. élevé. Mais dans la pratique, en mode « HS » et avec un quartz à 4 MHz, ça marcheaussi. Pour savoir quel mode choisir, regardez dans la documentation Microchip surla gamme des PIC « mid-range », ou mieux sur la documentation du 16F877 dans lasection « oscillator ».#pragma CLOCK_FREQ 20000000A nouveau une directive de précompilation. On indique ici quelle est la fréquence duquartz utilisé. Les temporisations générées par la fonction « delay » utilisée plus loindans le programme sont basées sur cette valeur.void main( void ){}La fonction « main » est obligatoire en langage C : c’est le « point d’entrée » duprogramme. Le «void» placé avant «main» indique que la fonction ne retourneaucune valeur, et le «void» entre parenthèses indique qu’on ne prend pas de valeuren argument. Tout le reste de notre programme viendra se placer entre lesaccolades 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 affectées aux registrescorrespondant à l’état des Entrées/Sortie des ports. (respectivement le PORTA,PORTB, PORTC, PORTD, PORTE). Ces variables sont déclarées dans le fichierd’entête spécifique au PIC 16F877 (fichier avec l’extension « .h » ), lui-même inclusdans le fichier «system.h». Ainsi, vous pouvez accéder à un registre du PICsimplement en l’appelant par son nom, sans se soucier de son adresse.Écrire une donnée dans un de ces registres affectera dès-lors les pinscorrespondantes du PORT, si celles-ci sont configurées en sortie. Ici, on initialise toutà 0. - 13 -
  • 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 même principe que pour les registres porta, portb, portc… les variablestrisa, trisb, trisc, trisd, trise sont affectées aux registres de contrôle de direction desports (respectivement le PORTA, PORTB, PORTC, PORTD, PORTE). On affecte aucinq registres «tris» la valeur hexadécimale (d’où le «x» pour heXa) 00. Un coupd’œil aux fiches détaillées des registres correspondant nous montre que cette valeur00 passe toutes les lignes d’Entrés/Sortie des ports en mode « sortie ».Une remarque : Microchip recommande de d’initialiser en premier lieu les registres« portx », et de configurer la direction avec les registres « trisx » ensuite. Pour éviterd’avoir un état incertain sur les pins au moment du démarrage. //Configuration A/D pins adcon1 = 0x06;Certaines pins des ports sont susceptibles d’être utilisée par le convertisseurAnalogique / Numérique. Par défaut, (voir fiche détaillée du registre adcon1), les pinsen question sont configurées en mode analogique. La valeur hexadécimale 0x06 lespasse en mode numérique. //désactivation du mécanisme de gestion des interruptions clear_bit( intcon, GIE );Le registre intcon contrôle le mécanisme d’interruption. «intcon» pour INTerruptCONtrol. GIE, Global Interrupt Enable bit, est un des bits du registre intcon, il activeou désactive de manière globale toutes les interruptions. La fonction «clear_bit()» estune fonction implémentée par BoostC, permettant de mettre un bit à 0. Son pendantest la fonction «set_bit()» qui permet, elle de mettre un bit à 1. La syntaxe ci-dessussignifie donc : « mettre à 0 le bit GIE du registre intcon ». - 14 -
  • 15. //Validation des résistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU );Le registre option_reg contrôle certaines options du PIC, parmi lesquelles figurel’activation ou non des résistances de pull-up du PORTB. Le bit correspondant àcette option est NOT_RBPU. Celui-ci fonctionne en logique négative (d’où le NOTdevant RBPU). La syntaxe ci-dessus signifie donc « mettre à 0 le bit NOT_RBPU duregistre option_reg ». Or, étant donné que le bit NOT_RBPU fonctionne en logiquenégative, le mettre à 0 signifie ACTIVER les résistances de pull-up du PORTB ! Pourl’instant on ne se sert pas de ces résistances, donc vous pouvez, si vous préférez,mettre ce bit à 1 pour les désactiver. //Boucle sans fin while( 1 ) { }Comme l’indique le commentaire, il s’agit là d’une boucle sans fin. «While» est uneinstruction de contrôle de boucle du langage C. La traduction française donnerait :« tant que 1… ». Or, «1» n’a pas de raison de changer d’état, donc une fois lancée,on ne sort pas de cette boucle. Tout le code entre les accolades ouvrante etfermante se répètera dès lors indéfiniment. portd = 0b00000001;La variable «portd» est affectée au registre correspondant à l’état des Entrées/Sortiedu PORTD. Ici, on écrit la donnée binaire (d’où le b de 0bxxxxxxxx) 0b00000001, cequi a pour effet de passer la pin RD0 à l’état 1, alors que les pins RD1 à RD7 restentà l’état 0. delay_ms(100);La fonction «delay_ms()» est une fonction implémentée par BoostC, permettantd’introduire une temporisation. Ici, delay_ms(100) génère une temporisation de 100millisecondes. Cette temporisation est calculée en fonction de la valeur de lafréquence d’horloge qu’on a indiquée plus en amont par la directive PRAGMACLOCK_FREQ. - 15 -
  • 16. portd = 0b00000011; delay_ms(10);On « allume » une deuxième 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, onattend 100 ms, on allume une deuxième led, on attend 10 ms, on éteint la premièreled, on attend 100 ms, etc. L’allumage simultané de deux les n’est là que pourdiminuer l’effet de saccade lors du passage d’une led à l’autre.Vous l’aurez remarqué : cette manière de faire est un peu « rustique », on aurait puremplacer la répétition des instructions par des boucles bien construites. Mais d’unpoint de vue didactique ça me semble plus simple à comprendre, et comme on estloin d’avoir saturé la mémoire du PIC…Compilation du programme et injection dans le PIC :Après l’étude théorique, il ne reste plus qu’à compiler notre programme et l’injecterdans le PIC. Pour cela, on va suivre les étapes suivantes :COMPILATION : • Lancez l’IDE de SourceBoost. • Assurer vous que le compilateur utilisé est bien BoostC (dans le menu paramètres). • Créez un nouveau projet (menu Projet : Nouveau). • Dans ce projet, créez un nouveau fichier (menu Fichier : Nouveau) dans lequel vous allez copier le code ci-dessus. • Sélectionnez la « cible », autrement dit le composant pour lequel vous voulez compiler le projet : PIC 16F877 (menu Paramètres : Cible) • Compilez le programme (menu Construction : Construire) • Si tout s’est bien passé, le compilateur indique « success » et a généré dans le répertoire de votre projet plusieurs fichiers. L’un d’entre 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). • Sélectionnez la cible, ici un PIC 16F877 (si vous ne le trouvez pas dans la liste, vérifiez sur le site de Velleman s’il n’y a pas de mise à jour). • Ouvrez le fichier «.hex » généré par le compilateur pour votre projet • Cliquez sur le bouton « write all data », et attendez que le transfert s’effectue. - 16 -
  • 17. • Si à ce stade tout est ok, déconnectez le programmateur, placez le PIC sur son circuit ou remettez les ponts à la place du connecteur ICSP de votre platine prototype.TestsVous pouvez alimenter votre circuit et… He is alive ! Un magnifique effet de balayageanime vos 8 led. Elle est pas belle la vie ?Conclusion :Ca y est, vous avez créé une application à base de microcontrôleur ! Il est vrai quepour l’instant, l’interaction de notre montage avec le monde réel est très limitée. Ilpeut néanmoins servir à créer de jolis effets lumineux. On pourrait égalementenvisager de s’en servir comme télécommande rustique (à une seule fonction ?) enmontant une led infrarouge et en programmant la séquence d’allumages/extinctionsadéquate. - 17 -
  • 18. Utilisation d’un PORT en entrée : un chenillard 8 leds contrôlé par 2boutons poussoirs.Étape suivante : on va utiliser des pins d’un autre port en entrée, pour contrôler lefonctionnement de notre application.Le matériel : 1 40 2 39 3 38 4 37 5 36 6 35 7 34 RB1 RB0/INT PIC 16F877 8 33 9 32 10 31 11 30 12 29 13 28 switchon switchoff 14 27 15 26 16 25 17 24 18 23 19 22 20 21On reprend le schéma précédent, et on y ajoute deux boutons poussoirs directementraccordés aux pins RB0 et RB1, autrement dit les deux bits de poids faible duPORTB. Vous allez me dire, « Quand on appuie sur les boutons poussoirs, ok, lespins sont à la masse, mais quand on relâche le potentiel est flottant, non ? »justement non, puisque qu’on va utiliser les résistances de pull-up interne du PIC.Une remarque importante : il n’y a que le PORTB qui soit équipé de tellesrésistances. Si vous utilisez un autre port, il faudra câbler vous-même cesrésistances de tirage entre VCC et la pin correspondante. - 18 -
  • 19. Le programme :La structure générale est identique à l’exemple précédent, avec tout de mêmequelques modifications :#include <system.h>//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 fréquence dhorloge, ici 4Mhz#pragma CLOCK_FREQ 4000000void 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 entrée //Configuration port C trisc = 0x00; //Configuration port D trisd = 0x00; //Configuration port E trise = 0x00; //Configuration A/D pins adcon1 = 0x06; //désactivation du mécanisme de gestion des interruptions clear_bit( intcon, GIE ); - 19 -
  • 20. //Validation des résistances de pull-ups du port Bclear_bit( option_reg, NOT_RBPU );volatile bit switchon@0x06.0; // 0 pour RB0volatile bit switchoff@0x06.1; // 1 pour RB1bool go =0; // variable de contrôle//Boucle sans finwhile( 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; - 20 -
  • 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); } }} - 21 -
  • 22. Analyse du programme :Le programme ressemble, à quelques détails près, à celui de l’exemple précédent./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 fréquence dhorloge, ici 4Mhz#pragma CLOCK_FREQ 4000000Comme vous pouvez le constater, on a changé de quartz. De 20 MHz on est passé à4 MHz. Pourquoi ? Pas de raison particulière, c’est uniquement dans un butdidactique. Si vous voulez conserver votre quartz 20 MHz, conservez les valeurs del’exemple précédent pour cette section.//Configuration port B trisb = 0x03; // On configure les deux pins de poids faible en entréeLes deux boutons poussoirs (« switchon » et « switchoff » sur le schéma) sont câbléssur les pins du port B : RB0 et RB1. Dans l’exemple précédent, ces pins étaientconfigurées en sortie. Il nous faut maintenant les configurer en entrée. Pour cela, onmet à 1 les bits correspondants du registre trisb, qui contrôle la direction du PORTB.Ce qui nous donne, en binaire : 0b00000011, et donc, en hexadécimal : 0x03. volatile bit switchon@0x06.0; // .0 pour RB0 volatile bit switchoff@0x06.1; // .1 pour RB1On crée ici deux variables, « switchon » et « switchoff », de type « bit », donc codéeschacune sur 1 bit. Ces variables ne devront pas être placées n’importe où enmémoire. Ce qu’on veut, c’est les associer aux bits correspondants aux pins RB0 etRB1 du PORTB. On spécifie donc au compilateur l’adresse de ces variables. Parexemple, pour switchon, « @0x06.0 », signifie « à l’adresse 0x06, le bit 0 ». 0x06étant, bien entendu, l’adresse du PORTB. Le « .0 » spécifie le rang du bit, ici le bit depoids 0, autrement dit RB0. Et pour switchoff, on procède de la même manière maisen associant le bit « .1 », autrement dit RB1.L’attribut « volatile » devrait surprendre les familiers du langage C. C’est un ajout deBoostC au langage C ANSI standard, utilisé pour spécifier au compilateur que lavariable peut être modifiée en dehors du flot normal du programme. Imaginez, vousvenez de lire l’état d’une variable, vous ne l’avez pas modifiée, et voilà qu’ellechange d’état ! Incompréhensible. D’où l’attribut volatile. On avait jusqu’à présent lesvariables « const » constantes, les variables standard modifiables par le programme,et on a maintenant les variables « volatile » dont l’état peut changer en dehors duprogramme. - 22 -
  • 23. bool go =0; // variable de contrôleOn crée une autre variable, « go », de type « bool » qui ne peut prendre que deuxétats : vrai ou faux (1 ou 0). On ne spécifie pas d’adresse, c’est donc le compilateurqui lui en attribuera une dans l’un des registre généraux de l’espace RAM. Oninitialise cette variable à 0. Celle-ci servira de variable de contrôle, nous permettantde valider ou non l’allumage 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 découvrez le langage C, remarquez ici la différence entre un« = » qui permet d’attribuer une valeur et un « == » qui permet de tester une égalité. if (switchoff == 0) { go = 0; portd = 0b00000000; }C’est au tour de switchoff d’être testé. S’il est égal à 0 (le bouton poussoir switchoffest actionné et ramène le potentiel Vss sur RB1), on exécute la portion de code entreaccolades : on attribue la valeur 0 à la variable go, puis on met toutes les pins duPORTD à 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 exécute le codeentre 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. Procédez comme pour l’exemple précédent, et tout devraitbien se passer. - 23 -
  • 24. TestsVous pouvez alimenter votre circuit et… Rien !Normal, vous n’avez pas encore appuyé sur switchon. Réparez cet oubli : unmagnifique effet de balayage anime à nouveau vos 8 leds.Appuyez maintenant sur switchoff. Le balayage s’éteint, mais, pas tout de suite !Uniquement à la fin du cycle de balayage des leds (eh oui, on doit attendre que leprogramme repasse par le test de switchoff).Conclusion :Le contrôle du fonctionnement de notre chenillard par deux boutons poussoirsmarque incontestablement un progrès. Vous savez maintenant utiliser les ports I/Odu pic en entrée et en sortie, utiliser les résistances de pull-up du PORTB.Cependant, le fonctionnement actuel ne nous satisfait pas pleinement. Ce qu’onvoudrait, c’est que le balayage s’éteigne tout de suite, dès qu’on appuie surswitchoff. Pour remédier à cela, on pourrait introduire des tests de switchoff avantchaque allumage de la led suivante, plutôt qu’une seule fois avant de dérouler toutela séquence. On pourrait également remplacer la séquence par une fonctionexécutée en boucle, le test sur switchoff étant alors réalisé avant chaque itération.Quoi qu’il en soit, nous allons passer à l’étape suivante : l’utilisation du mécanismed’interruption sur changement d’état du PORTB. - 24 -
  • 25. Le PORTB et les interruptionsPrincipe de fonctionnement :Le port B possède une caractéristique particulièrement intéressante : au même titreque certains autres modules périphériques du PIC, il a la possibilité de générer desinterruptions.Pour mémoire, le principe de fonctionnement des interruptions est le suivant : à unmoment donné (aléatoire), un événement particulier déclenche une interruption(débordement d’un compteur, fin de conversion analogique numérique…).L’exécution normale et linéaire du programme est interrompue, et le PIC se branchesur une portion de code particulière : la routine d’interruption. Celle-ci exécute alorsun traitement particulier en réponse à l’événement déclencheur de l’interruption.Puis, on sort de la routine d’interruption et on retourne à l’exécution normale duprogramme.Pour gérer ce mécanisme, il faut : valider dans le programme la ou les sourcesd’interruption, et écrire une routine d’interruption appropriée.Le contrôle des interruptions se fait grâce aux registres INTCON, PIE1, PIR1, PIE2,PIR2. Le registre INTCON regroupe les bits de validation (= enable bit) et designalisation (= flag ou drapeau) des interruptions « de base ». Les interruptions desmodules périphériques sont gérées par les registres PIE et PIR. Sur le PIC 16F877on a deux PIE et deux PIR, étant donné le nombre important de sourcesd’interruptions possibles.Avec BoostC, la routine d’interruption prend la forme d’une fonction particulière,intitulée « interrupt ».Dans l’exemple suivant, on va utiliser une interruption générée par le PORTB pourcontrôler la vitesse de défilement des 8 leds contrôlées par le PORTD. L’interruptionsur changement d’état du PORTB est générée dès qu’un changement d’état estdétecté sur une des pin RB4, RB5, RB6, ou RB7. Dans notre cas, ce sera RB4. - 25 -
  • 26. Le matériel : 1 40 2 39 3 38 4 37 5 36 6 35 7 34 PIC 16F877 8 33 9 32 10 31 11 30 12 29 13 28 switchint 14 27 15 26 16 25 17 24 18 23 19 22 20 21Pour cet exemple, pas de grand changement : on se contente de câbler un boutonpoussoir supplémentaire sur la pin RB4 (la patte n°37 du PIC 16F877). On appelle cepoussoir « switchint ». - 26 -
  • 27. Le programme :#include <system.h>//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 fréquence dhorloge, ici 4Mhz#pragma CLOCK_FREQ 4000000//*********************************************************************************************** volatile bit switchint@0x06.4; // 4 pour RB4 int i; // variable utilisée comme compteur dans une boucle "for" bool speed=1; // variable "mémoire"//***********************************************************************************************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 linterruption }}//***********************************************************************************************void leds(void) // fonction allumant successivement les leds{ portd = 0b00000001; if (speed == 0) { delay_ms(50); } delay_ms(50); for ( i=0; i<8; i++ ) { portd = portd << 0b00000001; if (speed == 0) { delay_ms(50); } delay_ms(50); - 27 -
  • 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 entrée (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 résistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU ); //désactivation (temporaire) du mécanisme de gestion des interruptions clear_bit( intcon, GIE ); //mise à 0 flags + désactivation toutes interruptions sauf interruption sur //changement PORTB intcon = 0b00001000; // on efface les flags, et on valide le bit RBIE : bit de validation dinterruption sur changement du PORTB //validation des interruptions : set_bit(intcon, GIE ); - 28 -
  • 29. //Boucle sans fin while( 1 ) { leds(); }}Analyse du programme :Notre programme nous permet de faire défiler les 8 leds contrôlées par le PORTD :Contrairement aux exemples précédents où on effectuait un « va et vient » avec uneffet de fondu, les leds sont allumées successivement l’une après l’autre. Puis onrecommence.Deux vitesses de défilement sont possibles. On passe de l’une à l’autre enactionnant le bouton poussoir « switchint ».#include <system.h>//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 fréquence dhorloge, ici 4Mhz#pragma CLOCK_FREQ 4000000Même séquence d’initialisation qu’à l’exemple précédent : on inclut le fichiersystem.h, on configure les bits de configuration, et on indique la fréquence d’horloge. volatile bit switchint@0x06.4; // 4 pour RB4 int i; // variable utilisée comme compteur dans une boucle "for" bool speed=1; // variable "mémoire"On déclare ensuite les variables utilisées dans le programme :« switchint » qui est une variable de type « bit », affectée à la pin RB4 du PORTB,« i » qui est une variable de type « int » qui nous servira à compter les itérationsd’une boucle « for », et « speed », variable booléenne (qui ne peut donc valoir que 0ou 1) qui nous permettra de contrôler les temporisations entre l’allumage des leds etdonc, la vitesse du défilement. - 29 -
  • 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 linterruption }}Voici donc la fameuse routine d’interruption ! Il s’agit d’une fonction spéciale chargéedu traitement des interruptions. Pas besoin de l’appeler dans le corps du programme(contenu dans la fonction main() ), elle sera exécutée automatiquement lorsqu’unesource d’interruption valide se manifestera. Son nom est figé, donc si vous laremplacez par une fonction « void interruption( void ) », ça ne marchera pas !SourceBoost ne reconnaitrait pas qu’il s’agit là de la routine de traitement desinterruptions. Quelle que soit la source d’interruption, la fonction interrupt() seraappelée. Donc, si vous avez plusieurs sources d’interruptions possibles, il faudratester quelle est l’origine, afin d’exécuter le traitement adéquat.C’est ce qu’on fait ici avec l’instruction « if (intcon & 0b00000001) » : on fait un ETlogique entre le registre INTCON et la valeur binaire 0b00000001. Si le bit de poids 0du registre INCON est égal à 1, le résultat vaudra 1 et la portion de code suivant letest « if » sera exécutée. Le bit de poids 0 d’INTCON n’est autre que RBIF, bit« drapeau » de signalisation de l’interruption sur changement du port PORTB.On aurait pu ici se passer de ce test, étant donné qu’on a qu’une seule sourced’interruption dans notre exemple.Vient ensuite une temporisation de 10 millisecondes (delay_ms(10) ) qui nous permetde nous affranchir des rebonds du contact de switchint. Sans cela, ces rebondsgénéreraient une multitude d’interruptions successives.Puis, on test la valeur de switchint, le traitement effectif n’ayant lieu que s’il est à 0,autrement dit si le bouton poussoir est appuyé. Je dois vous faire remarquer ici quecontre le PIC, vous n’avez aucune chance : il est beaucoup plus rapide que vous !Une interruption sera générée lorsque vous appuierez sur switchint, mais aussilorsque vous le relâcherez ! Mais dans ce dernier cas, switchint sera égal à 1, et letraitement sera ignoré : la condition du « if » sera fausse.Vient ensuite le code utile du traitement de notre interruption : on inverse l’état de lavariable « speed » grâce à l’opérateur « ! » (lire « NOT ») qui complémentel’opérande située à sa droite. Ainsi, « speed » devient égal à l’inverse de « speed ».Pour mémoire, j’ai mis en commentaire l’instruction « portb = portb ». Pourquoi ? Ilfaut savoir ici que l’interruption est générée lorsque l’état physique d’une pin duPORTB est différent de l’état mémorisé dans son tampon de réception. On a alors un« mismatch », autrement dit un décalage. Pour supprimer ce décalage, il fauteffectuer une opération de lecture du PORTB pour « réaligner » l’état théorique etl’état physique du port. Dans notre cas, une lecture de la variable switchint provoquela lecture du port, c’est donc déjà fait. Mais dans l’hypothèse ou votre code de - 30 -
  • 31. traitement de l’interruption n’accéderait pas au PORTB, il faudrait effectuer cettelecture. Sans quoi, à peine sorti de la routine d’interruption, on y retournerait, le« mismatch » étant toujours présent !On efface enfin le bit de signalisation d’interruption, RBIF (poRt B Interrupt Flag bit)grâce à l’instruction « 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<8; i++ ) { portd = portd << 0b00000001; if (speed == 0) { delay_ms(50); } delay_ms(50); }}Contrairement aux exemples précédents, le code chargé d’allumer successivementles leds est regroupé dans une fonction, appelée « leds ». Le « void » à gauchesignifie qu’on ne retourne aucune valeur, alors que le void entre parenthèses indiquequ’on ne prend aucune valeur en argument.On allume notre première led sur RD0 grâce à l’instruction « portd = 0b00000001 ;Puis, on test la variable « speed ». En fonction du résultat, soit on exécute unepremière temporisation de 50 millisecondes suivie d’une deuxième temporisation de50ms, soit on exécute uniquement la deuxième temporisation.Puis on entre dans la boucle for, qui utilise la variable « i » comme compteur.Dans cette boucle, exécutée 7 fois, on commence par effectuer un décalage à l’aidede l’instruction « portd = portd << 0b00000001 ; ». La traduction en français de cetteinstruction donne quelque chose du genre « portd est égal à portd décalé d’un bitvers la gauche ». L’opérateur de décalage étant << .Puis, on retrouve nos deux temporisations dont la première est conditionnée à lavaleur de « speed ». - 31 -
  • 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 entrée (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 résistances de pull-ups du port B clear_bit( option_reg, NOT_RBPU );On entre ensuite dans le corps du programme (la fonction « main »), la seuledifférence par rapport à l’exemple précédent étant la valeur affectée au registre« trisb » : seule la pin RB4 est configurée en entrée. - 32 -
  • 33. //désactivation (temporaire) du mécanisme de gestion des interruptions clear_bit( intcon, GIE ); //mise à 0 flags + désactivation toutes interruptions sauf interruption sur //changement PORTB intcon = 0b00001000; // on efface les flags, et on valide le bit RBIE : bit de validation dinterruption sur changement du PORTB //validation des interruptions : set_bit(intcon, GIE );Viens ensuite la partie configuration du mécanisme d’interruption. J’aurais pu faireplus simple et remplacer les trois instructions par une seule, mais je préfère procédercomme suis :1 – désactivation globale des interruptions avec l’instruction « clear_bit( intcon,GIE) » qui efface le bit GIE du registre INTCON.2 – effacement des bits « drapeaux » de signalisation d’interruption éventuellementpositionnés, et configuration de la source d’interruption : pour valider l’interruption surchangement d’état du PORTB, on met à 1 le bit RBIE.3 – activation globale des interruptions avec l’instruction « set_bit( intcon, GIE) » quimet à 1 le bit GIE (Global Interrupt Enable) du registre INTCON. A partir de là, c’estparti : si vous appuyez sur switchint, le PIC exécutera la fonction « interrupt ». //Boucle sans fin while( 1 ) { leds(); }Puis vient enfin, comme dans les exemples précédents, une boucle sans fin qui secontente d’appeler la fonction « leds() » définie précédemment. - 33 -
  • 34. TestsAprès avoir compilé et transféré votre programme comme précédemment, vouspouvez alimenter le montage : les leds se mettent à défiler l’une après l’autre, sansfin. Une pression sur le bouton poussoir switchint fait passer la vitesse de défilementde rapide à lente. Une nouvelle pression sur switchint et la vitesse de défilementrepasse de lente à rapide. Autrement dit, ça marche : une pression sur le boutonpoussoir switchint lance bien la routine d’interruption, et celle-ci inverse effectivementla variable booléenne « speed ».Trop fort, non ?Conclusion :Vous connaissez maintenant le mécanisme de base de gestion des interruptions.Les bits de validation (RBIE) et de signalisation (RBIF) de l’interruption surchangement du PORTB étant présents dans le registre INTCON, nous n’avons paseu pour l’instant à nous préoccuper des registres PIE1, PIR1, PIE2, PIR2.Mine de rien, notre dernier exemple nous a fait passer d’une programmation« séquentielle », où toutes les actions étaient effectuées dans l’ordre, l’une à la suitede l’autre, à une programmation « événementielle » capable de prendre en compteun événement à tout moment du déroulement du programme.Autrement dit : on devient bons ! - 34 -

×