Cosa siano e come si usano gli interrupt lo abbiamo già visto nella lezione di settorezero sul timer, e maggiori approfondimenti che riguardano gli interrupt a due livelli tipici dei PIC18 li possiamo trovare in quest’altra lezione.
Tuttavia la sintassi con cui si usano gli interrupt nell’SDCC non è documentata molto chiaramente, e per evitarvi di perdere tempo ve la spiego con un esempio:
int flagportaB = 0; //variabile che useremo per verificare se è successo qualcosa sulla porta B nei pin 4 - 7 int flagtimer = 0; //variabile che useremo per verificare se il timer è arrivato a 0 void pippo() interrupt 1 { if (INTCONbits.RBIF == 1) { flagportaB = 1; INTCONbits.RBIF = 0; } if( INTCONbits.TMR0IF == 1 ){ flagtimer = 1; INTCONbits.TMR0IF=0; } }
Come potete vedere occorre creare una funzione, non importa quale nome abbia, purchè dopo il nome ci sia scritta la parola “interrupt” seguita dal numero 1 o 2, nel caso dei PIC18, che indicano il livello di priorità degli interrupt. Il valore 1 indica la massima precedenza.
La funzione di gestione degli interrupt deve avere alcune caratteristiche importanti:
- non accetta parametri in ingresso e non restituisce nulla in uscita. L’unico modo per farla comunicare con il programma principale è usare delle variabili globali che possono essere modificate dalla funzione e poi lette nel programma principale
- deve essere brevissima
- deve resettare gli indicatori di interrupt per poterli intercettare altre volte
Detto questo, vediamo come si scrive il main():
void main() { long int i; TRISB = 0b11110000; TRISD = 0b00000000; PORTB = 0; LATD = 0; PORTD=7; INTCONbits.RBIE=1; //abilita gli interrupt sulla portB 4 - 7 //RCONbits.IPEN = 0; //funziona anche con lo 0, serve per usare 1 o 2 livelli di interrupt INTCONbits.GIE=1; Abilita gli interrupt while (1) { if (flagtimer==1) { faiqualcosa-relativo-al-timer() flagtimer=0; } if (flagportaB==1) { fai-qualcosa-relativo-alla-portaB() flagportaB=0; } } }
Come avete potuto vedere, il main() non richiama mai in modo esplicito la funzione di gestione degli interrupt, ma si limita ad inizializzare i registri degli interrupt, per abilitarli, e poi controlla se una delle variabili “flag” ha cambiato valore, ed in tal caso agisce di conseguenza