Schematicamente :
IPEN
|
INTCON<7>
|
INTCON<6>
|
Logica operativa
|
IPEN = 0
|
GIE
|
PEIE
|
Nessuna priorità
Differenziazione interrupt periferici e non
|
IPEN = 1
|
GIEH
|
GIEL
|
Doppia priorità
Differenziazione tra interrupt a priorità alta e bassa
|
Nel caso di una
sorgente periferica, ovvero i cui bit di controllo si trovano nei registri
PIE/PIR :
-
il bit IPEN
in RCON va programmato a 0 se non è desiderata la priorità e a 1 per
la doppia priorità
-
se è stata
scelta la doppia priorità, il bit xxxIP relativo alla sorgente
dovrà essere programmato per assegnare il livello voluto. Altrimenti
questo non occorre
-
il bit xxxIE
nel registro ICONn relativo alla sorgente di interrupt interessata va
settato
-
il bit xxxIF
va azzerato per evitare una chiamata di interrupt inaspettata
-
Trattandosi di sorgenti periferiche, alla loro
abilitazione si aggiunge un ulteriore bit PEIE che andrà settato.
Questo bit è disponibile solo nella modalità senza priorità. Se non
viene settato, la chiamata di interrupt dalla periferica resta inattiva
anche se è stato abilitato il bit globale GIE.
-
se esiste un
solo livello di interrupt il bit GIE di INTCON abiliterà (o
disabiliterà) globalmente tutti gli interrupt attivati, che non avranno
effetto fino a che questo bit resta a 0. Se esistono due livelli, il bit
GIE diventa GIEH e , attenzione, il bit PEIE diventa GIEL. In sostanza
nel modo a due priorità non esiste più una abilitazione
specifica per le sorgenti periferiche, ma solo una suddivisione in alta
e bassa priorità.
Esiste quindi una
importante differenza tra la logica di "compatibilità" con i
mid-range e quella propria dei PIC18 con priorità a livelli :
-
la prima vede
le sorgenti di interrupt divise tra periferiche (sotto l' azione di PEIE)
e non periferiche (sotto l' azione di GIE) ed entrambe dipendenti da
GIE.
-
la seconda,
pura mantenendo una struttura di registri simile, non distingue più le
sorgenti tra periferiche e non, ma solo tra assegnate alla alta o alla
bassa priorità. Anche qui, però, la funzionalità di GIEL dipende da
GIEH
Nota:
Una nota riguarda gli Errata del costruttore (che
è sempre necessario leggere prima di utilizzare il componente, in
quanto possono riservare sorprese non indifferenti).
Nel caso di GIE, per alcuni PIC è necessario attivare
prima GIEH e poi GIEL e disattivarli nell' ordine inverso, pena il
mancato funzionamento dell' operazione.
|
Una soluzione semplice ed efficiente al problema sopra
indicato è quella di creare un paio di macro che svolgano queste due
istruzioni in modo adeguato al PIC. Ad esempio:
STARTINT
macro
; abilita interrupt globale
bsf INTCON,GIEH
bsf INTCON,GIEL
endm
STOPINT
macro
; disabilita interrupt globale
bcf INTCON,GIEL
bcf INTCON,GIEH
endm |
A riguardo delle
priorità va detto che, attivare la modalità per poi assegnare tutte le
richieste alla priorità superiore non è sensato. Lo scopo delle priorità
è quello di fare operare periferiche in interrupt invece che in polling in
un insieme dove il tempo di esecuzione di alcune funzioni è drasticamente
più importante che per altre. Quindi l' uso della priorità sarà riservato
alle applicazione che ne necessitano realmente.
Un
esempio
Esempio 1 - Vogliamo
attivare gli interrupt esterni sui pin di PORTB, con INT1 ad alta priorità
e INT2 a bassa priorità.
-
IPEN = 1 in RCON per abilitare le
priorità
-
INT1IP = 1 in INTCON3 per avere l' alta
priorità
-
selezionare il fronte di trigger per INT1
con INTEDG1 del registro INTCON2
-
INT2IP = 0 in INTCON3 per avere la bassa
priorità
-
selezionare il fronte di trigger per INT2
con INTEDG2 del registro INTCON3
-
abilitare l' interrupt di INT1 con il bit
INT1IE = 1 in INTCON3
-
abilitare l' interrupt di INT2 con il bit
INT2IE = 1 in INTCON3
-
portare GIEH =1 (abilitazione alta
priorità)
-
portare GIEL =1 (abilitazione bassa
priorità)
Il che origina le seguenti istruzioni:
bsf
RCON, IPEN ; enable
priority
bsf INTCON3, INT1IP ; hp to INT1
bsf INTCON2, INTEDG1 ; select rising edge
bcf INTCON3, INT2IP ; lp to INT2
bcf INTCON2, INTEDG2 ; select falling edge
bsf INTCON3, INT1IE ; enable INT1
bsf INTCON3, INT2IE ; enable INT2
bcf INTCON3, INT1IF ; clear flag INT1
bcf INTCON3, INT2IF ; clear flag INT2
bsf INTCON, GIEH ;
enable global hp
bsf INTCON, GIEL ;
ebnable lp
|
A questo punti i
livelli di trigger scelti, quando presenti sui pin, attiveranno i relativi
interrupt.
Ovviamente sarà
necessario che il programma disponga dell' entry ad alta priorità all'
indirizzo 0008h e di quello a bassa priorità a 0018h, dei necessari
salvataggi delle variabili ambientali e , da non dimenticare, la
cancellazione dei flag prima di rientrare al flusso normale del
programma.
Il clear dei flag
realtivi alle sorgenti di interrupt è prassi necessaria prima dell'
abilitazione dell' interrupt in quanto questi flag potrebbero essere settati
da eventi precedenti e quindi generare un immediata chiamata di interrupt
non richiesta.
Esempio 2 - Volendo
attivare gli interrupt esterni sui pin di PORTB, con INT1 e INT2 , ma senza
gestione della priorità :
-
IPEN = 0 in RCON per disabilitare le
priorità (lo è già al reset)
-
Selezionare il fronte di trigger per INT1
con INTEDG1 del registro INTCON2
-
Selezionare il fronte di trigger per INT2
con INTEDG2 del registro INTCON3
-
Abilitare l' interrupt di INT1 con il bit
INT1IE = 1 in INTCON3
-
Abilitare l' interrupt di INT2 con il bit
INT2IE = 1 in INTCON3
-
Portare GIEH =1 (abilitazione globale)
Il che origina le seguenti istruzioni:
bcf
RCON, IPEN ; disable
priority
bsf INTCON2, INTEDG1 ; select rising edge
bcf INTCON2, INTEDG2 ; select falling edge
bsf INTCON3, INT1IE ; enable INT1
bsf INTCON3, INT2IE ; enable INT2
bcf INTCON3, INT1IF ; clear flag INT1
bcf INTCON3, INT2IF ; clear flag INT2
bsf INTCON, GIE
; enable global
|
Non occorre
toccare il bit PEIE in quanto non si tratta di interrupt periferici.
Come sopra, il flag
identificatore relativo all' interrupt chiamante va resettato via software
onde evitare chiamate inaspettate.
Inoltre, una volta servito l' interrupt , è tassativo ricordarsi di
resttare il flag.
Nota:
Si deve
ricordare che i flag IF vanno a 1 anche se il relativo
interrupt non è abilitato : basta si sia verificato l' evento ad
essi collegato.
Pertanto possono essere utilizzati per una
gestione in polling , ricordando sempre di azzerarli una volta
usati.
|