Salta la barra di navigazione [1] - Vai alla barra di navigazione [3] - Scrivimi una mail [4]

PIC18: interruzioni con priorità in assembly

Assembly PIC18 - PIC18 in C - Sommario - Novità - Tutorial - Progetti - Risorse - Non solo elettronica

In fase di sviluppo Stesura preliminare In fase di sviluppo

In questa pagina verrà mostrato come gestire in assembly le interruzioni con priorità del PIC18 generate da sorgenti esterne, quale un semplice interruttore. Qui una breve descrizione del concetto di interruzione.

Al solito, è vivamente consigliata la lettura in parallelo della spiegazione semplificata qui riportata e della la spiegazione "ufficiale" presente nei fogli tecnici.

Il PIC18 prevede due distinte modalità di uso delle interruzioni:

L'hardware di riferimento è il PICdemo oppure il PICdemo R2 anche se il circuito è realizzabile senza alcun problema direttamente su breadboard. In particolare vengono utilizzati:

Priority mode

Quando le interruzioni del PIC18 sono configurate in Priority mode è possibile definire due classi di priorità:

La differenza essenziale tra le due è che le seconde possono interrompere l'esecuzione delle prime, ma non viceversa.(nota 1).

La priorità delle interruzioni generate da una specifica periferica è in genere programmabile, a seconda delle esigenze.

A fondo pagina trovate il codice che utilizza un interrupt ad alta priorità ed uno a bassa priorità. In particolare:

Per la gestione vengono utilizzati diversi flag, distribuiti su vari registri:

Inizializzazione

Il codice di inizializzazione delle porte è sostanzialmente identico all'esempio relativo alla modalità compatibile, con la sola aggiunta della configurazione di INT1 come ingresso con pull-up:

 clrf TRISC ; PORTC come uscita, tutti gli 8 pin
 movlw 0x01 ; LED0 acceso; LED1-7 spenti
 movwf LATC

 movlw 0xFF ; PORTB come ingresso, tutti gli 8 pin
 movwf TRISB
 bsf WPUB, INT0 ; abilita il pull-up interno su INT0
 bsf WPUB, INT1 ; abilita il pull-up interno su INT1
 bcf INTCON2, RBPU ; Pull-up attivo su tutti i pin abilitati

Occorre quindi procedere alla configurazioni delle interruzioni, impostando:

Il codice corrispondente:

 bsf RCON, IPEN ; Abilito le interruzioni a livelli di priorità
 bsf INTCON, INT0IE ; Abilito INT0 a generare interruzioni (ad alta priorità)
 bcf INTCON3, INT1IP ; Imposto INT1 a bassa priorità
 bsf INTCON3, INT1IE ; Abilito INT1 a generare interruzioni
 bsf INTCON, GIEH ; Abilito la CPU a ricevere interruzioni ad alta priorità
 bsf INTCON, GIEL ; Abilito la CPU a ricevere interruzioni a bassa priorità

Superloop

Dopo le configurazioni iniziali, il processore inizia un ciclo infinito dove non vene fatto assolutamente nulla di significativo. In particolare il codice NON legge il valore dell'interruttore e NON imposta l'accensione dei LED.

repeat
  nop ; non fa nulla (No OPeration), per sempre
  nop
  bra repeat

ISR ad alta priorità

Questa ISR è il codice che viene eseguito quando l'hardware rileva la generazione di un interrupt ad alta priorità. La descrizione è identica a quanto già scritto a proposito delle interruzioni senza priorità, a cui si rimanda. In particolare non cambia l'indirizzo in cui il codice deve essere memorizzato (0x0008) e la modalità di salvataggio e recupero dei registri nei registri shadow.

Il codice:

ISR_Alta CODE 0x0008 ; Vettore per ISR ad alta priorità
 goto AltaPriorita ; Salta all'inizi della ISR ad alta priorità

Interruzioni CODE ; Codice per la gestione delle interruzioni
AltaPriorita
 btfsc INTCON, INT0IF ; Interruzione causata da INT0 ?
 bra GestioneINT0 ; Esegue il codice corrispondente

 retfie FAST ; Nessuna fleg settato... Indizio di un errore?

GestioneINT0
 rlncf LATC ; "Ruota" i LED
 bcf INTCON, INT0IF ; Azzera il flag che segnala INT0
 retfie FAST ; Torna ad eseguire il codice principale

L'unica cosa che è bene mettere in evidenza è che questo codice non può essere mai interrotto.

ISR a bassa priorità

Due sono le differenze fondamentali rispetto alla ISR ad alta priorità:

Il codice:

ISR_Bassa CODE 0x0018 ; Vettore per ISR a bassa priorità
 goto BassaPriorita ; Salta all'inizi della ISR bassa priorità

BassaPriorita
 movff WREG, WREG_TEMP ; salva il registro W nella variabile "temporanea"
 movff STATUS, STATUS_TEMP ; salva i flag nella variabile "temporanea"
 movff BSR, BSR_TEMP ; salva il registro BSR nella variabile "temporanea"

 btfsc INTCON3, INT1IF ; Interruzione causata da INT1 ?
 bra GestioneINT1 ; Esegue il codice corrispondente

 bra Ritorna ; Nessuna fleg settato... Indizio di un errore?

GestioneINT1
 bcf INTCON3, INT1IF ; Azzera il flag che segnala INT1
 movlw 0x01 ; LED0 acceso; LED1-7 spenti (situazione iniziale)
 movwf LATC
 bra Ritorna

Ritorna
 movff STATUS_TEMP, STATUS ; ripristina i flags
 movff WREG_TEMP, WREG ; ripristina il registro W
 movff BSR_TEMP, BSR ; ripristina il registro BSR
retfie

Il codice

Esercizi e quesiti

  1. Per quale motivo i vettori di reset e delle interrupt sono costituiti da un semplice salto e non dal codice principale vero e proprio?

Not

  1. In genere si preferisce impedire ad una ISR di interrompere una ISR della stessa priorità, anche se con un po' di attenzione nel salvataggio dei registri e rinunciando a qualche ottimizzazione nelle prestazioni, la cosa non è impossibile (pre-emptive interrupt).
  2. INT0 genera sempre interruzioni ad alta priorità
  3. Per questo motivo viene usata l'istruzione retfie senza l'argomento FAST

Ultima modifica di questa pagina: 21 maggio 2016 - Una pagina simile: Le interruzioni nel PIC18 (in C)


Assembly PIC18

Licenza Creative Commons Attribuzione 4.0 Internazionale


EN - Pagina principale - Sommario - Accessibilità - Note legali e privacy policy - Posta elettronica

XHTML 1.0 Strict - CSS 3