Le sorgenti degli interrupt non
periferici
Come abbiamo detto più sopra, sono interrupt non-periferici
i seguenti :
Vediamone maggiori dettagli.
PORTB change
Questa sorgente di interrupt riguarda i PORTB<7:4>: un cambio di stato su uno qualsiasi
diquesti pin attiva la chiamata
all' interrupt.
Va ben compreso che, abilitando questo interrupt, si abilitano
contemporaneamente tutti e 4 i pin del PORTB contemporaneamente e, se necessario, la
discriminazione del pin su cui è avvenuta la variazione deve essere
effettuata da programma.
In linea di massima, questa funzione è molto adatta alla
lettura di matrici di contatti, come quelli di una tastiera, con la
possibilità di mandare il processore in sleep e risvegliarlo solo al
momento della pressione di un tasto che modifica il livello di uno dei bit
del port.
Non esiste la possibilità di programmare la variazione di stato che
genera la chiamata interrupt: semplicemente il meccanismo compara lo stato
del port con l' ultimo letto in precedenza e se ci sono differenze, attiva
la chiamata interrupt. Quindi va considerato che sia il cambio dello
stato del pin H->L sia L->H sono entrambi eventi validi.
Questo, assieme al problema dei rimbalzi, va tenuto presente se si tratta di
interfacciare tastiere o comunque contatti meccanici.
I registri associati all' uso di PORTB Change sono i
seguenti :
Nome
|
bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
PORTB
|
RB7
|
RB6
|
RB5
|
RB4
|
|
|
|
|
INTCON
|
|
|
|
|
RBIE
|
|
|
RBIF
|
INTCON2
|
|
|
|
|
|
|
|
RBIP
|
Un cambio di stato sui pin
porta a livello 1 il flag RBIF
(INTCON<0>).
L' interrupt è abilitato dal bit RBIE
(INTCON<3>).
La priorità è scelta con RBIP
( INTCON2<0>).
Per utilizzare il PORTB Change occorre preliminarmente :
-
aver assegnato una funzione digitale a PB0 (PBADEN
= DIG nella configurazione oppure attraverso ADCON1)
-
assegnare i port come ingressi
-
aver assegnato PORTB<7:4>
come ingresso, settando i corrispondenti bit di TRISB
I pin dichiarati uscita sono esclusi dalla funzione PORTB
Change.
Lo sono anche i bit 7 e 6 se si stanno utilizzando per l' ICD (in Circuit
Debug), dato che
la funzione di debug sovrapassa ogni altra assegnazione.
Nel momento in cui si rilascia questa funzione attraverso il CONFIG, i pin
riassumono la loro funzione di PORTB, assieme all' eventuale PORTB Change
impostato. Quindi è possibile debuggare il programma e rilasciarne poi la
release finale senza modifiche.
In ogni
caso, abilitando questo interrupt, la funzione generica di pin di ingresso
digitale è sempre presente; quindi sarà possibile in qualunque momento
leggere lo stato di PORTB<7:4>.
La funzione di interrupt alla variazione del livello viene
attivata con le seguenti operazioni :
-
stabilire , se richiesto, un livello di priorità con i
bit RBIP (il default
è high priority)
-
abilitare l' interrupt con RBIE
-
avendo predisposto al vettore 0x008 per l' alta
priorità ( o per gestione senza priorità) o al vettore 0x018 per la
bassa priorità, una opportuna routine di gestione dell' evento
Ovviamente occorrerà che il bit GIE
(GIEH) sia abilitato per
rendere operativa la chiamata di interrupt.
Avvenuto l' evento, il flag RBIF
sarà a 1 ; va tassativamente ricordato che il flag deve essere
obbligatoriamente azzerato dal programma per evitare una immediata e non
richiesta chiamata di interrupt all' uscita della precedente e che l'
azzeramento si ottiene dopo la lettura del PORTB.
Se RBIE o GIE
(GIEH-L) non sono
abilitati, non avviene la chiamata al vettore di interrupt, ma il flag RBIF
viene comunque posto a 1 quando si verifica l' evento impostato. Pertanto,
se necessario, il flag può anche essere verificato in polling (sempre
ricordando la necessità del suo azzeramento).
Per riassumere, PORTB Change viene gestito da:
Bit di abilitazione
|
INTCON, RBIE
|
Bit di flag
|
INTCON, RBIIF
|
Bit di priorità
|
INTCON2, RBIP
|
E, in pratica, la procedura corretta per la cancellazione del
flag richiede le seguenti istruzioni:
MOVF
PORTB, W ; read PORTB to
clear
BCF INTCON, RBIF ; clear flag |
NOTE:
-
Prima di resettare il flag RBIF occorre aver letto
almeno una volta il PORTB. Senza questa precauzione il flag sarà
riposizionato a 1 immediatamente, bloccando in loop l' interrupt.
-
All' accensione, RBIF assume un valore casuale.
Quindi, prima di abilitare l' interrupt relativo, occorre prima resettarlo.
-
Come detto all' inizio, va considerato che questo
interrupt agisce sul cambio di livello dei pin del PORTB<7:4>
indifferentemente da quale pin si tratti e da quale cambio di
livello (alto-basso o viceversa), dato che la direzione e il pin dell'
evento non sono filtrabili.
In tal senso è opportuno considerare anche la qualità del segnale
applicato : soprattutto nel caso di segnali provenienti da contatti
meccanici, ricchi di rimbalzi, occorrerà una accurata valutazione per
evitare falsi trigger e chiamate di interrupt inaspettate. L'
indispensabile scelta tra un debounce via software o un pre trattamento
hardware del segnale o entrambi è lasciato al giudizio del progettista.
-
Nel caso di sviluppo con sistemi tipo ICD, PicKit, Real
ICE e simili, che utilizzano PB<7:6> (ICSP), la funzione PORTB
Change è comunque debuggabile, limitatamente a PORTB<5:4> in
quanto gli altri due bit saranno usati per la connessione col debugger ;
questa, infatti, avviene senza influire sulla funzione del PORTB change
per i bit non impegnati
|
La necessità della lettura intenzionale di PORTB
per cancellare il flag di interrupt deriva da alcune considerazioni.
Innanzitutto serve una lettura per avere una base con cui
effettuare una comparazione della variazione futura e da questa viene
fatto dipendere l' azzeramento del flag, che, altrimenti, resta a 1.
In secondo luogo, una volta che RBIF sia settato, è possibile che
il primo passo per la sua cancellazione sia effettuato non
intenzionalmente da una qualsiasi istruzione che acceda a PORTB, anche su
altri bit non interessati al PORTB Change, ad esempio:
Però questo, da solo, non cancella RBIF, che può
essere testato e poi cancellato direttamente.
Quindi, ad esempio, in una gestione in polling, la routine lavora
correttamente.
Però un problema si presenta se una variazione sui pin
avviene nel momento in cui una istruzione accede alla porta. In tal caso è
possibile che RBIF non venga settato.
Questo può essere causa del mancato funzionamento pseudo-casuale del
PORTB Change, crenado situazioni molto difficili da debuggare.
Per evitare questo, una prima soluzione è quella di non utilizzare il
PORTB per altre funzioni, durante la gestione del PORTB Change, in modo da
evitare accessi che potrebbero creare il problema.
Un' altra alternativa è quella di utilizzare il PORTB Change con il
processore in sleep: in tal caso non c'è possibilità di accessi al
PORTB stesso, dato che la CPU è arrestata.
Per evitare di trovarsi in situazioni da cui non è semplice uscire in
fase di debug, prima di utilizzare questa funzione è utile consultare
le AN556 e AN552 di Microchip che analizzano il problema.
External interruput INTn : INT0,
INT1, INT2
In aggiunta al cambio di stato sul PORTB,
i PIC18F introducono un gruppo di interrupt, chiamati Extrenal Interrupt,
analoghi alla funzione di PORTB0-INT
dei mid range. Sono sempre concentrati sul PORTB,
ma hanno alcune differenze essenziali :
-
sono relativi a singoli pin e non ad un gruppo di 4
-
i pin sono abilitabili singolarmente
-
sono attivati non dallo stato, ma dal fronte di salita o di discesa del
segnale applicato.
-
il fronte è programmabile
Queste caratteristiche rendono molto ampie le possibilità
di impiego di queste sorgenti di interrupt.
Nella famiglia 18F432x sono disponibili 3 ingressi per l'
external interrupt :
-
INT0
dipendente dal pin PORTB0
-
INT1
dipendente dal pin PORTB1
-
INT2
dipendente dal pin PORTB2
Tutti e tre i pin sono indipendenti, sia come abilitazione
all' interrupt, sia come scelta del fronte da discriminare.
I registri associati sono i seguenti :
Nome
|
bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
PORTB
|
|
|
|
|
|
RB2
|
RB1
|
RB0
|
INTCON
|
|
|
|
INT0IE
|
|
|
INT0IF
|
|
INTCON2
|
|
INTEDG0
|
INTEDG1
|
INTEDG1
|
|
|
|
|
INTCON3
|
INT2IP
|
INT1IP
|
|
INT2IE
|
INT1IE
|
|
INT2IF
|
INT1IF
|
|
Per tutti e tre gli ingressi l' interrupt è dipendente dal
fronte del segnale applicato,
ovvero è sensibile non al livello logico del pin, ma alla sua
variazione.
E'
possibile la scelta tra il fronte di salita (rising
edge) e quello di
discesa (falling edge), attraverso i bit
INTEDGx.
Data questa
condizione, occorre verificare la qualità del segnale applicato,
principalmente se generato da contatti meccanici, in modo che
eventuali rimbalzi non siano interpretati erroneamente dal
programma.
Quindi occorrerà
valutare se applicare un filtro di debounce hardware o software. |
Per tutti gli ingressi esiste un bit di abilitazione dell' interrupt (INTxIE)
e un bit di flag (INTxIF).
Va notato che INT1 e INT2 sono anche programmabili come interrupt ad alta o
bassa priorità, avendo a disposizione un bit di selezione INTxIP, mentre
INT0 è sempre ad alta priorità.
Per poter essere utilizzati come interrupt, i pin vanno
configurati come ingressi digitali. I pin configurati come uscite sono
esclusi da questa funzione.
INT0
I bit e registri interessati sono i seguenti :
Nome
|
bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
PORTB
|
|
|
|
|
|
|
|
RB0
|
INTCON
|
|
|
|
INT0IE
|
|
|
INT0IF
|
|
INTCON2
|
|
INTEDG0
|
|
|
|
|
|
|
Il bit INTEDG0
(INTCON2<6>)
stabilisce il fronte del segnale applicato come segue :
INTEDG0
= 1 fronte di salita - rising edge
INTEDG0
= 0 fronte di discesa - falling edge
L' interrupt è abilitato settando il bit INT0IE
(INTCON<4>).
Susseguentemente all' evento selezionato, il flag INT0IF
(INTCON1<1>) viene
settato e attivata la chiamata del vettore di interrupt.
Il flag deve essere azzerato da programma.
Non esiste un bit di assegnazione della priorità per
INT0, che è
sempre considerato interrupt ad alta priorità (nel caso di impiego della
priorità).
Per utilizzare INT0 occorre preliminarmente :
-
aver assegnato una funzione digitale a PB0 ( PBADEN
= DIG nella configurazione oppure attraverso ADCON1)
-
aver assegnato PB0 come ingresso, settando il bit 0 di
TRISB
PB0 assegnato alla funzione INT0 non può ovviamente essere
utilizzato per altre funzioni. In ogni caso, abilitando INT0, la funzione
generica di pin di ingresso digitale è sempre presente; quindi sarà
possibile in qualunque momento leggere lo stato di PB0.
La funzione di interrupt alla variazione del livello viene
abilitata :
-
selezionando il fronte desiderato con INTEDG0
-
abilitando l' interrupt con INT0IE
-
avendo predisposto al vettore 0x008 una opportuna
routine di gestione dell' evento
Ovviamente occorrerà che il bit GIE
(GIEH) sia abilitato per
rendere operativa la chiamata di interrupt.
Avvenuto l' evento, il flag INT0IF
sarà a 1 ; va tassativamente ricordato che il flag deve essere
obbligatoriamente azzerato dal programma per evitare una immediata e non
richiesta chiamata di interrupt all' uscita della precedente.
Se INT0IE o GIE
(GIEH) non sono
abilitati, non avviene la chiamata al vettore di interrupt, ma il flag
INT0IF viene comunque posto a 1 quando si verifica l' evento impostato.
Pertanto, se necessario, il flag può anche essere verificato in polling
(sempre ricordando la necessità del suo azzeramento).
Per riassumere, INT0 viene gestito da:
Bit di abilitazione |
INTCON,
INT0IE |
Bit di flag |
INTCON, INT0IF |
Bit di selezione del fronte |
INTCON2, INTEDG0 |
Bit di priorità |
nessuno (sempre a priorità alta) |
Un esempio di codice:
; initializ za
INT0
movlw
0x07
; PB3:0 digitali
movwf
ADCON1
; se non
PBADEN = DIG
bsf TRISB,
0 ; PB0 come
input
bcf INTCON,INT0IF
; clear flag per
sicurezza
bcf
INTCON2,INTEDG0 ; falling edge
bsf INTCON,INT0IE
; abilita
INT0
; initialize other interrupts
bsf INTCON, GIE
; abilita
global interrupt
; Reset vector (no priority)
ORG
08
higp bra IRQ
; Reset vector (no priority)
ORG 0x18
lowp bra lowp
; trappola
IRQ btfss INTCON, INT0IF ;
chiamata da INT0 ?
bra
irq1
; no - analizza altri interrupt
; si - interrupt management
.....
bcf INTCON,
INT0IF ; clear flag
irq1:
; analizza altri interrupt
.....
retfie FAST
; ritorno con restore dei registri
|
INT1 / INT2
I bit ed i registri interessati sono i seguenti :
Nome
|
bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
PORTB
|
|
|
|
|
|
RB2
|
RB1
|
|
INTCON2
|
|
|
INTEDG1
|
INTEDG1
|
|
|
|
|
INTCON3
|
INT2IP
|
INT1IP
|
|
INT2IE
|
INT1IE
|
|
INT2IF
|
INT1IF
|
Il bit INTEDG1
(INTCON2<5>) e INTEDG2
(INTCON2<4>)
stabilisce il fronte del segnale applicato come segue :
INTEDG1
- 2 = 1
fronte di salita - rising edge
INTEDG1
- 2 = 0
fronte di discesa - falling edge
L' interrupt è abilitato settando il bit INT1IE
(INTCON3<3>) e INT2IE
(INTCON3<4>).
Susseguentemente all' evento selezionato, il flag INT1IF
(INTCON3<0>) e INT2IF
(INTCON3<1>)
vengono settati e viene attivata la chiamata del vettore di interrupt.
I flag devono essere azzerati da programma.
Contrariamente a INT0, la chiamata di interrupt di INT1 e
INT2 è impostabile come priorità, attraverso i bit INT1P
e INT2P (INTCON3<7:6>)
nel seguente modo :
INT1P
- INT2P =
1 high priority
INT1P
- INT2P =
0 low priority
Il default al POR è 1.
Per utilizzare INT1/2 occorre preliminarmente :
-
aver assegnato una funzione digitale a PB1/2 ( PBADEN
= DIG nella configurazione oppure attraverso ADCON1)
-
aver assegnato PB1/2 come ingresso, settando il
corrispondente bit di TRISB
PB1 e/o PB2, assegnati alla funzione INT1/2, non possono
ovviamente essere utilizzati per altre funzioni. In ogni caso, abilitando
INT1/2, la funzione generica di pin di ingresso digitale è sempre presente;
quindi sarà possibile in qualunque momento leggere lo stato di PB1/2.
La funzione di interrupt alla variazione del livello viene
abilitata :
-
selezionando il fronte desiderato con INTEDG1
- 2
-
stabilire , se richiesto, un livello di priorità con i
bit INT1IP/INT2IP
(il default è high priority)
-
abilitando l' interrupt con INT1IE/INT2IE
-
avendo predisposto al vettore 0x008 per l' alta
priorità ( o per gestione senza priorità) o al vettore 0x018 per la
bassa priorità, una opportuna routine di gestione dell' evento
Ovviamente occorrerà che il bit GIE
(GIEH per l' alta
priorità e GIEH / GIEL
per la bassa priorità) sia abilitato per rendere operativa la chiamata di
interrupt. Inoltre, se è scelta una gestione a priorità occorre che il
relativo bit di configurazione IPEN
sia abilitato.
Avvenuto l' evento, il flag INT1IF /
INT2IF sarà a 1 ; va
tassativamente ricordato che il flag deve essere obbligatoriamente azzerato
dal programma per evitare una immediata e non richiesta chiamata di
interrupt all' uscita della precedente.
Per riassumere, INT 1/2
sono
gestiti
da:
Bit di abilitazione |
INTCON, INT1IE
/INT2IE |
Bit di flag |
INTCON, INT1IF
/INT2IF |
Bit di selezione del fronte |
INTCON2, INTEDG1
/INTEDG2 |
Bit di priorità |
INTCON3, INT1IP /INT2IP |
Se INTxIE o GIE
(GIEH / GIEL)
non sono abilitati, non avviene la chiamata al vettore di interrupt, ma il
flag INTxIF viene
comunque posto a 1 quando si verifica l' evento impostato. Pertanto, se
necessario, il flag può anche essere verificato in polling (sempre
ricordando la necessità del suo azzeramento).
NOTA:
Come
per tutti i segnali provenienti dall' esterno, anche quelli applicati
ai pin PBO,1 e
2 per generare interrupt sul fronte, devono essere adeguati alla
funzione.
Ad esempio, nel caso di segnali provenienti da contatti meccanici, e
quindi ricchi di rimbalzi, occorrerà una accurata valutazione della
qualità di questi segnali allo scopo di evitare falsi trigger. L'
indispensabile debounce, anche con
un pre trattamento hardware del segnale,
è lasciato al giudizio del progettista. |
Timer0
I registri collegati all' uso dell' interrupt di TMR0 sono i
seguenti :
Nome
|
bit 7
|
bit 6
|
bit 5
|
bit 4
|
bit 3
|
bit 2
|
bit 1
|
bit 0
|
INTCON
|
|
|
TMR0IE
|
|
|
TMR0IF
|
|
|
INTCON2
|
|
|
TMR0IP
|
|
|
|
|
|
TRISA
|
|
|
|
|
|
|
|
|
In modalità a 8 bit (default al reset), il Timer0 va in
overflow al passaggio FFh -> 00h del suo registro di conteggio. Questo
porta a livello 1 il bit TMR0IF.
Nel modo a 16 bit l' overflow è al passaggio FFFFh -> 0000h della coppia
di registri TMR0H:L
L' interrupt viene disabilitato o abilitato dal bit TMR0IE
(INTCON<5>); il livello di priorità è controllato dal bit
TMR0IP (INTCON2<5>). L' avvenuto overflow è segnalato dal flag
TMR0IF (INTCON<2>).
Maggiori dettagli sono riportati nel capitolo riguardante
Timer0
NOTA:
Come
per tutti i segnali provenienti dall' esterno, anche quelli
applicati all' ingresso del Timer0 utilizzato come contatore, devono
essere adeguati alla funzione. Ad esempio, nel caso di segnali
provenienti da contatti meccanici, e quindi ricchi di rimbalzi,
occorrerà una accurata valutazione della qualità di questi segnali
allo scopo di evitare falsi trigger e conteggi non
appropriati.
Non essendo possibile un debounce via software del segnale di
ingresso del timer/counter, occorrerà un adeguato pre trattamento
hardware del segnale. |
|
|
Copyright © afg. Tutti i diritti riservati.
Aggiornato il 09/12/10.
|