Tutorials - PIC18 by Data Sheet

 

INTERRUPT


Le sorgenti degli interrupt non periferici

Come abbiamo detto più sopra, sono interrupt non-periferici i seguenti :

  • interrupt generati dal cambio sul PORTB

  • interrupt dalle line esterne INT

  • interrupt di Timer0.

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 :

  1. aver assegnato una funzione digitale a PB0 (PBADEN = DIG nella configurazione oppure attraverso ADCON1)

  2. assegnare i port come ingressi

  3. 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 :

  1. stabilire , se richiesto, un livello di priorità con i bit RBIP (il default è high priority)

  2. abilitare l' interrupt con RBIE

  3. 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:
  1. 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.

  2. All' accensione, RBIF assume un valore casuale. Quindi, prima di abilitare l' interrupt relativo, occorre prima resettarlo.

  3. 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.

  4. 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:

 bcf  PORTB,0

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 :

  1. INT0 dipendente dal pin PORTB0

  2. INT1 dipendente dal pin PORTB1

  3. 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 :

  1. aver assegnato una funzione digitale a PB0 ( PBADEN = DIG nella configurazione oppure attraverso ADCON1)

  2. 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 :

  1. selezionando il fronte desiderato con INTEDG0

  2. abilitando l' interrupt con INT0IE

  3. 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:

; initializza 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 edg
e
     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 :

  1. aver assegnato una funzione digitale a PB1/2 ( PBADEN = DIG nella configurazione oppure attraverso ADCON1)

  2. 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 :

  1. selezionando il fronte desiderato con  INTEDG1 - 2

  2. stabilire , se richiesto, un livello di priorità con i bit INT1IP/INT2IP (il default è high priority)

  3. abilitando l' interrupt con INT1IE/INT2IE

  4. 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, INT1/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.