You are on page 1of 7

Utilisation des interruptions avec le PIC

Claude Barbaud

10 janvier 2011

Principe:
Le fonctionnement par interruptions sur un microcontrleur permet celui-ci
d'excuter une tche(programme principal) qui peut tre interrompue par un
vnement. Le processeur doit alors excuter une tche(sous-programme)
associe cette source d'interruption. Quand la tche est excute, le processeur
revient sa tche 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 tlphone,
la minuterie de ses appareils de cuisson, le dtecteur de fume. Il doit traiter
l'vnement avant de revenir sa tche principale. Le traitement de ces
vnements peut lui-mme tre interrompu par un vnement jug plus important.
De la mme faon, avec un systme ordin, on doit souvent dfinir des priorits
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 infrieur.
Le traitement d'une interruption ne peut tre interrompu par aucune autre.

Sources d'interruptions
Les interruptions peuvent tre causes par des sources externes ou par des sources
internes
Sources externes:
broches parallles (Exemples: clavier, alarme)
ports sries
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 indique au dbut 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 dfinies en entre peuvent dclencher une interruption. Ces directives
ne discriminent pas quelle entre est la source, mais on peut utiliser bit_test()
Validation de l'interruption
L'interruption ne peut tre active que si elle est valide
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);

// Valide l'interruption sur RB0


// validation globale

L'interruption doit tre valide individuellement (INT_EXT) et globalement.


On peut interdire une interruption par l'instruction disable_interrupt() Les paramtres sont
les mmes:
disable_interrupts(INT_EXT);
disable_interrupts(GLOBAL);

Gestion des priorits 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
void main(void)
{
set_tris_b(0xFF);
//
enable_interrupts(INT_RB); //
enable_interrupts(GLOBAL); //
cligne(4);
}

while(1);

principal ----------------------port_b en entree


Valide l'interruption sur B4-B7
Valide les interruptions

// 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
//
//
Dmonstration 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 chronomtrage avec le
// timer1. Il est ncessaire de recharger le compteur nouveau
// chaque interruption. Il faut ajouter le temps de latence,
// soit le contenu du timer1 et le dlai caus par la lecture
// et le chargement de cette valeur.
//---------------------------------------------------------------#int_timer1
// Cette fonction est appele chaque
clock_isr1() {
// 8 dbordements du timer1 (65535->0).
long int cycles;
setup_timer_1(T1_DISABLED); // Arrt 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);

// Tmoin

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 tmoin 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 =
#define in 0xe0;
int
int

last_b;
// memorisation de l'ancienne valeur du port
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

You might also like