Utilisation des interruptions avec le PIC Claude Barbaud 10 janvier 2011 Princi

Utilisation des interruptions avec le PIC Claude Barbaud 10 janvier 2011 Principe: Le fonctionnement par interruptions sur un microcontrôleur permet à celui-ci d'exécuter une tâche(programme principal) qui peut être interrompue par un événement. Le processeur doit alors exécuter une tâche(sous-programme) associée à cette source d'interruption. Quand la tâche est exécutée, le processeur revient à sa tâche principale. On peut faire une analogie avec quelqu'un qui fait la cuisine tranquillement: il peut être interrompu par plusieurs sources: la sonnette de la maison, le téléphone, la minuterie de ses appareils de cuisson, le détecteur de fumée. Il doit traiter l'événement avant de revenir à sa tâche principale. Le traitement de ces évènements peut lui-même être interrompu par un événement jugé plus important. De la même façon, avec un système ordiné, on doit souvent définir des priorités dans les interruptions:  Le traitement d'une interruption peut être interrompu par une interruption qui lui est prioritaire.  Le traitement d'une interruption ne doit pas être interrompu par une interruption de niveau inférieur.  Le traitement d'une interruption ne peut être interrompu par aucune autre. Sources d'interruptions Les interruptions peuvent être causées par des sources externes ou par des sources internes Sources externes:  broches parallèles (Exemples: clavier, alarme)  ports séries Sources internes  Timer  Convertisseur A-N  Reset 19-1 Exemple[PIC]: Interruption avec une source externe: RB0 // Claude Barbaud 24 janvier 2005 //---------------------------------------------------------------- // INT_EXT.C // // Exemple d'utilisation de l'interruption externe. // Chaque fois qu'il y a une interruption on fait // clignoter le led temoin. // la source d'interruption est un front descendant sur RB0 //---------------------------------------------------------------- #include "16F876.H" #fuses HS,NOWDT,PUT,NOPROTECT,NOLVP #use delay(clock=20000000) #use RS232(Baud=19200,Xmit=PIN_C6,Rcv=PIN_C7, bits=8, errors) #define LED PIN_A5 // Led temoin void cligne(int x); // prototype de la fonction cligne() //------------------------------------------------------// // Sous programme de traitement de l'interruption // // externe // //------------------------------------------------------// #int_ext // Cette directive indique que la fonction // suivante est la tache de l'interruption rb_ext( ) // fonction sans parametres { cligne(2); } //-------------------- Programme principal ----------------------- void main(void) { ext_int_edge(H_TO_L); // Front descendant enable_interrupts(INT_EXT); // Valide l'interruption sur RB0 enable_interrupts(GLOBAL); // Valide les interruptions cligne(4); while(1); // ce programme ne fait rien } //---------------------------------------------------// // void cligne(int x) // // // // Clignotement de la led verte x fois a // // intervalle de 200 ms. // //-------------------------------------------------- // void cligne(int x) { int i; for (i=0; i<x; ++i) { output_low(led); delay_ms(80); output_high(led); 19-2 delay_ms(80); } } Source de l'interruption La source de l'interruption est indiquée au début du sous-programme d'interruption par la directive #int_ext . Cette directive identifie RB0 comme source de l'interruption. Autre directive concernant les sources externes: #int_rb changement sur B4-B7 Seules les broches définies en entrée peuvent déclencher une interruption. Ces directives ne discriminent pas quelle entrée est la source, mais on peut utiliser bit_test() Validation de l'interruption L'interruption ne peut être active que si elle est validée enable_interrupts(INT_EXT); // Valide l'interruption sur RB0 enable_interrupts(GLOBAL); // validation globale L'interruption doit être validée individuellement (INT_EXT) et globalement. On peut interdire une interruption par l'instruction disable_interrupt() Les paramètres sont les mêmes: disable_interrupts(INT_EXT); disable_interrupts(GLOBAL);  Gestion des priorités des interruptions Exemple[PIC]: Interruption externe par B4-B7 // Claude Barbaud 24 janvier 2005 //---------------------------------------------------------------- // INT_RB.C // // Exemple d'utilisation de l'interruption externe. // Chaque fois qu'il y a une interruption on fait // clignoter le led temoin. // la source d'interruption est un changement sur B4_B7 //---------------------------------------------------------------- #include "16F876.H" #fuses HS,NOWDT,PUT,NOPROTECT,NOLVP #use delay(clock=20000000) #use RS232(Baud=19200,Xmit=PIN_C6,Rcv=PIN_C7, bits=8, errors) #byte port_b = 6 // adresse du port B #define LED PIN_A5 // Led temoin void cligne(int x); // prototype de la fonction cligne() //------------------------------------------------------// // Sous programme de traitement de l'interruption // // externe // //------------------------------------------------------// 19-3 #int_rb rb_ext( ) { int lecture; disable_interrupts(GLOBAL); // Evite de s'interrompre soi-meme lecture = port_b & 0xF0; // isole les 4 bits d'en haut if(bit_test(lecture, 4)) // on peut tester les bits pour // decider des actions cligne(4); if(bit_test(lecture, 7)) cligne(7); enable_interrupts(GLOBAL); } //-------------------- Programme principal ----------------------- void main(void) { set_tris_b(0xFF); // port_b en entree enable_interrupts(INT_RB); // Valide l'interruption sur B4-B7 enable_interrupts(GLOBAL); // Valide les interruptions cligne(4); while(1); // ce programme ne fait rien } //---------------------------------------------------// // void cligne(int x) // // // // Clignotement de la led verte x fois a // // intervalle de 200 ms. // //-------------------------------------------------- // void cligne(int x) { int i; for (i=0; i<x; ++i) { output_low(led); delay_ms(200); output_high(led); delay_ms(200); } } 19-4 Exemple[PIC]: Interruption de source interne: Timer 1 // Isidore Lauzier 10/3/02 - CCS C //----------------------------------------------------------------// // Timer1.c // // Démonstration de l'utilisation du timer1 // // Le timer est programmé en tranches de 100 ms. On affiche // // l'heure, les minutes et les secondes. // //----------------------------------------------------------------// #include <16F876.H> #device ADC=10 #device PIC16F876 *=16 #fuses HS,NOWDT,PUT,NOPROTECT,NOLVP #use delay(clock=20000000) #use RS232(Baud=19200,Xmit=PIN_C6,Rcv=PIN_C7, bits=8, errors) #bit TMR1IF = 0x0C.0 // Indicateur d'int. du timer1 #define TEMOIN PIN_A5 void cligne(int x); //------------------ Variables globales -------------------------- int ms_100; short sec; //---------------------------------------------------------------- // #int_timer1 // Gestion des interruptions pour le chronométrage avec le // timer1. Il est nécessaire de recharger le compteur à nouveau // à chaque interruption. Il faut ajouter le temps de latence, // soit le contenu du timer1 et le délai causé par la lecture // et le chargement de cette valeur. //---------------------------------------------------------------- #int_timer1 // Cette fonction est appelée à chaque clock_isr1() { // 8 débordements du timer1 (65535->0). long int cycles; setup_timer_1(T1_DISABLED); // Arrêt pour le chargement cycles = get_timer1(); // Temps de latence cycles = cycles + 3038; // (65535-62500)=3035+(25/div8)=3038 set_timer1(cycles); setup_timer_1( T1_INTERNAL | T1_DIV_BY_8 ); // tranche de 100 ms --ms_100; if (!ms_100) { sec=TRUE; ms_100=10; } } //---------------------- Programme principal ---------------------- main() { int i, min; cligne(1); // Témoin 19-5 ms_100=10; i=0; min=0; sec=FALSE; set_timer1(3035); // 65535-62500 = 100 ms avec setup_timer_1( T1_INTERNAL | T1_DIV_BY_8 ); // un cristal de 20 mHz. TMR1IF=0; // Reset de l'indicateur d'int. du timer1 enable_interrupts(int_timer1); enable_interrupts(GLOBAL); do { if (sec) { i++; if (i==60) { i=0; ++min; if (min==60) min=0; } printf("\r%2u:%2u",min,i); sec=FALSE; } } while (TRUE); disable_interrupts(int_timer1); // avec un crystal de 20 mHz. } //---------------------------------------------------// // void cligne(int x) // // // // Clignotement de la led témoin x fois à // // intervalle de 200 ms. // //-------------------------------------------------- // void cligne(int x) { int i; for (i=0;i<x;i++) { output_high(TEMOIN); delay_ms(100); output_low(TEMOIN); delay_ms(100); } } 19-6 Exemple: utilisation des changements sur RB7-RB5 //------------------------------------------------------// // Claude Barbaud 25 janvier 2005 // // Ce programme montre l'utilisation des changements de // // B5 - B7 comme source d'interruption // //------------------------------------------------------// #include <16F876.H> #fuses HS,NOWDT,NOPROTECT #use delay(clock=20000000) #use RS232(Baud=19200,Xmit=PIN_C6,Rcv=PIN_C7, bits=8, errors) #byte port_b = 6 #define in 0xe0; int last_b; // memorisation de l'ancienne valeur du port int cmpt1, cmpt2, cmpt3; //-------sous-programme de traitement de l'interruption--------// #int_rb rb_isr( ) { byte changes; output_low(PIN_B0); delay_ms(100); // anti-rebond changes = port_b & 0xe0; // RB7, RB6, RB5 if (bit_test(changes,5) != bit_test(last_b,5)) cmpt1= cmpt1+1; if (bit_test(changes,6) != bit_test(last_b,6)) cmpt2= cmpt2+1; if (bit_test(changes,7) != bit_test(last_b,7)) cmpt3= cmpt3+1; last_b = changes; printf("\n\rB5 = %u B6 = %u B7 = %u",cmpt1, cmpt2,cmpt3); output_high(PIN_A5); } Main() { set_tris_b(0xe0); cmpt1=cmpt2=cmpt3=0; last_b = port_b & 0xe0; disable_interrupts(GLOBAL); enable_interrupts(RB_CHANGE); // RB_CHANGE = INT_RB enable_interrupts(GLOBAL); for (;;) ; } 19-7 uploads/Geographie/ utilisation-des-interruptions-avec-le-pic 1 .pdf

  • 18
  • 0
  • 0
Afficher les détails des licences
Licence et utilisation
Gratuit pour un usage personnel Attribution requise
Partager