Utilisation Des Interruptions Avec Le PIC
Utilisation Des Interruptions Avec Le PIC
Utilisation Des Interruptions Avec Le PIC
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)
//---------------------------------------------------//
// 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.
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
On peut interdire une interruption par l'instruction disable_interrupt() Les paramètres sont
les mêmes:
disable_interrupts(INT_EXT);
disable_interrupts(GLOBAL);
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);
}
//---------------------------------------------------//
// 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)
//----------------------------------------------------------------
// #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;
}
}
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);
//---------------------------------------------------//
// 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)
#byte port_b = 6
#define in 0xe0;
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